SpringBoot使用@EnableAsync @Async注解异步发送邮件

in java with 2 comment

pom包配置

<dependency>
   <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

spring boot 配置文件

以下是QQ邮箱的配置,其他邮箱修改对应的host、username、password即可。

spring:
  mail:
    default-encoding: UTF-8
    # 指定SMTP server使用的协议,默认为: smtp
    protocol: smtp
    # 指定SMTP server host.
    host: smtp.qq.com
    port: 465
    # 指定SMTP server的用户名.
    username: xxx@qq.com
    # 指定SMTP server登录密码:
    password: xxx
    # 指定是否在启动时测试邮件服务器连接,默认为false
    test-connection: true
    properties:
      mail.smtp.auth: true
      # 腾讯企业邮箱 下两个配置必须!!!
      mail.smtp.ssl.enable: true
      mail.smtp.socketFactory.class: javax.net.ssl.SSLSocketFactory
      mail.smtp.socketFactory.port: 465
      mail.smtp.starttls.enable: true
      mail.smtp.starttls.required: true
      mail.smtp.connectiontimeout: 60000
      mail.smtp.timeout: 60000
      mail.smtp.writetimeout: 60000

自定义线程池的配置类,并在类上添加@EnableAsync注解

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 线程初始化
 *
 * @Author: mtr
 * @Date: 2020/5/6 13:45
 */
@Slf4j
@Configuration
@EnableAsync
public class EnableAsyncConfig {

    @Bean
    public Executor taskExecutor() {
        log.info("start taskExecutor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(10);
        //配置最大线程数
        executor.setMaxPoolSize(20);
        executor.setKeepAliveSeconds(60);
        //配置队列大小
        executor.setQueueCapacity(99999);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("async-service-");

        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //执行初始化
        executor.initialize();
        return executor;
    }

}

在需要异步的方法上使用@Async("线程池名称") 该方法就可以异步执行了。线程池名称是上面配置类中方法的名称,即taskExecutor@Async默认是taskExecutor所有这里没有写,如果方法名不同,则必须写。

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * 邮件发送服务
 *
 * @Author: mtr
 * @Date: 2020/5/6 14:45
 */
@Slf4j
@Component
public class MailService {

    @Value("${spring.mail.username}")
    private String from;

    @Autowired
    private JavaMailSender mailSender;

    /**
     * 功能描述:
     *  异步发送邮件
     * @Author mtr
     * @date 2020/5/6 14:46
     * @param email 收件人
     * @param title 邮件标题
     * @param content 邮件内容
     * @return void
     */
    @Async
    public void send(String email, String title, String content) {
        try {
            // new 一个简单邮件消息对象
            SimpleMailMessage message = new SimpleMailMessage();
            // 和配置文件中的的username相同,相当于发送方
            message.setFrom(from);
            // 收件人邮箱
            message.setTo(email);
            // 标题
            message.setSubject(title);
            // 正文
            message.setText(content);
            // 发送
            mailSender.send(message);
            log.info("给{}发送邮件[{}]成功", email, title);
        } catch (Exception e){
            log.error("邮件发送失败email["+ email +"],title["+ title +"]",e);
        }
    }

}