文章目录
- 1. 异步任务
- 2. 定时任务
- 3. 邮件任务
1. 异步任务
在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,使用Spring Boot中的@EnableAysnc、@Aysnc注解可以很简便的处理异步任务的调用。
例如在Spring Boot中写一个Service类,其中包含一个方法在睡眠3秒后输出"hello world…"。为了使它作为一个异步方法执行,在方法上使用@Async注解
@Service
public class AsyncService {
@Async
public void hello(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hello world...");
}
}
编写一个controller来访问这个异步方法:
@RestController
public class AsyncController {
@Autowired
AsyncService asyncService;
@GetMapping("/hello")
public String hello(){
asyncService.hello();
return "success";
}
}
并在主程序类上使用@EnableAsync注解开启对异步的支持。
@EnableAsync
@SpringBootApplication
public class DyliangApplication {
public static void main(String[] args) {
SpringApplication.run(DyliangApplication.class, args);
}
}
执行主程序,并通过localhost:8080/hello
发送请求,可以看到在3秒后控制台才打印hello world…。
2. 定时任务
在项目中通常会需要在某个固定的时间或是时间段执行某项操作,如分析日志信息等。Spring Boot使用@EnableScheduling、@Scheduled这两个注解就可以实现定时任务。
重新编写一个service类,通过通过调用hello()
来输出hello world…,为了表示它执行的是定时任务,需要在方法上添加注解@Scheduled
@Service
public class ScheduledService {
@Scheduled(cron = "0-4 * * * * MON-FRI")
public void hello(){
System.out.println("hello world...");
}
}
其中"0-4 * * * * MON-FRI"表示在周一到周五的每分钟的前四秒都执行该标识的方法,其它秒不执行。另外cron表达式的写法还有:
字段 | 允许值 | 允许的特殊字符 |
秒 | 0-59 | ,- * / |
分 | 0-59 | ,- * / |
小时 | 0-23 | ,- * / |
日期 | 1-31 | ,- * / L W C |
月份 | 1-12 | ,- * / |
星期 | 0-7 或 SUN-SAT | ,- * / L C # |
其中特殊字符分别代表的含义为:
特殊字符 | 代表含义 |
, | 枚举,如1,2,3,4 |
- | 区间,如1-4 |
* | 任意 |
/ | 步长 |
? | 日/星期冲突匹配 |
L | 最后 |
W | 工作日 |
C | 和calendar联系后计算过的值 |
# | 星期,如4#2表示第2个星期四 |
例如:
- 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#:表示每个月的第一个周一凌晨2点到4点期间,每个整点都执行一次;
为了开启定时任务支持,还需要@EnableScheduling开启基于注解的定时任务。
@EnableAsync
@EnableScheduling
@SpringBootApplication
public class DyliangApplication {
public static void main(String[] args) {
SpringApplication.run(DyliangApplication.class, args);
}
}
执行程序可以看到在每分钟的前四秒的每一秒都会在控制台打印hello world…。
3. 邮件任务
为了使用Spring Boot中的邮件任务,首先需要引入相关的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
引入依赖后,在Spring Boot自动配置的包下找到和mail相关的类,可以看到包含如下的五个类:
- MailProperties
- MailSenderAutoConfiguration
- MailSenderJndiConfiguration
- MailSenderPropertiesConfiguration
- MailSenderValidatorAutoConfigruration
MailProperties允许通过在配置文件使用spring.mail.xxx来自定义配置类中相关的属性,如host、port、username等,其中还有一些默认设置,如编码格式为UTF-8,所使用的协议为SMTP。
另外一个重要的类就是MailSenderJndiConfiguration,它在容器中注入了一个组件JavaMailSenderImpl,通过它可以实现邮件相关的一些功能,例如setUsername()
、setPassword()
、setPort()
等。
根据配置类的描述,我们可以在application.xml中添加一些重要的配置:
spring.mail.username=xxxx@qq.com # QQ邮箱名
spring.mail.password=xkuvqcdgjtjtbfij # 授权码
spring.mail.host=smtp.qq.com # QQ邮箱服务器
spring.mail.properties.mail.smtp.ssl.enable=true # 安全控制
当不同类型的有限之间发送邮件时,并不是邮箱之间直接进行发送和接收,而是通过它们对应的邮箱服务器来实现邮件的发送和接收。因此,这里需要指定发送时的邮箱服务器地址。
Spring Boot中通过SimpleMailMessage可以发送一些简单的邮件,而通过MimeMessage可以发送比较复杂的邮件,如添加一些附件等。
- SimpleMailMessage
@SpringBootTest
class DyliangApplicationTests {
@Autowired
JavaMailSenderImpl javaMailSender;
@Test
public void testSendSimpleMessage() {
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("test");
message.setText("Hello World...");
message.setTo("目标邮箱地址");
message.setFrom("发送邮箱地址");
javaMailSender.send(message);
}
}
执行单元测试后,我们就可以在setTo()
中传入的邮箱地址指定的邮箱中找到发送的内容。
- MimeMessage
@SpringBootTest
class DyliangApplicationTests {
@Autowired
JavaMailSenderImpl javaMailSender;
@Test
public void testSendComplexMessage() throws MessagingException {
// 创建复杂的消息邮件
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setSubject("test more...");
helper.setText("<b style='color:red'>HELLO WORLD...</b>",true);
helper.setTo("18dyliang@stu.edu.cn");
helper.setFrom("1002457567@qq.com");
//上传文件
helper.addAttachment("444873.jpg", new File("C:\\Users\\dyliang\\Pictures\\444873.jpg"));
javaMailSender.send(mimeMessage);
}
}
同样的指定单元测试,可以在目标邮箱中看到发送的邮件,包含邮件的正文和的相应的附件