异步任务
背景
在我们的业务处理中,比如处理完成需要3s才能完成,但是我们需要如果要让用户等3s,则体验非常差,所以我们采用异步的方式去处理,可以通过线程池来处理 ,但是还要写线程,而springboot中已经默认提供了这种能力 ,我们只要开启即可使用。
具体使用
- 创建项目
我们只要创建一个基本的springboot项目,然后只要添加web的依赖即可。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 编写场景模拟上面背景
service层:
@Service
public class AsyncService {
public void sync(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("方法中在执行中");
}
public void async(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("方法中在执行中");
}
}
controller层:
@RestController
public class AsyncController {
@Autowired
private AsyncService asyncService;
@GetMapping("/sync")
public String sync(){
asyncService.sync();
return "处理完成";
}
@GetMapping("/async")
public String async(){
asyncService.async();
return "处理完成";
}
}
- 启动项目,测试
请求 localhost:8080/sync ,发现会转圈等待3s后才有返回值:
- 问题解决
采用异步的方式来解决这个问题。
首先在启动类上打开异步: @EnableAsync ,然后再调用的方法上添加注解 @Async
# 启动类
@SpringBootApplication
@EnableAsync
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
#方法
@Async
public void async(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("方法中在执行中");
}
然后再次请求 ocalhost:8080/async ,发现我们的方法立马就返回了。这样就是实现了异步任务。
邮件任务
背景
通过springboot提供的mail-starter来实现邮件任务。
具体使用
- 添加依赖
<!--mail-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
- 配置文件
spring.mail.username=xxxx@qq.com
spring.mail.password=你的qq授权码
spring.mail.host=smtp.qq.com
# qq需要配置ssl
spring.mail.properties.mail.smtp.ssl.enable=true
获取授权码:在QQ邮箱中的设置->账户->开启pop3和smtp服务.
- Spring单元测试
@Autowired
JavaMailSenderImpl mailSender;
@Test
public void contextLoads() {
//邮件设置1:一个简单的邮件
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("通知-明天来上班");
message.setText("今晚7:30开会");
message.setTo("xxx@qq.com");
message.setFrom("xxx@qq.com");
mailSender.send(message);
}
@Test
public void contextLoads2() throws MessagingException {
//邮件设置2:一个复杂的邮件
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setSubject("通知-明天吃饭");
helper.setText("<b style='color:red'>今天 7:30来开会</b>",true);
//发送附件
helper.addAttachment("1.jpg",new File(""));
helper.addAttachment("2.jpg",new File(""));
helper.setTo("xxx@qq.com");
helper.setFrom("xxx@qq.com");
mailSender.send(mimeMessage);
定时任务
背景
在指定的时间或者场景下执行某些代码。
相关联的类和注解
TaskScheduler : 任务调度者
TaskExecutor :任务执行者
@EnableScheduling : 开启定时功能的注解
@schedule :什么时候执行
具体使用
只要导入了springboot的web依赖,就默认给我们导入了这个功能,不需要我们再去导入。
关于cron表达式的可以参考我的另一篇文章: spring中@schedule注解的使用
- 在启动类上添加注解 @EnableScheduling
@SpringBootApplication
@EnableAsync
@EnableScheduling
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
- service层编写方法
@Service
public class ScheduleService {
public void testSchedule(){
System.out.println("任务被执行了");
}
}
- 添加注解 @Scheduled
其中的cron表达式可以参考我的另一篇博客: spring中@schedule注解的使用 ,也就是固定的时间周期去执行
@Service
public class ScheduleService {
/**
* 每隔10s执行一次
*/
@Scheduled(cron = "0/10 * * * * ?")
public void testSchedule(){
System.out.println(LocalDateTime.now()+"任务被执行了");
}
}
- 结果
每隔10s执行一次,验证了准确性。