Springboot 配置异步执行发送邮件

358 阅读1分钟

在一个单子项目中使用到了发送邮件业务,因为发送邮件业务是网络请求,会有所延迟,可能达到10ms才请求成功,在前端页面,我们不可能让前端去等待10秒后才告诉执行结果。

其实发送邮件只要配置正确,都是可以执行的,所以无需返回结果。所以我们把发送邮件的相关代码丢到异步中去执行即可。

这样的话,用户一发送验证码,我们判断邮箱号是否正确与否,就可以告诉它发送成功。然后又异步线程池在后台去完成发送邮件的一个操作即可。

  1. 首先配置线程池
@Configuration
public class ThreadPoolConfig {

    @Bean("AsyncTaskExecutor")
    public AsyncTaskExecutor taskExecutor(){
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(4);
        executor.setQueueCapacity(32);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("task-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}
  1. 配置Service层
@Scope("prototype")
@Service
public class AsyncSendEmailTaskImpl implements IAsyncSendEmailTaskService {

在Sercice实现类上加 @Scope("prototype") 代表此service层是多例模式,这样的话才能用到我们的线程池。

  1. 配置Service层实现方法
@Override
@Async
public void sendCode(String email) {
  todo...
}

这里需要注意的是,要在方法上加在@Async注解才会生效。

4.Controller调用

@Scope("prototype")
@Api(tags = "基础-发送邮件")
@RestController
@RequestMapping
public class SendEmailController {

    @Autowired
    private IAsyncSendEmailTaskService asyncSendEmailTaskService;


    @GetMapping("/sendCode")
    @ApiOperation("发送验证码")
    public ApiResult sendCode(@RequestParam String email){
        asyncSendEmailTaskService.sendCode(email);
        return ApiResult.ok("邮件发送成功,10分钟内有效");
    }

}

结果对比:

使用单例模式、同步方法耗时:21s

image.png

使用多例模式、异步方法耗时:10ms image.png

在计算量大的、耗时久的,不需要立马告诉用户结果的,都可以丢在线程池中去执行,这样增加用户的体验感。