邮件自动发送是各种系统不可或缺的功能,例如办公系统会在出现特定状况时向人事部门或技术部门发送告警信息。
Spring框架提供了JavaMailSender接口可以进行简单的邮件发送,我们可以很轻易的使用。此外,邮件发送还需要考虑是否采用异步的方式,如果邮件发送功能是在用户触发某个操作后发生的,使用同步的方式串行执行发邮任务势必会导致业务的阻塞,我们可以使用Spring提供的ThreadPool来实现异步多线程。
二、配置异步任务
- 首先在SpringBootApplication主类下增加注解@EnableAsync,以在该项目启用异步功能创建一个异步多线程的配置类,名字随意,但必须加上@Configuration注解以将该类作为配置类注册到Spring中在该配置类下声明一个执行器方法,名字随意,但返回值必须为AsyncTaskExecutor,且应加上@Bean("AsyncTaskExecutor")注解以将该方法返回的对象注册到Spring中进行多线程任务的配置,其中核心线程数推荐设为CPU内核数,最大线程数为核心线程数的两倍:
@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;
}
}
三、配置邮件功能
- 首先在Maven的pom.xml下增加JavaMailSender的相关依赖:
org.springframework.boot spring-boot-starter-mail
- 在SpringBoot的yml配置文件下,增加SMTP服务器的相关信息,以下使用阿里云个人邮箱作为示例:
spring:
...
mail:
default-encoding: UTF-8
host: smtp.aliyun.com
username: xxxxxx@aliyun.com
password: xxxxxx
在邮箱设置页中修改反垃圾级别,以避免系统发送的邮件被视作垃圾邮件
在配置文件下的自定义信息区域,增加系统级邮箱及需要接收邮件的相关部门邮箱:
xxx:
...
email:
system: xxxxxx@aliyun.com
hr: xxxxxxx@qq.com
...
- 创建一个邮件发送的任务类,名字随意,但必须实现Serializable接口,并且开启了@Component + @Scope("prototype")(异步任务必须使用多例模式),具体内容如下:
@Component
@Scope("prototype")
public class EmailTask implements Serializable {
@Autowired
private JavaMailSender javaMailSender;
@Value("${xxx.email.system}")
private String mailbox;
@Async
public void sendAsync(SimpleMailMessage message) {
message.setFrom(mailbox);
message.setCc(mailbox); //将邮件向自己抄送,能够降低被当作垃圾邮件的概览,可以省略
javaMailSender.send(message);
}
}
- 修改需要使用邮件功能的业务类为多例模式,并将相关收件人信息注入,使用封装好的邮件任务类执行任务:
@Service
@Scope("prototype")
public class XXXXXServiceImpl implements XXXXXService {
...
@Value("${xxx.email.hr}")
private String hrEmail;
@Autowired
private EmailTask emailTask;
...
public void xxx(xx){
...
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(hrEmail);
message.setSubject("标题内容xxx");
message.setText("正文内容xxx");
emailTask.sendAsync(message);
...
}
}
至此就完成了所有的操作,再次强调:涉及异步任务的类不得以singleton模式运行,应再三检查是否改成了prototype模式,不然会出问题!



