SpringBoot整合Quartz及異步調(diào)用的案例
前言
Quartz是一個(gè)完全由java編寫的開源作業(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)入依賴
<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)類
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")//開啟異步執(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)類
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)類開啟異步

整體目錄結(jié)構(gòu)如下:

測(cè)試:
運(yùn)行項(xiàng)目,訪問controller

訪問controller時(shí),頁面直接出現(xiàn)返回值,控制臺(tái)過了兩秒打印文字,證明異步執(zhí)行成功!

二、測(cè)試定時(shí)任務(wù)
1.導(dǎo)入依賴
<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.編寫測(cè)試類,開啟掃描定時(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ù)類
@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è)功能類似于通過郵箱找回密碼類似,需要我們進(jìn)行授權(quán)碼操作
1.郵箱開啟IMAP服務(wù)
登陸QQ郵箱,找到帳戶,下拉

看到如下圖:

我這里已經(jīng)開啟了,按照步驟操作,會(huì)有一個(gè)授權(quán)碼,保存好下邊步驟要用,此處不再演示
2.導(dǎo)入依賴
<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郵箱的客戶端授權(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() {
// 用戶名、密碼
String userName = props.getProperty("mail.user");
String password = props.getProperty("mail.password");
return new PasswordAuthentication(userName, password);
}
};
// 使用環(huán)境屬性和授權(quán)信息,創(chuàng)建郵件會(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è)試郵件,無需回復(fù)。", "測(cè)試郵件隨機(jī)生成的驗(yàn)證碼是:" + getValidateCode(6));
System.out.println("發(fā)送成功");
}
}
4.編寫郵件發(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.開啟異步和定時(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//開啟異步
@EnableScheduling//開啟定時(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ù)庫存儲(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開啟異步調(diào)用方法
相關(guān)文章
java遞歸實(shí)現(xiàn)樹形結(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)樹形結(jié)構(gòu)數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2023-04-04
Java 14 發(fā)布了,你還會(huì)使用Lombok?
2020年3月17日發(fā)布,Java正式發(fā)布了JDK 14 ,目前已經(jīng)可以開放下載。在JDK 14中,共有16個(gè)新特性,本文主要來介紹其中的一個(gè)特性:JEP 359: Records,需要的朋友可以參考下2020-04-04
解決SpringBoot項(xiàng)目在啟動(dòng)后自動(dòng)關(guān)閉的問題
今天搭建了一個(gè)SpringBoot項(xiàng)目,但是在啟動(dòng)之后就自行關(guān)閉了,下面通過本文給大家介紹SpringBoot項(xiàng)目在啟動(dòng)后自動(dòng)關(guān)閉問題及解決方法,需要的朋友可以參考下2023-08-08
SpringMVC實(shí)現(xiàn)注解式權(quán)限驗(yàn)證的實(shí)例
本篇文章主要介紹了SpringMVC實(shí)現(xiàn)注解式權(quán)限驗(yàn)證的實(shí)例,可以使用Spring MVC中的action攔截器來實(shí)現(xiàn),具有一定的參考價(jià)值,有興趣的可以了解下。2017-02-02
java 實(shí)現(xiàn)定時(shí)的方法及實(shí)例代碼
這篇文章主要介紹了java 定時(shí)任務(wù)詳細(xì)介紹及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03

