异步任务、定时任务、邮件任务
异步任务
先模拟一个场景,现在我有一个AsyncService和一个AsyncController:
1 2 3 4 5 6 7 8 9 10 11
| @Service public class AsyncService { public void hello(){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("处理数据中。。。"); } }
|
1 2 3 4 5 6 7 8 9 10
| @RestController public class AsyncController { @Autowired AsyncService asyncService; @RequestMapping("/hello") public String hello(){ asyncService.hello(); return "success"; } }
|
运行该应用并发起请求,在阻塞了三秒之后,控制台打印了“处理数据中。。。”与此同时收到success响应。
上面是个“同步调用”的例子,由于Controller中的hello方法和Service中的hello方法没有必须的依赖关系,所以我们不想让success响应去等待被阻塞的hello方法,那么我们就要让其“异步调用”。在SpringBoot应用中进行异步处理是相对简单的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| @EnableAsync @SpringBootApplication public class TaskTestApplication { public static void main(String[] args) { SpringApplication.run(TaskTestApplication.class, args); } }
@Service public class AsyncService { @Async public void hello(){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("处理数据中。。。"); } }
|
重新启动应用并请求,此时success立刻就响应了,经过短暂等待之后控制台上才打印出”处理数据中。。。”,说明现在已经成功进行了”异步调用”了。
*注: *
- @Async所修饰的函数不要定义为static类型,这样异步调用不会生效。
- 此注解可以用在方法上,也可以用在类上(如果用在类上,这个类中的所有的方法就是异步的)。
- 如果需要“异步回调”,可以使用“Future<T>”来返回异步调用的结果。
定时任务
项目开发中经常需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息。Spring为我们提供了异步执行任务调度的方式,提供TaskExecutor、TaskScheduler接口。
定时任务和上文的异步任务一样便于使用只需要在:启动类上标注@EnableScheduling开启定时任务注解,在需要定时的方方法上标注@Scheduled并写上cron表达式即可。
cron表达式的规则并不复杂,该表达式一共需要六位,每位之间用“空格”隔开,从前往后分别表示“秒,分,小时,日,月,星期”,具体可填写的值见下表:
举几个例子:
- “0 0 12 * * ?” 每天中午12点触发
- “0 15 10 ? * *” 每天上午10:15触发
- “0 15 10 * * ?” 每天上午10:15触发
- “0 15 10 * * ? *” 每天上午10:15触发
- “0 15 10 * * ? 2005” 2005年的每天上午10:15触发
- “0 * 14 * * ?” 在每天下午2点到下午2:59期间的每1分钟触发
- “0 0/5 14 * * ?” 在每天下午2点到下午2:55期间的每5分钟触发
- “0 0/5 14,18 * * ?” 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
- “0 0-5 14 * * ?” 在每天下午2点到下午2:05期间的每1分钟触发
- “0 10,44 14 ? 3 WED” 每年三月的星期三的下午2:10和2:44触发
- “0 15 10 ? * MON-FRI” 周一至周五的上午10:15触发
- “0 15 10 15 * ?” 每月15日上午10:15触发
- “0 15 10 L * ?” 每月最后一日的上午10:15触发
- “0 15 10 ? * 6L” 每月的最后一个星期五上午10:15触发
- “0 15 10 ? * 6L 2002-2005” 2002年至2005年的每月的最后一个星期五上午10:15触发
- “0 15 10 ? * 6#3” 每月的第三个星期五上午10:15触发
1 2 3 4 5 6 7 8
| @EnableScheduling @EnableAsync @SpringBootApplication public class TaskTestApplication { public static void main(String[] args) { SpringApplication.run(TaskTestApplication.class, args); } }
|
1 2 3 4 5 6 7 8
| @Service public class ScheduleService {
@Scheduled(cron = "1-30 * * * * *") public void demo(){ System.out.println("demo...."); } }
|
@Scheduled注解有多个属性:
@Scheduled(fixedRate = 5000)
:上一次开始执行时间点之后5秒再执行
@Scheduled(fixedDelay = 5000)
:上一次执行完毕时间点之后5秒再执行
@Scheduled(initialDelay=1000, fixedRate=5000)
:第一次延迟1秒后执行,之后按fixedRate的规则每5秒执行一次
@Scheduled(cron="*/5 * * * * *")
:通过cron表达式定义规则
邮件任务
既然是邮件任务,那么必须要引入邮件发送的依赖和相关配置:
1 2 3 4 5 6
| <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-mail --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> <version>2.2.0.RELEASE</version> </dependency>
|
1 2 3 4 5 6 7 8
| spring.mail.username=577373789@qq.com
spring.mail.password=xzodfhcfmzaebbfi
spring.mail.host=smtp.qq.com
spring.mail.properties.mail.smtp.ssl.enable=true
|
测试一下是否可以发送简单邮件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Autowired JavaMailSenderImpl mailSender;
@Test void contextLoads() { SimpleMailMessage simpleMailMessage=new SimpleMailMessage(); simpleMailMessage.setSubject("lmh"); simpleMailMessage.setText("111111111"); simpleMailMessage.setTo("2818553826@qq.com"); simpleMailMessage.setFrom("577373789@qq.com"); mailSender.send(simpleMailMessage); }
|
运行后发现目标邮箱中收到了该邮件,接下来测试发送一个稍微复杂的邮件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Autowired JavaMailSenderImpl mailSender; @Test public void test02() throws Exception { MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper=new MimeMessageHelper(message,true); helper.setSubject("lmh"); helper.setText("<font color=red>111111111</font>",true); helper.setTo("2818553826@qq.com"); helper.setFrom("577373789@qq.com"); helper.addAttachment("图片1",new File("E:\\images\\83394.jpg")); helper.addAttachment("图片2",new File("E:\\images\\83395.jpg")); mailSender.send(message); }
|
也没什么问题成功接收到邮件,邮件内容为红色字体,并且有两个附件。