SpringBoot专题学习Part29:SpringBoot的Async异步任务、Scheduled定时任务、mail邮件发送任务

一、Async异步任务

在Java应用中绝大多数情况下默认都是通过同步的方式来实现交互处理的
但在处理与第三方系统交互的时候 容易造成响应迟缓的情况
可以使用多线程来完成此类任务 但其实 在Spring 3.x之后 已经内置了@Async注解来完美解决该问题

首先来模拟一个同步任务响应迟缓的场景 以供比较:
Service:

@Service
public class AsyncService {

    public void hello()
    {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Hello");
    }
}

Controller:

@RestController
public class AsyncController {

    @Autowired
    AsyncService asyncService;

    @GetMapping("/hello")
    public String hello()
    {
        asyncService.hello();
        return "success";
    }
}

此时 若访问/hello 则需要先等待两秒才可在页面显示出"success"结果 控制台打印"Hello"字样

开启异步任务:

在主程序类上添加@EnableAsync注解来开启异步注解功能:

@SpringBootApplication
@EnableAsync // 开启异步注解功能
public class SpringbootTaskApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootTaskApplication.class, args);
    }
}

然后 给要进行异步任务的方法上添加@Async注解即可:
添加该注解之后 Spring就会自动开启一个线程池进行调用

@Service
public class AsyncService {

    // 用@Async注解来说明这是一个异步方法
    @Async
    public void hello()
    {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Hello");
    }
}

此时 若访问/hello 直接可在页面显示出"success"结果 然后等待两秒后在控制台打印"Hello"字样 实现了异步


二、定时任务

在项目开发中经常需要执行一些定时的任务
例如 在每天凌晨时候分析一次前一天的日志信息
Spring提供了异步执行任务调度的方式 提供了两个注解:@EnableScheduling@Scheduled

定时任务使用cron表达式来指定定时的时间

cron表达式:

SpringBoot专题学习Part29:SpringBoot的Async异步任务、Scheduled定时任务、mail邮件发送任务
星期可以用英文前三位 或是数字
用数字的时候 1-6代表周一到周六 0和7都可代表周日
SpringBoot专题学习Part29:SpringBoot的Async异步任务、Scheduled定时任务、mail邮件发送任务
枚举
例:0,1,2,3,4 * * * * MON-SAT
意为:周一到周六无论什么时候 每当处在0,1,2,3,4秒时 运行一次

区间
例:0-4 * * * * MON-SAT
意为:周一到周六无论什么时候 每当处在0,1,2,3,4秒时 运行一次

步长
指定每隔多长时间执行一次
例:0/4 * * * * MON-SAT
意为:周一到周六无论什么时候 从0秒开始启动 每隔4秒 运行一次

?问号
用于日和星期的冲突匹配
例:0 15 12 * 1 MON 这里的和MON起了冲突 因为代表每天 而MON代表周一 并不是每天都是周一 会起冲突
因此应改为0 15 12 ? 1 MON 使用问号来进行冲突匹配

LLast
WWorkday
CCalendar

使用:

在主程序类上添加@EnableScheduling注解来开启基于注解的定时任务功能:

@SpringBootApplication
@EnableScheduling // 开启基于注解的定时任务
public class SpringbootTaskApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootTaskApplication.class, args);
    }
}

然后 给要进行异步任务的方法上添加@Scheduled注解即可:
表达式共有六位 每位之间用空格进行分隔
格式:second(秒) minute(分) hour(时) day of month(日) month(月) day of week(周几)
例:0 * * * * MON-FRI 代表周一到周五 每分钟启动一次

@Scheduled(cron = "0 * * * * MON-SAT")
public void hello()
{
    System.out.println("Hello");
}

部分cron表达式案例:

  • 0 0/5 14,18 * * ?:每天14点整合18点整 每隔5分钟执行一次
  • 0 15 10 ? * 1-6:每个月周一到周六的10:15分执行一次
  • 0 0 2 ? * 6L:每个月的最后一个周六的凌晨2点执行一次
  • 0 0 2 LW * ?:每个月的最后一个工作日的凌晨2点执行一次
  • 0 0 2-4 ? * 1#1:每个月的第一个周一的凌晨2点到4点这期间 每个整点执行一次(会执行三次:分别是2点 3点 4点执行)

三、邮件任务

邮件发送的流程是这样的:
例如 一个qq邮箱要发送到163邮箱
发邮件的时候 并不是两个邮箱地址直接交互的
而是发送者(qq邮箱)要先用账号密码登录qq邮箱服务器
之后以此账户为名 发送邮件给接收者(163邮箱)
发送的时候是qq邮箱服务器发送邮件给163邮箱服务器
然后接收者从163邮箱服务器获取邮件

邮件发送需要spring-boot-starter-mail

为此 首先 引入依赖:

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

然后 进行配置:

为安全起见 配置的password并不是真实的密码 而是授权码
SpringBoot专题学习Part29:SpringBoot的Async异步任务、Scheduled定时任务、mail邮件发送任务
(在邮箱的设置页面中获取授权码)

# 配置发送者的邮箱用户名
spring.mail.username=1111111111@qq.com
# 配置授权码 并不是真实的密码
spring.mail.password=fcddfhqwzksxjhjg
# 配置SMTP服务器地址
spring.mail.host=smtp.qq.com
# 开启使用SSL安全连接
spring.mail.properties.mail.smtp.ssl.enable=true

ps:这个使用SSL安全连接貌似qq邮箱不加也能正常收发
但部分邮箱收发时有可能会报错

最后 就是发送邮件了

首先 注入JavaMailSenderImpl:

@Autowired
JavaMailSenderImpl javaMailSender;

发送简单邮件:

// 创建一个简单邮件信息
SimpleMailMessage simpleMailMessage=new SimpleMailMessage();
// 邮件信息设置
// 设置标题
simpleMailMessage.setSubject("【xx网】恭喜!注册成功!");
// 设置内容
simpleMailMessage.setText("您在xx网刚刚注册了一个账户,接下来您可以尽情使用了。");
// 设置发送目的地邮箱地址
simpleMailMessage.setTo("2222222222@qq.com");
// 设置发送者邮箱地址
simpleMailMessage.setFrom("1111111111@qq.com");
// 发送邮件
javaMailSender.send(simpleMailMessage);

SpringBoot专题学习Part29:SpringBoot的Async异步任务、Scheduled定时任务、mail邮件发送任务
SpringBoot专题学习Part29:SpringBoot的Async异步任务、Scheduled定时任务、mail邮件发送任务
发送成功


发送复杂邮件:
复杂邮件可以带有HTML文本和附件

// 创建一个复杂邮件
MimeMessage mimeMessage = javaMailSender.createMimeMessage();

// 使用MimeMessageHelper 其构造方法传入true代表允许上传文件
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);

// 邮件信息设置
// 设置标题
mimeMessageHelper.setSubject("【xx网】恭喜!注册成功!");
// 设置内容 可以带上HTML样式 其构造方法传入true代表开启识别HTML标签
mimeMessageHelper.setText("<b style='color:aqua'>您在xx网刚刚注册了一个账户,接下来您可以尽情使用了。</b>",true);
// 设置发送目的地邮箱地址
mimeMessageHelper.setTo("2222222222@qq.com");
// 设置发送者邮箱地址
mimeMessageHelper.setFrom("1111111111@qq.com");
// 上传附件 addAttachment(文件名,文件(可以是File或流之类的))
mimeMessageHelper.addAttachment("1.png",new File("F:\\IdeaProjects\\filetest\\img.png"));
mimeMessageHelper.addAttachment("2.jpg",new File("F:\\IdeaProjects\\filetest\\img2.jpg"));

// 发送邮件
javaMailSender.send(mimeMessage);

SpringBoot专题学习Part29:SpringBoot的Async异步任务、Scheduled定时任务、mail邮件发送任务
发送成功


上一篇:@Scheduled(cron = "* * * * * *") cron表达式详解


下一篇:基于@scheduled注解,实现定时任务