SpringBoot - 異步任務、定時任務(Scheduled和Quartz)、郵件任務

異步任務

在Java應用中,絕大多數情況下都是通過同步的方式來實現交互處理的;但是在處理與第三方系統交互的時候,容易造成響應遲緩的情況,之前大部分都是使用多線程來完成此類任務,其實,在Spring 3.x之後,就已經內置了@Async來完美解決這個問題。

註解使用

在SpringBoot裏,需要給啓動類添加@EnableAsync來開啓異步註解。
使用@Async異步註解:

@Service
public class AsyncService {
    @Async       // 該註解表明這是一個異步任務
    public void hello(){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("處理數據中...");
    }
}

定時任務

一、@Scheduled

項目開發中經常需要執行一些定時任務,比如需要在每天凌晨時候,分析一次前一天的日誌信息,統計前一天的商品銷量等。Spring爲我們提供了異步執行任務調度的方式,提供TaskExecutorTaskScheduler接口。
要使用同步任務,首先需要了解SpringTask以及Cron表達式
cron表達式cron表達式

註解使用

在SpringBoot裏,需要給啓動類添加@EnableScheduling來開啓定時任務註解。
使用@Scheduled定時任務註解:

@Service
public class ScheduleService {
    /**
     * Cron表達式
     */
    @Scheduled(cron = "0/4 * * * * MON-SAT")  // 每4秒執行一次
    public void hello(){
        System.out.println("hello...");
    }
    
    /**
     * initialDelay:首次執行任務的延遲
     * fixedRate:當前任務開始執行2000ms之後開啓另一個定時任務
     */
    @Scheduled(initialDelay = 1000,fixedRate = 2000)
    public void world(){
   		System.out.println("world...");
    }
   
    /**
     * fixedDelay:當前任務執行結束1000ms之後開啓另一個任務
     */
    @Sheduled(fixedDelay = 1000)
    public void test(){
    	System.out.println("text...");
    }
}

二、Quartz

Quartz 是一個功能豐富的開源作業調度庫,它由 Java 寫成,可以集成在任何 Java 應用程序中,
包括 Java SE 和 Java EE 等。使用 Quartz 可以創建簡單或者複雜的執行計劃,它支持數據庫、集羣、插件以及郵件,並且支持 cron 表達式,具有極高的靈活性。

1、引入依賴
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2、創建兩個任務

①普通JavaBean

@Component
public class MyFirstJob {
    public void firstJob(){
        System.out.println("MyFirstJob:firstJob-" + new Date());
    }
}

②繼承QuartzJobBean

public class MySecondJob extends QuartzJobBean{
    private String name;

    public void setName(String name){
        this.name = name;
    }

    /**
     * 任務被調用時使用
     */
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext){
        System.out.println("SecondJob:" + name + "-" + new Date());
    }
}

3、配置任務
@Configuration
public class QuartzConfig {
    /**
     * JobDetail配置方式一
     * 該方式只需要指定:實例名、方法名
     * 缺點:無法傳遞參數
     */
    @Bean
    public MethodInvokingJobDetailFactoryBean jobDetail1(){
        MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
        bean.setTargetBeanName("myFirstJob");
        bean.setTargetMethod("firstJob");
        return bean;
    }

    /**
     * JobDetail配置方式二
     * 該方式只需要指定:JobClass - 即繼承QuartzJobBean的類
     * 優點:可以通過jobDataMap傳遞參數,key與Job中的屬性名一致即可,且Job中的屬性要提供set方法
     */
    @Bean
    public JobDetailFactoryBean jobDetail2(){
        JobDetailFactoryBean bean = new JobDetailFactoryBean();
        bean.setJobClass(MySecondJob.class);
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("name","LCY");
        bean.setJobDataMap(jobDataMap);
        bean.setDurability(true);
        return bean;
    }

    /**
     * Trigger常見實現方式一
     */
    @Bean
    public SimpleTriggerFactoryBean simpleTrigger(){
        SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
        bean.setJobDetail(jobDetail1().getObject());
        // 任務循環次數
        bean.setRepeatCount(3);
        // 任務啓動延遲時間
        bean.setStartDelay(1000);
        // 任務時間間隔
        bean.setRepeatInterval(2000);
        return bean;
    }

    /**
     * Trigger常見實現方式二
     */
    @Bean
    public CronTriggerFactoryBean cronTrigger(){
        CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
        bean.setJobDetail(jobDetail2().getObject());
        // Corn表達式 - 每秒執行一次
        bean.setCronExpression("* * * * * ?");
        return bean;
    }

    /**
     * 創建SchedulerFactory
     */
    @Bean
    public SchedulerFactoryBean schedulerFactory(){
        SchedulerFactoryBean bean = new SchedulerFactoryBean();
        // 配置Trigger
        SimpleTrigger simpleTrigger = simpleTrigger().getObject();
        CronTrigger cronTrigger = cronTrigger().getObject();
        // Trigger多參數
        bean.setTriggers(simpleTrigger,cronTrigger);
        return bean;
    }

}
4、測試結果

在這裏插入圖片描述

郵件任務

郵件任務在項目中也比較常見,比如用戶註冊,我們可以通過郵件的方式確認註冊信息(驗證碼),註冊成功了,發送一些有關的信息等等。

原理

[email protected]要給[email protected]發送郵件,它們不是直接交互的。而是lcy要登錄自己的郵箱服務器,登進來以後以這個賬戶爲名,給jyqc發郵件。而給jyqc發郵件,也是qq郵箱服務器發給163郵箱服務器,163郵箱服務器再發給jyqc的。
原理圖

一、依賴引入及自動配置

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

自動配置
MailSenderAutoConfiguration
配置文件內容
MailProperties

二、開啓郵箱服務

QQ郵箱爲例,需要開啓這些服務:
郵箱服務
然後我們就可以點擊生成授權碼,在yml配置文件中使用。

三、配置yml

主要需要配置郵箱的賬號密碼(授權碼)郵箱主機地址

spring:
  mail:
    username: 123456789@qq.com    # 郵箱
    password: vzydizxcystfkwefi    # 授權碼
    host: smtp.qq.com             # QQ郵箱主機地址
    default-encoding: utf-8       # 編碼,默認UTF-8
    properties:
      mail:
        smtp:
          ssl:
            enable: true          # 安全的ssl鏈接

四、簡單郵件發送

注入JavaMailSenderImpl

@Autowired
private JavaMailSenderImpl mailSender;

@Test
public void test(){
	// 簡單郵件信息對象
	SimpleMailMessage message = new SimpleMailMessage();
	// 郵件標題
	message.setSubject("尋寶遊戲註冊驗證碼:");
	// 郵件內容
	message.setText("驗證碼:123456");
	// 郵件接收方
	message.setTo("[email protected]");
	// 郵件發送方
	message.setFrom("[email protected]");
	// 發送
	mailSender.send(message);
}

驗證碼

五、複雜郵件發送

@Test
public void test1(){
	try {
		// 複雜的消息郵件對象
		MimeMessage mimeMessage = mailSender.createMimeMessage();
		// 參數2:是否上傳文件
		MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
		// 郵件標題
		helper.setSubject("尋寶遊戲註冊");
		// 設置內容 - 參數2:是否使用html格式
		helper.setText("<em style='color:red'>註冊成功!請閱讀附件!</em>",true);
		// 郵件接收方
		helper.setTo("[email protected]");
		// 郵件發送方
		helper.setFrom("[email protected]");

		//上傳文件
		helper.addAttachment("1.jpg",new File("D:\\1.jpg"));
		helper.addAttachment("2.jpg",new File("D:\\2.jpg"));
		// 發送
		mailSender.send(mimeMessage);
	} catch (MessagingException e) {
		e.printStackTrace();
	}
}

發送成功

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章