SpringBoot整合Quartz及異步調(diào)用的案例
前言
Quartz是一個(gè)完全由java編寫(xiě)的開(kāi)源作業(yè)調(diào)度框架、它的簡(jiǎn)單易用受到業(yè)內(nèi)人士的一致好評(píng)。本篇記錄怎么用SpringBoot使用Quartz
一、異步方法調(diào)用
由于多個(gè)任務(wù)同時(shí)執(zhí)行時(shí),默認(rèn)為單線程,所以我們用異步方法調(diào)用,使其成為多線程執(zhí)行
看一個(gè)案例
1、導(dǎo)入依賴(lài)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
2、創(chuàng)建異步執(zhí)行任務(wù)線程池
這里我們使用springboot自帶的線程池
package com.lzl.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; @Configuration public class AsyncExcutorPoolConfig implements AsyncConfigurer { @Bean("asyncExecutor") @Override public Executor getAsyncExecutor() { //Spring自帶的線程池(最常用) ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); //線程:IO密集型 和 CPU密集型 //線程設(shè)置參數(shù) taskExecutor.setCorePoolSize(8);//核心線程數(shù),根據(jù)電腦的核數(shù) taskExecutor.setMaxPoolSize(16);//最大線程數(shù)一般為核心線程數(shù)的2倍 taskExecutor.setWaitForTasksToCompleteOnShutdown(true);//任務(wù)執(zhí)行完成后關(guān)閉 return taskExecutor; } }
注意注解不要少
3、創(chuàng)建業(yè)務(wù)層接口和實(shí)現(xiàn)類(lèi)
package com.lzl.Service; /** * --效率,是成功的核心關(guān)鍵-- * * @Author lzl * @Date 2023/3/7 09:42 */ public interface AsyncService { void testAsync1(); void testAsync2(); }
package com.lzl.Service.impl; import com.lzl.Service.AsyncService; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; /** * --效率,是成功的核心關(guān)鍵-- * * @Author lzl * @Date 2023/3/7 09:43 */ @Service public class AsyncImpl implements AsyncService { @Async @Override public void testAsync1() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("精準(zhǔn)是唯一重要的標(biāo)準(zhǔn)!"); } @Async("asyncExecutor")//開(kāi)啟異步執(zhí)行 @Override public void testAsync2() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("效率是成功的核心關(guān)鍵!"); } }
4、創(chuàng)建業(yè)務(wù)層接口和實(shí)現(xiàn)類(lèi)
package com.lzl.task; import com.lzl.Service.AsyncService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * --效率,是成功的核心關(guān)鍵-- * * @Author lzl * @Date 2023/3/7 09:40 */ @RestController @RequestMapping("/login") public class LoginController { @Autowired private AsyncService service; @RequestMapping("/Async1") public String testAsync1(){ service.testAsync1(); return "牛逼!"; } @RequestMapping("/Async2") public String testAsync2(){ service.testAsync2(); return "不牛逼!"; } }
在啟動(dòng)類(lèi)開(kāi)啟異步
整體目錄結(jié)構(gòu)如下:
測(cè)試:
運(yùn)行項(xiàng)目,訪問(wèn)controller
訪問(wèn)controller時(shí),頁(yè)面直接出現(xiàn)返回值,控制臺(tái)過(guò)了兩秒打印文字,證明異步執(zhí)行成功!
二、測(cè)試定時(shí)任務(wù)
1.導(dǎo)入依賴(lài)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
2.編寫(xiě)測(cè)試類(lèi),開(kāi)啟掃描定時(shí)任務(wù)
package com.lzl.task; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import java.util.Date; /** * --效率,是成功的核心關(guān)鍵-- * * @Author lzl * @Date 2023/3/7 10:42 */ //任務(wù)類(lèi) @Configuration public class Tasks { @Async @Scheduled(cron = "*/2 * * * * ?") public void task1(){ System.out.println("效率"+new Date().toLocaleString()); } @Async @Scheduled(cron = "*/1 * * * * ?") public void task2(){ System.out.println("精準(zhǔn)"+new Date().toLocaleString()); } }
3.測(cè)試
三、實(shí)現(xiàn)定時(shí)發(fā)送郵件案例
這里以QQ郵箱為例,這個(gè)功能類(lèi)似于通過(guò)郵箱找回密碼類(lèi)似,需要我們進(jìn)行授權(quán)碼操作
1.郵箱開(kāi)啟IMAP服務(wù)
登陸QQ郵箱,找到帳戶(hù),下拉
看到如下圖:
我這里已經(jīng)開(kāi)啟了,按照步驟操作,會(huì)有一個(gè)授權(quán)碼,保存好下邊步驟要用,此處不再演示
2.導(dǎo)入依賴(lài)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 郵箱 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
3.導(dǎo)入EmailUtil
package com.lzl.utils; import javax.mail.*; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.util.Properties; import java.util.Random; /** * --效率,是成功的核心關(guān)鍵-- * * @Author lzl * @Date 2023/3/7 11:44 */ public class EmailUtil { private static final String USER = "@qq.com"; // 發(fā)件人郵箱地址 private static final String PASSWORD = ""; // qq郵箱的客戶(hù)端授權(quán)碼(需要發(fā)短信獲取) /** * @param to 收件人郵箱地址 * @param text 郵件正文 * @param title 標(biāo)題 */ /* 發(fā)送驗(yàn)證信息的郵件 */ public static boolean sendMail(String to, String text, String title) { try { final Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", "smtp.qq.com"); // 發(fā)件人的賬號(hào) props.put("mail.user", USER); //發(fā)件人的密碼 props.put("mail.password", PASSWORD); // 構(gòu)建授權(quán)信息,用于進(jìn)行SMTP進(jìn)行身份驗(yàn)證 Authenticator authenticator = new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { // 用戶(hù)名、密碼 String userName = props.getProperty("mail.user"); String password = props.getProperty("mail.password"); return new PasswordAuthentication(userName, password); } }; // 使用環(huán)境屬性和授權(quán)信息,創(chuàng)建郵件會(huì)話(huà) Session mailSession = Session.getInstance(props, authenticator); // 創(chuàng)建郵件消息 MimeMessage message = new MimeMessage(mailSession); // 設(shè)置發(fā)件人 String username = props.getProperty("mail.user"); InternetAddress form = new InternetAddress(username); message.setFrom(form); // 設(shè)置收件人 InternetAddress toAddress = new InternetAddress(to); message.setRecipient(Message.RecipientType.TO, toAddress); // 設(shè)置郵件標(biāo)題 message.setSubject(title); // 設(shè)置郵件的內(nèi)容體 message.setContent(text, "text/html;charset=UTF-8"); // 發(fā)送郵件 Transport.send(message); return true; } catch (Exception e) { e.printStackTrace(); } return false; } //隨機(jī)生成num個(gè)數(shù)字驗(yàn)證碼 public static String getValidateCode(int num) { Random random = new Random(); String validateCode = ""; for (int i = 0; i < num; i++) { //0 - 9 之間 隨機(jī)生成 num 次 int result = random.nextInt(10); validateCode += result; } return validateCode; } //測(cè)試 public static void main(String[] args) throws Exception { //給指定郵箱發(fā)送郵件 EmailUtil.sendMail("729953102@qq.com", "你好,這是一封測(cè)試郵件,無(wú)需回復(fù)。", "測(cè)試郵件隨機(jī)生成的驗(yàn)證碼是:" + getValidateCode(6)); System.out.println("發(fā)送成功"); } }
4.編寫(xiě)郵件發(fā)送方法
package com.lzl.task; import com.lzl.utils.EmailUtil; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.Scheduled; /** * --效率,是成功的核心關(guān)鍵-- * * @Author lzl * @Date 2023/3/7 11:45 */ @Configuration public class TaskEmail { //指定時(shí)間進(jìn)行發(fā)送郵件 @Scheduled(cron = "10 49 11 * * ?") public void sendMail(){ EmailUtil.sendMail("自己的郵箱@qq.com", "效率,是成功的核心關(guān)鍵!", "測(cè)試郵件隨機(jī)生成的驗(yàn)證碼是:" + EmailUtil.getValidateCode(6)); } }
5.開(kāi)啟異步和定時(shí)任務(wù)
package com.lzl; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableAsync//開(kāi)啟異步 @EnableScheduling//開(kāi)啟定時(shí)任務(wù) public class QuartzStudyApplication { public static void main(String[] args) { SpringApplication.run(QuartzStudyApplication.class, args); } }
測(cè)試:
此處不再演示
總結(jié)
定時(shí)任務(wù)在很多業(yè)務(wù)場(chǎng)景中經(jīng)常會(huì)用到,好記性不如爛筆頭,本篇只是簡(jiǎn)單的記錄一下
到此這篇關(guān)于SpringBoot整合Quartz以及異步調(diào)用的文章就介紹到這了,更多相關(guān)SpringBoot整合Quartz內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot+Quartz+數(shù)據(jù)庫(kù)存儲(chǔ)的完美集合
- SpringBoot自動(dòng)配置Quartz的實(shí)現(xiàn)步驟
- SpringBoot+SpringBatch+Quartz整合定時(shí)批量任務(wù)方式
- Springboot2.x+Quartz分布式集群的實(shí)現(xiàn)
- SpringBoot集成Quartz實(shí)現(xiàn)定時(shí)任務(wù)的方法
- 淺談SpringBoot集成Quartz動(dòng)態(tài)定時(shí)任務(wù)
- Springboot整個(gè)Quartz實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)的示例代碼
- springboot+Quartz實(shí)現(xiàn)任務(wù)調(diào)度的示例代碼
- SpringBoot異步調(diào)用方法并接收返回值
- SpringBoot開(kāi)啟異步調(diào)用方法
相關(guān)文章
java遞歸實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)數(shù)據(jù)完整案例
遞歸算法的代碼比較簡(jiǎn)潔,可讀性較好;但是在實(shí)際的業(yè)務(wù)處理中會(huì)出現(xiàn)多次的重復(fù)調(diào)用,如果處理不好,很容易出現(xiàn)StackOverflowError報(bào)錯(cuò),這篇文章主要給大家介紹了關(guān)于java遞歸實(shí)現(xiàn)樹(shù)形結(jié)構(gòu)數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2023-04-04Java 14 發(fā)布了,你還會(huì)使用Lombok?
2020年3月17日發(fā)布,Java正式發(fā)布了JDK 14 ,目前已經(jīng)可以開(kāi)放下載。在JDK 14中,共有16個(gè)新特性,本文主要來(lái)介紹其中的一個(gè)特性:JEP 359: Records,需要的朋友可以參考下2020-04-04解決SpringBoot項(xiàng)目在啟動(dòng)后自動(dòng)關(guān)閉的問(wèn)題
今天搭建了一個(gè)SpringBoot項(xiàng)目,但是在啟動(dòng)之后就自行關(guān)閉了,下面通過(guò)本文給大家介紹SpringBoot項(xiàng)目在啟動(dòng)后自動(dòng)關(guān)閉問(wèn)題及解決方法,需要的朋友可以參考下2023-08-08SpringMVC實(shí)現(xiàn)注解式權(quán)限驗(yàn)證的實(shí)例
本篇文章主要介紹了SpringMVC實(shí)現(xiàn)注解式權(quán)限驗(yàn)證的實(shí)例,可以使用Spring MVC中的action攔截器來(lái)實(shí)現(xiàn),具有一定的參考價(jià)值,有興趣的可以了解下。2017-02-02java 實(shí)現(xiàn)定時(shí)的方法及實(shí)例代碼
這篇文章主要介紹了java 定時(shí)任務(wù)詳細(xì)介紹及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03