SpringBoot之非同步、定時、郵件任務

The_Beacon發表於2020-10-15

非同步任務

  1. 建立一個service包

  2. 建立一個類AsyncService

    非同步處理還是非常常用的,比如我們在網站上傳送郵件,後臺會去傳送郵件,此時前臺會造成響應不動,直到郵件傳送完畢,響應才會成功,所以我們一般會採用多執行緒的方式去處理這些任務。

    編寫方法,假裝正在處理資料,使用執行緒設定一些延時,模擬同步等待的情況;

    @Service
    public class AsyncService {
    
       public void hello(){
           try {
               Thread.sleep(3000);
          } catch (InterruptedException e) {
               e.printStackTrace();
          }
           System.out.println("業務進行中....");
      }
    }
    
  3. 編寫controller包

  4. 編寫AsyncController類

    我們去寫一個Controller測試一下

    @RestController
    public class AsyncController {
    
       @Autowired
       AsyncService asyncService;
    
       @GetMapping("/hello")
       public String hello(){
           asyncService.hello();
           return "OK";
      }
    
    }
    
  5. 訪問http://localhost:8080/hello進行測試,3秒後出現OK,這是同步等待的情況。

    問題:我們如果想讓使用者直接得到訊息,就在後臺使用多執行緒的方式進行處理即可,但是每次都需要自己手動去編寫多執行緒的實現的話,太麻煩了,我們只需要用一個簡單的辦法,在我們的方法上加一個簡單的註解即可,如下:

  6. 給hello方法新增@Async註解;

    //告訴Spring這是一個非同步方法
    @Async
    public void hello(){
       try {
           Thread.sleep(3000);
      } catch (InterruptedException e) {
           e.printStackTrace();
      }
       System.out.println("業務進行中....");
    }
    

    SpringBoot就會自己開一個執行緒池,進行呼叫!但是要讓這個註解生效,我們還需要在主程式上新增一個註解@EnableAsync ,開啟非同步註解功能;

    @EnableAsync //開啟非同步註解功能
    @SpringBootApplication
    public class SpringbootTaskApplication {
    
       public static void main(String[] args) {
           SpringApplication.run(SpringbootTaskApplication.class, args);
      }
    
    }
    

7、重啟測試,網頁瞬間響應,後臺程式碼依舊執行!(也就是3秒後控制檯輸出“業務進行中…”)

郵件任務

郵件傳送,在我們的日常開發中,也非常的多,Springboot也幫我們做了支援

  • 郵件傳送需要引入spring-boot-start-mail
  • SpringBoot 自動配置MailSenderAutoConfiguration
  • 定義MailProperties內容,配置在application.yml中
  • 自動裝配JavaMailSender
  • 測試郵件傳送

測試:

  1. 引入pom依賴

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>
    

    看它引入的依賴,可以看到 jakarta.mail

    <dependency>
        <groupId>com.sun.mail</groupId>
        <artifactId>jakarta.mail</artifactId>
        <version>1.6.5</version>
        <scope>compile</scope>
    </dependency>
    
  2. 檢視自動配置類:MailSenderAutoConfiguration

    image-20200801104504309

    這個類中存在bean,JavaMailSenderImpl

    在這裡插入圖片描述

    然後我們去看下配置檔案

    @ConfigurationProperties(prefix = "spring.mail")
    public class MailProperties {
    
    	private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
    	private String host;
    	private Integer port;
    	private String username;
    	private String password;
    	private String protocol = "smtp";
    	private Charset defaultEncoding = DEFAULT_CHARSET;
    	private Map<String, String> properties = new HashMap<>();
    	private String jndiName;
    	//set、get方法省略。。。
    }
    
    
  3. 配置檔案:

    spring.mail.username=125xxx2251@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服務

    image-20200801105503766

  4. Spring單元測試

    @Autowired
    JavaMailSenderImpl javaMailSender;
    @Test//郵件設定1:一個簡單的郵件
    void contextLoads() {
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setSubject("Hello World");
        mailMessage.setText("Content Text");
    
        mailMessage.setTo("xxxxxxxx@163.com");
        mailMessage.setFrom("125xxx2251@qq.com");
        javaMailSender.send(mailMessage);
    }
    
    @Test// 一個複雜的郵件
    void contextLoads2() throws MessagingException {
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        //組裝
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
    
        //正文
        helper.setSubject("Hello World!!");
        helper.setText("<p style='color:red'>Content Text</p>", true);
    
        //附件
        helper.addAttachment("1.jpg", new File("G:\Pictures\MAC.jpg"));
        helper.addAttachment("2.jpg", new File("G:\Pictures\MAC.jpg"));
    
        helper.setTo("xxxxxxxx@163.com");
        helper.setFrom("125xxx2251@qq.com");
    
        javaMailSender.send(mimeMessage);
    
    }
    

    在這裡插入圖片描述

檢視郵箱,郵件接收成功!

我們只需要使用Thymeleaf進行前後端結合即可開發自己網站郵件收發功能了!

定時任務

專案開發中經常需要執行一些定時任務,比如需要在每天凌晨的時候,分析一次前一天的日誌資訊,Spring為我們提供了非同步執行任務排程的方式,提供了兩個介面。

  • TaskExecutor介面(任務執行者)
  • TaskScheduler介面(任務排程者)

兩個註解:

  • @EnableScheduling——開啟定時功能的註解
  • @Scheduled——什麼時候執行

Cron表示式:

欄位允許值允許特殊字元
0-59, - * /
0-59, - * /
小時0-23, - * /
日期1-31, - * / ? L W C
月份1-12, - * /
星期0-1或SUN-SAT 0,7是SUN, - * / ? L W C
特殊字元代表含義
,列舉
-區間
*任意
/步長
?日/星期衝突匹配
L最後
W工作日
C和calendar練習後計算過的值
#星期,4#2 第二個星期三

測試步驟:

1、建立一個ScheduledService

我們裡面存在一個hello方法,他需要定時執行,怎麼處理呢?

@Service
public class ScheduledService {

    // 在一個特定的時間執行這個方法——Timer
    //cron表示式
    // 秒 分 時 日 月 周幾

    /*
        0 49 11 * * ?   每天的11點49分00秒執行
        0 0/5 11,12 * * ?   每天的11點和12點每隔五分鐘執行一次
        0 15 10 ? * 1-6     每個月的週一到週六的10點15分執行一次
        0/2 * * * * ?     每2秒執行一次
     */
    @Scheduled(cron = "0/2 * * * * ?")
    public void hello() {
        System.out.println("hello,你被執行了");
    }
}

2、這裡寫完定時任務之後,我們需要在主程式上增加@EnableScheduling 開啟定時任務功能

@EnableAsync //開啟非同步註解功能
@EnableScheduling //開啟基於註解的定時任務
@SpringBootApplication
public class SpringbootTaskApplication {

   public static void main(String[] args) {
       SpringApplication.run(SpringbootTaskApplication.class, args);
  }

}

3、我們來詳細瞭解下cron表示式;

http://www.bejson.com/othertools/cron/

4、常用的表示式

(1)0/2 * * * * ?   表示每2秒 執行任務
(1)0 0/2 * * * ?   表示每2分鐘 執行任務
(1)0 0 2 1 * ?   表示在每月的1日的凌晨2點調整任務
(2)0 15 10 ? * MON-FRI   表示週一到週五每天上午10:15執行作業
(3)0 15 10 ? 6L 2002-2006   表示2002-2006年的每個月的最後一個星期五上午10:15執行作
(4)0 0 10,14,16 * * ?   每天上午10點,下午2點,4點
(5)0 0/30 9-17 * * ?   朝九晚五工作時間內每半小時
(6)0 0 12 ? * WED   表示每個星期三中午12點
(7)0 0 12 * * ?   每天中午12點觸發
(8)0 15 10 ? * *   每天上午10:15觸發
(9)0 15 10 * * ?     每天上午10:15觸發
(10)0 15 10 * * ?   每天上午10:15觸發
(11)0 15 10 * * ? 2005   2005年的每天上午10:15觸發
(12)0 * 14 * * ?     在每天下午2點到下午2:59期間的每1分鐘觸發
(13)0 0/5 14 * * ?   在每天下午2點到下午2:55期間的每5分鐘觸發
(14)0 0/5 14,18 * * ?     在每天下午2點到2:55期間和下午6點到6:55期間的每5分鐘觸發
(15)0 0-5 14 * * ?   在每天下午2點到下午2:05期間的每1分鐘觸發
(16)0 10,44 14 ? 3 WED   每年三月的星期三的下午2:10和2:44觸發
(17)0 15 10 ? * MON-FRI   週一至週五的上午10:15觸發
(18)0 15 10 15 * ?   每月15日上午10:15觸發
(19)0 15 10 L * ?   每月最後一日的上午10:15觸發
(20)0 15 10 ? * 6L   每月的最後一個星期五上午10:15觸發
(21)0 15 10 ? * 6L 2002-2005   2002年至2005年的每月的最後一個星期五上午10:15觸發
(22)0 15 10 ? * 6#3   每月的第三個星期五上午10:15觸發

相關文章