title: springboot定时-邮件-异步
date: 2020-08-20 18:44:32
tags: [‘框架’]
介绍: 以前我们想要异步处理一个请求,还需要我们手动去创建线程池去执行,我们要开启定时任务也是很复杂的,还有发送邮件…springboot的出现让这一切变得简单,只需要简单的配置就可以实现。但是我们想要真整的了解和掌握这些技术,还是需要我们比零开始一步步的搭建,才能真的做到活学活用。
springboot异步-定时-邮件
1、定时任务
(1)了解cron表达式
定时任务在我们开发中也是比较常见的,数据定时清楚了,更新之类的,我们通过cron表达式定义定时任务的执规则。
cron表达式: 秒 分 时 日 月 星期 年
(1) :* 表示匹配该域的任意值
(2)- : 表示范围
(3)?: 只能用在DayofMonth和DayofWeek两个域。 因为日期和星期有冲突,假如我们要10号触发,肯定就不用考虑是星期几个,但是*是匹配所有,因此要用**?符号**
(4)/ : 表示开始时间,每隔多久执行一次。 例如Minutes 使用5/20,则意味着20分钟触发一次
(5)L : 表示最后,只能出现在DayofWeek和DayofMonth域
(6)W : 表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件
(7)LW : 表示在某个月最后一个工作日,即最后一个星期五
(8)# : 用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三
(9),: 表示并列,枚举的意思
在开发中我们为了避免出错,我们可以使用在线成功工具:cron在线生成工具
了解了cron表达式,我们就可以开启定时任务了。
(2)代码操作
1、在springboot的启动类上加入注解:@EnableScheduling
2、创建定时任务类
@Component //要交给spring容器管理
public class SecdulingConfig {
private static Logger logger=LoggerFactory.getLogger(SecdulingConfig.class);
@Scheduled(cron = "0/3 * * * * ? ") //定时执行方法 ,cron表达式,每3秒执行一次
public void say(){
logger.info("我来了");
}
}
3、启动程序结果打印
2020-08-21 10:48:09.001 INFO 9876 --- [boot-Scheduled1] com.dl.config.SecdulingConfig : 我来了
2020-08-21 10:48:12.001 INFO 9876 --- [boot-Scheduled1] com.dl.config.SecdulingConfig : 我来了
2020-08-21 10:48:15.002 INFO 9876 --- [boot-Scheduled1] com.dl.config.SecdulingConfig : 我来了
2020-08-21 10:48:18.001 INFO 9876 --- [boot-Scheduled1] com.dl.config.SecdulingConfig : 我来了
每3秒就会打印一次,测试通过,我们在开启一个定时任务…
@Component
public class SecdulingConfig {
private static Logger logger=LoggerFactory.getLogger(SecdulingConfig.class);
@Scheduled(cron = "0/3 * * * * ? ")
public void say(){
logger.info("定时任务1");
try{
Thread.sleep(2000); //模拟业务执行
}catch (Exception e){
e.printStackTrace();
}
}
@Scheduled(cron = "0/2 * * * * ? ")
public void say2(){
logger.info("定时任务2");
}
}
2020-08-21 11:04:12.001 INFO 10580 --- [ scheduling-1] com.dl.config.SecdulingConfig : 定时任务1
2020-08-21 11:04:14.002 INFO 10580 --- [ scheduling-1] com.dl.config.SecdulingConfig : 定时任务2
2020-08-21 11:04:15.001 INFO 10580 --- [ scheduling-1] com.dl.config.SecdulingConfig : 定时任务1
2020-08-21 11:04:17.002 INFO 10580 --- [ scheduling-1] com.dl.config.SecdulingConfig : 定时任务2
2020-08-21 11:04:18.001 INFO 10580 --- [ scheduling-1] com.dl.config.SecdulingConfig : 定时任务1
不难看出在执行这两个定时任务的时候,使用的是同一条线程,所以问题就出现了,两个定时任务之间会相互影响,导致不是在我们规定的时间执行的。
所以我们要修改定时任务的执行线程,我们使用线程池去执行定时任务,spring为我们提供了异步任务执行的接口,我们进行配置:
//用线程池去执行定时任务,在测试下成功
@Bean
public TaskScheduler taskScheduler(){
ThreadPoolTaskScheduler tts=new ThreadPoolTaskScheduler();
tts.setPoolSize(10);
tts.setThreadNamePrefix("springboot-Scheduled");
return tts;
}
2、邮件任务
随着网络的发展,邮件效验通知用户是越来越火爆。
(1)引入jar
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
(2)配置文件
spring.mail.host=smtp.qq.com
spring.mail.username=2415414232@qq.com
spring.mail.password=你的qq授权码
spring.mail.default-encoding=UTF-8
#下面的部署要用
spring.mail.port=465
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
qq授权码在qq邮箱----设置----账号-----开启smtp服务–我们就可以获取我们的qq授权码了
(3)发送邮件
//springboot已经帮我们封装好了,直接导入
@Autowired
private JavaMailSenderImpl javaMailSender;
//发送简单邮件
public String sendSimpleMail() {
try {
SimpleMailMessage smm = new SimpleMailMessage();
smm.setFrom("2415414232@qq.com"); //谁发的
smm.setTo("766027826@qq.com"); //发给谁
smm.setSubject("加油吧!"); //主题
smm.setText("点击一下吧:" + "https://dl6hg.cn");
javaMailSender.send(smm); //邮件发送
}catch (Exception e){
e.printStackTrace();
return "发送失败!";
}
return "发送成功!";
}
766027826用户就可以收到我们发送的邮件了
//发送html邮件
public String sendMimeMail() {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper mimeMessageHelper=new MimeMessageHelper(mimeMessage,true);
mimeMessageHelper.setFrom("2415414232@qq.com");
mimeMessageHelper.setTo("766027826@qq.com");
mimeMessageHelper.setSubject("这是文件"); //主体
mimeMessageHelper.setText("<h1 style='color:red'>helloWorld</h1><img src='cid:test001'/>",true); //文本内容
mimeMessageHelper.addInline("test001", new FileSystemResource(ResourceUtils.getFile("classpath:nuli2.jpg"))); //内容图片
mimeMessageHelper.addAttachment("附件",new FileSystemResource(ResourceUtils.getFile("classpath:nuli2.jpg"))); //附件
javaMailSender.send(mimeMessage); //发送邮件
} catch (Exception e) {
e.printStackTrace();
}
return "发送成功";
}
邮件发送是非常慢的,不可能让用户一直在哪里等待,所以我们要异步处理,用户点击发送邮件,我们直接返回结果给用户,另一条线程去发送邮件,通常我们要创建线程池,但是现在springboot已经给我们提供好了。
3、异步任务
(1)开启异步
@EnableAsync // 开启异步
(2)业务层修改
//我们的controller层
@RequestMapping("/aa")
public String aa() {
mailService.sendSimpleMail(); //调用业务层邮件发送方法
return "发送成功";
}
访问该衔接我们要好几秒才能看到发送成功,因为邮件发送需要很长时间,我们现在用多线程处理邮件发送,在service层方法上添加注解就可以实现异步,方便吧
@Async //异步注解
//springboot已经帮我们封装好了,直接导入
public String sendSimpleMail() {
try {
SimpleMailMessage smm = new SimpleMailMessage();
smm.setFrom("2415414232@qq.com"); //谁发的
smm.setTo("766027826@qq.com"); //发给谁
smm.setSubject("加油吧!"); //主题
smm.setText("点击一下吧:" + "https://dl6hg.cn");
javaMailSender.send(smm); //邮件发送
}catch (Exception e){
e.printStackTrace();
return "发送失败!";
}
return "发送成功!";
}
访问衔接,瞬间看到发送成功,这也是我们经常用短信登陆APP时,点击下获取验证码就看到发送成功,但是我们好久才可以正真的收到短信。