1. 程式人生 > >二十三、 SpringBoot之任務(非同步、定時、郵件)

二十三、 SpringBoot之任務(非同步、定時、郵件)

一、非同步任務

在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;
	}