二十三、 SpringBoot之任務(非同步、定時、郵件)
阿新 • • 發佈:2018-12-18
一、非同步任務
在Java應用中,絕大多數情況下都是通過同步的方式來實現互動處理的;但是在處理與第三方系統互動的時候,容易造成響應遲緩的情況,之前大部分都是使用多執行緒來完成此類任務,其實,在Spring 3.x之後,就已經內建了@Async來完美解決這個問題。
兩個註解:@EnableAysnc、@Aysnc
- Service
@Service public class AsyncService { //告訴Spring這是一個非同步方法 @Async public void hello(){ try { Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("資料處理中。。。。"); } }
- Controller
@RestController
public class AsyncController {
@Autowired
AsyncService asyncService;
@GetMapping("/hello")
public String hello(){
asyncService.hello();
return "success";
}
}
- Application
@EnableAsync //開啟非同步註解功能 @SpringBootApplication public class SpringBootTaskApplication { public static void main(String[] args) { SpringApplication.run(SpringBootTaskApplication.class, args); } }
二、定時任務
專案開發中經常需要執行一些定時任務,比如需要在每天凌晨時候,分析一次前一天的日誌資訊。Spring為我們提供了非同步執行任務排程的方式,提供 TaskExecutor 、TaskScheduler 介面。
兩個註解:@EnableScheduling、@Scheduled
- cron表示式
欄位 |
允許值 |
允許的特殊字元 |
秒 |
0-59 |
,-*/ |
分 |
0-59 |
,-*/ |
小時 |
0-23 |
,-*/ |
日期 |
1-31 |
,-*?/LWC |
月份 |
1-12 |
,-*/ |
星期 |
0-7或SUN-SAT 0,7是SUN |
,-*?/LC# |
- 特殊字元
特殊字元 |
代表含義 |
, |
列舉 |
- |
區間 |
* |
任意 |
/ |
步長 |
? |
日/星期衝突匹配 |
L |
最後 |
W |
工作日 |
C |
和calendar聯絡後計算過的值 |
# |
星期,4#2,第2個星期四 |
- service
@Service
public class ScheduledService {
/**
* 定時任務
* cron 指定定時任務的cron表示式
* second(秒),minute(分),hour(時),day of month(日),month(月),day of week(周幾)
* 0 * * * * MON-FRI (週一到週五每一分鐘整分鐘的時候執行一次)
*/
//@Scheduled(cron = "0 * * * * MON-FRI")
//@Scheduled(cron = "0,1,2,3,4 * * * * MON-FRI") //0,1,2,3,4列舉
//@Scheduled(cron = "0-4 * * * * MON-FRI") //0-4秒區間
//@Scheduled(cron = "0/4 * * * * MON-FRI") //每4秒一次
//@Scheduled(cron = "0 0/5 14,18 * * ?") //每天14點整和18點整,每隔5分鐘執行一次
//@Scheduled(cron = "0 15 10 ? * 1-6") //每個月點週一至週六10:15分執行一次
//@Scheduled(cron = "0 0 2 ? * 6L") //每個月的最後一個週六凌晨2點執行一次
//@Scheduled(cron = "0 0 2 LW * ?") //每個月的最後一個工作日凌晨兩點執行一次
@Scheduled(cron = "0 0 2-4 ? * 1#1") //每個月的第一個週一凌晨2點到4點期間每個整點都執行一次
public void hello() {
System.out.println("hello...");
}
}
- Application
@EnableScheduling //開啟基於註解的定時任務
@SpringBootApplication
public class SpringBootTaskApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootTaskApplication.class, args);
}
}
三、郵件任務
1、步驟:
- 郵件傳送需要引入spring-boot-starter-mail
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
- 定義MailProperties內容,配置在application.yml中
[email protected]
spring.mail.password=mpduxmuivewdigjf
spring.mail.host=smtp.qq.com
- 測試郵件傳送
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootTaskApplicationTests {
//注入郵件傳送器
@Autowired
JavaMailSenderImpl javaMailSender;
//測試簡單郵件
@Test
public void contextLoads() {
SimpleMailMessage message = new SimpleMailMessage();
//郵件設定
message.setSubject("通知:今晚開會");
message.setText("今晚7:30開會");
message.setTo("[email protected]");
message.setFrom("[email protected]");
javaMailSender.send(message);
}
//測試複雜郵件
@Test
public void test() throws MessagingException {
//1、建立一個複雜訊息郵件
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);//multipart 是否上傳檔案
//郵件設定
helper.setSubject("通知:今晚開會");
helper.setText("<b style='color:red'>今晚7:30開會</b>", true);
helper.setTo("[email protected]");
helper.setFrom("[email protected]");
//上傳附件
helper.addAttachment("1.jpg", new File("/Users/Amy/Downloads/1.jpg"));
helper.addAttachment("2.jpg", new File("/Users/Amy/Downloads/2.jpg"));
javaMailSender.send(message);
}
}
2、原理:
- Spring Boot 自動配置MailSenderAutoConfiguration
//郵件自動配置類
@Configuration
@ConditionalOnClass({ MimeMessage.class, MimeType.class, MailSender.class })
@ConditionalOnMissingBean(MailSender.class)
@Conditional(MailSenderCondition.class)
@EnableConfigurationProperties(MailProperties.class)
@Import({ MailSenderJndiConfiguration.class, MailSenderPropertiesConfiguration.class })
public class MailSenderAutoConfiguration {
//郵件傳送屬性
@ConfigurationProperties(prefix = "spring.mail")
public class MailProperties {
- 自動裝配JavaMailSender
@Configuration
@ConditionalOnClass(Session.class)
@ConditionalOnProperty(prefix = "spring.mail", name = "jndi-name")
@ConditionalOnJndi
class MailSenderJndiConfiguration {
private final MailProperties properties;
MailSenderJndiConfiguration(MailProperties properties) {
this.properties = properties;
}
@Bean //傳送郵件的元件
public JavaMailSenderImpl mailSender(Session session) {
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setDefaultEncoding(this.properties.getDefaultEncoding().name());
sender.setSession(session);
return sender;
}