1.1 介紹
Spring Task 是Spring框架提供的任務(wù)調(diào)度工具,可以按照約定的時(shí)間自動(dòng)執(zhí)行某個(gè)代碼邏輯。
-
定位:定時(shí)任務(wù)框架
-
作用:定時(shí)自動(dòng)執(zhí)行某段Java代碼
-
應(yīng)用場(chǎng)景:
1). 信用卡每月還款提醒
2). 銀行貸款每月還款提醒
3). 火車票售票系統(tǒng)處理未支付訂單
強(qiáng)調(diào):只要是需要定時(shí)處理的場(chǎng)景都可以使用Spring Task
1.2 cron表達(dá)式
cron表達(dá)式其實(shí)就是一個(gè)字符串,通過cron表達(dá)式可以定義任務(wù)觸發(fā)的時(shí)間
構(gòu)成規(guī)則:分為6或7個(gè)域,由空格分隔開,每個(gè)域代表一個(gè)含義
每個(gè)域的含義分別為:秒、分鐘、小時(shí)、日、月、周、年(可選)
舉例:
2022年10月12日上午9點(diǎn)整 對(duì)應(yīng)的cron表達(dá)式為:0 0 9 12 10 ? 2022
說明:一般日和周的值不同時(shí)設(shè)置,其中一個(gè)設(shè)置,另一個(gè)用?表示。
比如:描述2月份的最后一天,最后一天具體是幾號(hào)呢?可能是28號(hào),也有可能是29號(hào),所以就不能寫具體數(shù)字。
為了描述這些信息,提供一些特殊的字符。這些具體的細(xì)節(jié),我們就不用自己去手寫,因?yàn)檫@個(gè)cron表達(dá)式,它其實(shí)有在線生成器。
cron表達(dá)式在線生成器:在線Cron表達(dá)式生成器
可以直接在這個(gè)網(wǎng)站上面,只要根據(jù)自己的要求去生成corn表達(dá)式即可。所以一般就不用自己去編寫這個(gè)表達(dá)式。
通配符:
* 表示所有值;
? 表示未說明的值,即不關(guān)心它為何值;
- 表示一個(gè)指定的范圍;
, 表示附加一個(gè)可能值;
/ 符號(hào)前表示開始時(shí)間,符號(hào)后表示每次遞增的值;
cron表達(dá)式案例:
*/5 * * * * ? 每隔5秒執(zhí)行一次
0 */1 * * * ? 每隔1分鐘執(zhí)行一次
0 0 5-15 * * ? 每天5-15點(diǎn)整點(diǎn)觸發(fā)
0 0/3 * * * ? 每三分鐘觸發(fā)一次
0 0-5 14 * * ? 在每天下午2點(diǎn)到下午2:05期間的每1分鐘觸發(fā)
0 0/5 14 * * ? 在每天下午2點(diǎn)到下午2:55期間的每5分鐘觸發(fā)
0 0/5 14,18 * * ? 在每天下午2點(diǎn)到2:55期間和下午6點(diǎn)到6:55期間的每5分鐘觸發(fā)
0 0/30 9-17 * * ? 朝九晚五工作時(shí)間內(nèi)每半小時(shí)
0 0 10,14,16 * * ? 每天上午10點(diǎn),下午2點(diǎn),4點(diǎn)
1.3 入門案例
1.3.1 Spring Task使用步驟
1). 導(dǎo)入maven坐標(biāo) spring-context
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
2). 啟動(dòng)類添加注解 @EnableScheduling 開啟任務(wù)調(diào)度
3). 自定義定時(shí)任務(wù)類
1.3.2 代碼開發(fā)(例子*)
編寫定時(shí)任務(wù)類:
進(jìn)入xxx-server模塊中
自定義定時(shí)任務(wù)類MyTask
package com.xxx.task;
?
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
?
import java.util.Date;
?
/**
* 自定義定時(shí)任務(wù)類
*/
@Component
@Slf4j
public class MyTask {
?
? ?/**
? ? * 定時(shí)任務(wù) 每隔5秒觸發(fā)一次
? ? */
? ?@Scheduled(cron = "0/5 * * * * ?")
? ?public void executeTask(){
? ? ? ?log.info("定時(shí)任務(wù)開始執(zhí)行:{}",new Date());
? }
}
開啟任務(wù)調(diào)度:
啟動(dòng)類添加注解 @EnableScheduling
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
?
@SpringBootApplication
@EnableTransactionManagement //開啟注解方式的事務(wù)管理
@Slf4j
@EnableCaching
@EnableScheduling //開啟任務(wù)調(diào)度
public class SkyApplication {
? ?public static void main(String[] args) {
? ? ? ?SpringApplication.run(SkyApplication.class, args);
? ? ? ?log.info("server started");
? }
}
1.3.3 功能測(cè)試
啟動(dòng)服務(wù),查看日志
每隔5秒執(zhí)行一次。
二、實(shí)例代碼(訂單業(yè)務(wù)自動(dòng)處理)
需求:待付款,超時(shí)自動(dòng)取消,需求代碼開發(fā)
開發(fā)步驟:
-
定義觸發(fā)時(shí)間
-
明確查詢條件
-
獲取查詢數(shù)據(jù)
-
將滿足條件的數(shù)據(jù)更新
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
?
/**
* 定時(shí)任務(wù)類,定時(shí)處理訂單狀態(tài)
*/
@Component
@Slf4j
public class OrderTask {
?
? ?@Autowired
? ?private OrderMapper orderMapper;
?
? ?/**
? ? * 處理超時(shí)訂單的方法
? ? */
? ?@Scheduled(cron = "0 * * * * ? ") //每分鐘觸發(fā)一次
? ?public void processTimeoutOrder(){
? ? ? ?log.info("定時(shí)處理超時(shí)訂單:{}", LocalDateTime.now());
? ? ? ?
? ? ? ?//獲得當(dāng)前時(shí)間15分鐘前的時(shí)間
? ? ? ?LocalDateTime time = LocalDateTime.now().plusMinutes(-15);
?
? ? ? ?// select * from orders where status = ? and order_time < (當(dāng)前時(shí)間 - 15分鐘)
? ? ? ?List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.PENDING_PAYMENT, time);
?
? ? ? ?if(ordersList != null && ordersList.size() > 0){
? ? ? ? ? ?for (Orders orders : ordersList) {
? ? ? ? ? ? ? ?orders.setStatus(Orders.CANCELLED);
? ? ? ? ? ? ? ?orders.setCancelReason("訂單超時(shí),自動(dòng)取消");
? ? ? ? ? ? ? ?orders.setCancelTime(LocalDateTime.now());
? ? ? ? ? ? ? ?orderMapper.update(orders);
? ? ? ? ? }
? ? ? }
? }
?
? ?/**
? ? * 處理一直處于派送中狀態(tài)的訂單
? ? */
? ?@Scheduled(cron = "0 0 1 * * ?") //每天凌晨1點(diǎn)觸發(fā)一次
? ?public void processDeliveryOrder(){
? ? ? ?log.info("定時(shí)處理處于派送中的訂單:{}",LocalDateTime.now());
?
? ? ? ?LocalDateTime time = LocalDateTime.now().plusMinutes(-60);
?
? ? ? ?List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.DELIVERY_IN_PROGRESS, time);
?
? ? ? ?if(ordersList != null && ordersList.size() > 0){
? ? ? ? ? ?for (Orders orders : ordersList) {
? ? ? ? ? ? ? ?orders.setStatus(Orders.COMPLETED);
? ? ? ? ? ? ? ?orderMapper.update(orders);
? ? ? ? ? }
? ? ? }
? }
}
mapper查詢訂單數(shù)據(jù)文章來源:http://www.zghlxwxcb.cn/news/detail-817962.html
?
/**
? ? * 根據(jù)訂單狀態(tài)和下單時(shí)間查詢訂單
? ? * @param status
? ? * @param orderTime
? ? * @return
? ? */
? @Select("select * from orders where status = #{status} and order_time < #{orderTime}")
? List<Orders> getByStatusAndOrderTimeLT(Integer status, LocalDateTime orderTime);
訂單數(shù)據(jù)庫(kù)對(duì)象文章來源地址http://www.zghlxwxcb.cn/news/detail-817962.html
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
?
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
?
/**
* 訂單
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Orders implements Serializable {
?
? ?/**
? ? * 訂單狀態(tài) 1待付款 2待接單 3已接單 4派送中 5已完成 6已取消
? ? */
? ?public static final Integer PENDING_PAYMENT = 1;
? ?public static final Integer TO_BE_CONFIRMED = 2;
? ?public static final Integer CONFIRMED = 3;
? ?public static final Integer DELIVERY_IN_PROGRESS = 4;
? ?public static final Integer COMPLETED = 5;
? ?public static final Integer CANCELLED = 6;
?
? ?/**
? ? * 支付狀態(tài) 0未支付 1已支付 2退款
? ? */
? ?public static final Integer UN_PAID = 0;
? ?public static final Integer PAID = 1;
? ?public static final Integer REFUND = 2;
?
? ?private static final long serialVersionUID = 1L;
?
? ?private Long id;
?
? ?//訂單號(hào)
? ?private String number;
?
? ?//訂單狀態(tài) 1待付款 2待接單 3已接單 4派送中 5已完成 6已取消 7退款
? ?private Integer status;
?
? ?//下單用戶id
? ?private Long userId;
?
? ?//地址id
? ?private Long addressBookId;
?
? ?//下單時(shí)間
? ?private LocalDateTime orderTime;
?
? ?//結(jié)賬時(shí)間
? ?private LocalDateTime checkoutTime;
?
? ?//支付方式 1微信,2支付寶
? ?private Integer payMethod;
?
? ?//支付狀態(tài) 0未支付 1已支付 2退款
? ?private Integer payStatus;
?
? ?//實(shí)收金額
? ?private BigDecimal amount;
?
? ?//備注
? ?private String remark;
?
? ?//用戶名
? ?private String userName;
?
? ?//手機(jī)號(hào)
? ?private String phone;
?
? ?//地址
? ?private String address;
?
? ?//收貨人
? ?private String consignee;
?
? ?//訂單取消原因
? ?private String cancelReason;
?
? ?//訂單拒絕原因
? ?private String rejectionReason;
?
? ?//訂單取消時(shí)間
? ?private LocalDateTime cancelTime;
?
? ?//預(yù)計(jì)送達(dá)時(shí)間
? ?private LocalDateTime estimatedDeliveryTime;
?
? ?//配送狀態(tài) 1立即送出 0選擇具體時(shí)間
? ?private Integer deliveryStatus;
?
? ?//送達(dá)時(shí)間
? ?private LocalDateTime deliveryTime;
?
? ?//打包費(fèi)
? ?private int packAmount;
?
? ?//餐具數(shù)量
? ?private int tablewareNumber;
?
? ?//餐具數(shù)量狀態(tài) 1按餐量提供 0選擇具體數(shù)量
? ?private Integer tablewareStatus;
}
?
到了這里,關(guān)于基于Spring Task框架的定時(shí)任務(wù)處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!