關于對逾期提醒的定時任務~改進完善

Spring Boot 中實現到期提醒任務的定時Job詳解

在金融或借貸系統中,到期提醒是常見的功能需求。通過定時任務,可以定期掃描即將到期的借款記錄,并生成或更新提醒信息。本文基于提供的三個JobHandler類(FarExpireRemindJob、MidExpireRemindJob 和 RecentExpireRemindJob),詳細分析其實現邏輯。這些類使用Spring Boot的組件注解(@Component),并實現了JobHandler接口(假設這是自定義的定時任務接口),結合MyBatis-Plus的QueryWrapper進行數據庫操作。代碼涉及借款入庫(LoanInDO)、借款出庫(LoanOutDO)和提醒記錄(RemindExpireDO)的處理。

本文將逐一拆解每個類的代碼結構、核心邏輯、潛在優化點和注意事項,確保覆蓋所有提供的代碼片段。假設這些Job是集成在XXL-JOB或類似調度框架中的定時任務。

1. 整體功能概述
  • FarExpireRemindJob:負責遠期到期提醒(默認30天)。掃描即將到期的借款記錄,生成提醒記錄,并更新借款記錄的提醒標志。
  • MidExpireRemindJob:負責中期到期提醒(默認15天)。更新已存在的提醒記錄,調整提醒狀態和時間。
  • RecentExpireRemindJob:負責近期到期提醒(默認7天)。類似于中期提醒,更新提醒記錄的狀態和時間。 這些Job通過參數(param)支持自定義天數,支持事務回滾(僅FarExpireRemindJob有@Transactional注解),并返回執行結果字符串,便于日志記錄或監控。

依賴的Mapper(如LoanInMapper、RemindExpireMapper等)使用MyBatis-Plus進行CRUD操作。DO類(如LoanInDO)是數據庫實體,包含字段如id、custId、expireTime等。

2. FarExpireRemindJob 詳細分析

這個類是三個Job中最復雜的,涉及多表操作和批量更新。它的目的是在借款到期前一定天數(默認30天)生成提醒記錄,并標記借款記錄已提醒。

代碼結構:

  • 類注解和依賴注入:

  • @Component
    public class FarExpireRemindJob implements JobHandler {@Autowiredprivate LoanInMapper loanInMapper;@Autowiredprivate RemindExpireMapper remindExpireMapper;@Autowiredprivate LoanOutMapper loanOutMapper;

    • @Component:將類注冊為Spring Bean,便于調度框架注入和調用。
    • 注入三個Mapper:用于查詢和更新借款入庫、出庫和提醒表。
  • execute方法(核心執行邏輯):

@Override
@Transactional(rollbackFor = Exception.class)
public String execute(String param) throws Exception {// 到期提醒默認值int day = (StringUtils.isEmpty(param)) ? 30 : Integer.parseInt(param);List<LoanInDO> loanInDOList = loanInMapper.selectList(new QueryWrapperX<LoanInDO>().eq("overdue_flag", 0).eq("expire_remind_flag", 0).le("expire_time", LocalDate.now().plusDays(day)));List<LoanOutDO> loanOutDOList = loanOutMapper.selectList(new QueryWrapper<LoanOutDO>().eq("overdue_flag", 0).eq("expire_remind_flag", 0).le("expire_time", LocalDate.now().plusDays(day)));
  • 解析參數:如果param為空,默認day=30,否則轉換為整數。
  • 查詢借款入庫記錄:使用QueryWrapperX(MyBatis-Plus擴展)過濾未逾期(overdue_flag=0)、未提醒(expire_remind_flag=0)、到期時間 <= 當前日期 + day 的記錄。
  • 類似查詢借款出庫記錄。注意:QueryWrapperX可能是自定義的Wrapper,支持更靈活的查詢。
    List<RemindExpireDO> remindExpireDOList = new ArrayList<>();loanInDOList.forEach(loanInDO -> {loanInDO.setExpireRemindFlag(1);RemindExpireDO remindExpireDO = RemindExpireDO.builder().loanId(loanInDO.getId()).custId(loanInDO.getCustId()).custCode(loanInDO.getCustCode()).custName(loanInDO.getCustName()).contractCode(loanInDO.getContractCode()).amount(loanInDO.getAmount()).balance(loanInDO.getBalance()).beginTime(loanInDO.getBeginTime()).expireTime(loanInDO.getExpireTime()).remindTime(LocalDateTime.now()).showFlag(1).remindStatus(day).remindFlag(1).userName(loanInDO.getUserName()).userId(loanInDO.getUserId()).deptName(loanInDO.getDeptName()).deptId(loanInDO.getDeptId()).build();loanInDO.setExpireRemindFlag(1);  // 重復設置,可能是筆誤remindExpireDOList.add(remindExpireDO);});
  • 處理借款入庫列表:遍歷每個LoanInDO,設置expireRemindFlag=1(標記已提醒)。
  • 使用Lombok的builder模式創建RemindExpireDO,復制借款相關字段,并設置提醒時間、狀態等。
  • 注意:loanInDO.setExpireRemindFlag(1); 出現了兩次,第二次是多余的,可能為代碼筆誤,會導致無謂操作但不影響功能。
  • 添加到remindExpireDOList中。
    loanOutDOList.forEach(loanOutDO -> {loanOutDO.setExpireRemindFlag(1);RemindExpireDO remindExpireDO = RemindExpireDO.builder()// ... 與入庫類似,復制字段 ....build();loanOutDO.setExpireRemindFlag(1);  // 同樣重復設置remindExpireDOList.add(remindExpireDO);});

處理借款出庫列表:邏輯與入庫完全相同,包括重復的setExpireRemindFlag。

    if (!loanInDOList.isEmpty()) {loanInMapper.updateBatch(loanInDOList);}if (!loanOutDOList.isEmpty()) {loanOutMapper.updateBatch(loanOutDOList);}if (!remindExpireDOList.isEmpty()) {remindExpireMapper.insertBatch(remindExpireDOList);}return String.format("已產生 %s 條到期提醒", remindExpireDOList.size());
}
    • 批量更新借款記錄(如果列表非空)。
    • 批量插入提醒記錄。
    • 返回結果字符串,報告生成的提醒條數。
    • @Transactional:確保所有操作在事務中,如果異常則回滾,防止數據不一致。

分析與優化點:

  • 優點:批量操作高效,避免了循環中的單條更新;事務保障數據一致性;參數化day支持靈活配置。
  • 潛在問題:如果借款記錄量大,查詢和遍歷可能耗時,需要監控性能。重復的setExpireRemindFlag是小bug,可移除第二次調用。未處理param解析異常(e.g., 非數字),建議添加try-catch。
  • 改進建議:添加日志記錄(e.g., SLF4J);如果day很大,查詢條件可優化索引(expire_time字段應有索引);考慮分頁查詢以防內存溢出。
3. MidExpireRemindJob 詳細分析

這個Job專注于更新中期提醒(默認15天),不生成新記錄,只更新現有提醒的status和time。

代碼結構:

  • 類注解和依賴注入:
@Component
public class MidExpireRemindJob implements JobHandler {@Autowiredprivate RemindExpireMapper remindExpireMapper;
    • 類似前者,只注入提醒Mapper。
  • execute方法:
@Override
public String execute(String param) throws Exception {int day = (StringUtils.isEmpty(param)) ? 15 : Integer.parseInt(param);List<RemindExpireDO> remindExpireDOS = remindExpireMapper.selectList(new QueryWrapperX<RemindExpireDO>().between("expire_time",LocalDate.now().plusDays(day),LocalDate.now().plusDays(day + 1)));remindExpireDOS.forEach(remindExpireDO -> {remindExpireDO.setRemindTime(LocalDateTime.now());remindExpireDO.setRemindStatus(day);});if (!remindExpireDOS.isEmpty()) {remindExpireMapper.updateBatch(remindExpireDOS);}return String.format("更新了 %d 條提醒", remindExpireDOS.size());
}
    • 解析day,默認15。
    • 查詢提醒記錄:到期時間在 [當前+day, 當前+day+1) 之間,使用between條件。
    • 遍歷更新:設置當前提醒時間和status=day。
    • 批量更新,如果非空。
    • 返回更新條數。

分析與優化點:

  • 優點:簡單高效,只更新必要字段;between條件精確匹配特定天窗。
  • 潛在問題:未加@Transactional,如果更新失敗無回滾(與其他Job不一致)。查詢未過濾已逾期或已處理記錄,可能重復更新。
  • 改進建議:添加事務注解;添加過濾條件如.eq("remindStatus", > day) 以避免重復;考慮day的邊界(如day=0時)。
4. RecentExpireRemindJob 詳細分析

與MidExpireRemindJob幾乎相同,僅默認day=7和返回字符串略不同,用于近期提醒。

代碼結構:

  • 類注解和依賴注入: 同Mid,僅注入RemindExpireMapper。
  • execute方法:
@Override
public String execute(String param) throws Exception {int day = (StringUtils.isEmpty(param)) ? 7 : Integer.parseInt(param);List<RemindExpireDO> remindExpireDOS = remindExpireMapper.selectList(new QueryWrapperX<RemindExpireDO>().between("expire_time",LocalDate.now().plusDays(day),LocalDate.now().plusDays(day + 1)));remindExpireDOS.forEach(remindExpireDO -> {remindExpireDO.setRemindTime(LocalDateTime.now());remindExpireDO.setRemindStatus(day);});if (!remindExpireDOS.isEmpty()) {remindExpireMapper.updateBatch(remindExpireDOS);}return String.format("更新了 %d 條提醒記錄", remindExpireDOS.size());
}
    • 邏輯完全一致,僅day默認7,返回消息為“提醒記錄”。

分析與優化點:

  • 優點:代碼復用性高,與Mid類似,便于維護。
  • 潛在問題:同Mid,無事務;可能與Mid重疊更新(如果day重合)。
  • 改進建議:合并Mid和Recent為一個Job,通過param區分;添加唯一性檢查避免多Job沖突。
5. 整體系統設計與注意事項
  • 定時調度:這些Job適合每天運行一次(e.g., 凌晨)。FarJob生成初始提醒,Mid/Recent逐步更新status,形成多級提醒(如30→15→7天)。
  • 數據一致性:Far有事務,其他無,建議統一添加。所有Job使用LocalDate.now(),注意時區。
  • 性能考慮:批量操作好,但大表需索引(expire_time、flags)。錯誤處理:param非數字時拋異常,可加校驗。
  • 擴展性:可添加短信/郵件通知在更新后;DO類字段豐富,支持報表。
  • 測試建議:單元測試查詢條件;集成測試事務回滾。

通過這些Job,可以實現自動化到期提醒系統。如果需要完整項目代碼或進一步優化,歡迎評論交流!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/96063.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/96063.shtml
英文地址,請注明出處:http://en.pswp.cn/web/96063.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

springboot配置請求日志

springboot配置請求日志 一般情況下&#xff0c;接口請求都需要日志記錄&#xff0c;Java springboot中的日志記錄相對復雜一點 經過實踐&#xff0c;以下方案可行&#xff0c;記錄一下完整過程 一、創建日志數據模型 創建實體類&#xff0c;也就是日志文件中要記錄的數據格式 …

Redis(50) Redis哨兵如何與客戶端進行交互?

Redis 哨兵&#xff08;Sentinel&#xff09;不僅負責監控和管理 Redis 主從復制集群的高可用性&#xff0c;還需要與客戶端進行有效的交互來實現故障轉移后的透明連接切換。下面詳細探討 Redis 哨兵如何與客戶端進行交互&#xff0c;并結合代碼示例加以說明。 哨兵與客戶端的交…

【.Net技術棧梳理】04-核心框架與運行時(線程處理)

文章目錄1. 線程管理1.1 線程的核心概念&#xff1a;System.Threading.Thread1.2 現代線程管理&#xff1a;System.Threading.Tasks.Task 和 Task Parallel Library (TPL)1.3 狀態管理和異常處理1.4 協調任務&#xff1a;async/await 模式2. 線程間通信2.1 共享內存與競態條件2…

(JVM)四種垃圾回收算法

在 JVM 中&#xff0c;垃圾回收&#xff08;GC&#xff09;是核心機制之一。為了提升性能與內存利用率&#xff0c;JVM 采用了多種垃圾回收算法。本文總結了 四種常見的 GC 算法&#xff0c;并結合其優缺點與應用場景進行說明。1. 標記-清除&#xff08;Mark-Sweep&#xff09;…

論文閱讀:VGGT Visual Geometry Grounded Transformer

論文閱讀&#xff1a;VGGT: Visual Geometry Grounded Transformer 今天介紹一篇 CVPR 2025 的 best paper&#xff0c;這篇文章是牛津大學的 VGG 團隊的工作&#xff0c;主要圍繞著 3D 視覺中的各種任務&#xff0c;這篇文章提出了一種多任務統一的架構&#xff0c;實現一次輸…

python編程:一文掌握pypiserver的詳細使用

更多內容請見: python3案例和總結-專欄介紹和目錄 文章目錄 一、 pypiserver 概述 1.1 pypiserver是什么? 1.2 核心特性 1.3 典型應用場景 1.4 pypiserver優缺點 二、 安裝與基本使用 2.1 安裝 pypiserver 2.2 快速啟動(最簡模式) 2.3 使用私有服務器安裝包 2.4 向私有服務…

Git reset 回退版本

- 第 121 篇 - Date: 2025 - 09 - 06 Author: 鄭龍浩&#xff08;仟墨&#xff09; 文章目錄Git reset 回退版本1 介紹三種命令區別3 驗證三種的區別3 如果不小心git reset --hard將「工作區」和「暫存區」中的內容刪除&#xff0c;剛才的記錄找不到了&#xff0c;怎么辦呢&…

ARM 基礎(2)

ARM內核工作模式及其切換條件用戶模式(User Mode, usr) 權限最低&#xff0c;運行普通應用程序。只能通過異常被動切換到其他模式。快速中斷模式(FIQ Mode, fiq) 處理高速外設中斷&#xff0c;專用寄存器減少上下文保存時間&#xff0c;響應周期約4個時鐘周期。觸發條件為FIQ中…

Flutter 性能優化

Flutter 性能優化是一個系統性的工程&#xff0c;涉及多個層面。 一、性能分析工具&#xff08;Profiling Tools&#xff09; 在開始優化前&#xff0c;必須使用工具定位瓶頸。切忌盲目優化。 1. DevTools 性能視圖 DevTools 性能視圖 (Performance View) 作用&#xff1a;…

Spring事件監聽機制(三)

為了理解EvenListener注解的底層原理&#xff0c;我們可以自己實現一個類似的注解模擬實現。1.定義MyListener注解Target({ElementType.METHOD})Retention(RetentionPolicy.RUNTIME)public interface MyListener {}2.注解使用Componentstatic class SmsService {private static…

基于Springboot + vue3實現的小區物業管理系統

項目描述本系統包含管理員和用戶兩個角色。管理員角色&#xff1a;用戶管理&#xff1a;管理系統中所有用戶的信息&#xff0c;包括添加、刪除和修改用戶。房屋信息管理&#xff1a;管理房屋信息&#xff0c;包括新增、查看、修改和刪除房屋信息。車輛信息管理&#xff1a;管理…

交叉熵和KL散度

這個問題之前我也是傻傻分不清&#xff0c;決定整理一下&#xff0c;用更印象深刻的方式讓人記住。核心聯系&#xff1a;交叉熵 KL 散度 真實分布的熵 交叉熵作為 “絕對” 度量&#xff0c;會綜合真實分布的熵&#xff08;固有難度&#xff09;與預測誤差&#xff0c;直接體…

HTML 各種事件的使用說明書

HTML 各種事件的使用說明書 1. HTML 事件簡介 HTML事件是瀏覽器或用戶在網頁上執行的動作或發生的事情。當這些事件發生時&#xff0c;可以通過JavaScript來響應和處理這些事件&#xff0c;從而實現網頁的交互功能。事件處理是Web前端開發中實現動態交互的核心機制。 基本概…

Kafka面試精講 Day 10:事務機制與冪等性保證

【Kafka面試精講 Day 10】事務機制與冪等性保證 在分布式消息系統中&#xff0c;如何確保消息不丟失、不重復&#xff0c;是系統可靠性的核心挑戰。Kafka自0.11版本起引入了冪等性Producer和事務性消息機制&#xff0c;徹底解決了“至少一次”語義下可能產生的重復消息問題&am…

時序數據庫簡介和安裝

一、簡介1. 什么是時序數據庫&#xff1f;時序數據庫是專門用于存儲和處理時間序列數據的數據庫系統。時間序列數據是指按時間順序索引的一系列數據點。每個數據點都包含&#xff1a;一個時間戳&#xff1a;記錄數據產生的時間。一個或多個指標值&#xff1a;例如溫度、濕度、C…

comfyUI 暴露網絡restful http接口

https://zhuanlan.zhihu.com/p/686893291 暴露websocket接口。 打開開發者選項 如圖

linux系統address already in use問題解決

linux系統上某個端口被占用&#xff0c;如何解決&#xff1f;1.找到占用的進程編號&#xff1a;netstat -tulnp | grep :80002.強制殺死該進程kill -9 80603其他說明&#xff1a;1.查找占用端口的進程&#xff0c;可以用&#xff1a;lsof -i :8001 # 或者使用 netstat -tulnp |…

基于SpringBoot的家政保潔預約系統【計算機畢業設計選題 計算機畢業設計項目 計算機畢業論文題目推薦】

&#x1f34a;作者&#xff1a;計算機編程-吉哥 &#x1f34a;簡介&#xff1a;專業從事JavaWeb程序開發&#xff0c;微信小程序開發&#xff0c;定制化項目、 源碼、代碼講解、文檔撰寫、ppt制作。做自己喜歡的事&#xff0c;生活就是快樂的。 &#x1f34a;心愿&#xff1a;點…

【Linux系統】 4. 權限(一)

一. shell 命令及運行原理基本理解1&#xff09;廣義理解的操作系統包括&#xff1a;操作系統內核、外殼程序&#xff08;shell命令行、圖形化界面&#xff09;、必要的軟件。2&#xff09;狹義的操作系統&#xff1a;操作系統內核。3&#xff09;在用戶和內核之間有一個外殼程…

6.python——字符串

python中用’ 和" "創建字符串 python的子字符串截取用[]取字符串拼接可以直接用相加。 python三引號允許一個字符串跨多行&#xff0c;其中無需進行轉義&#xff08;所見即所得&#xff09;。 當你需要一塊HTML或者SQL時&#xff0c;這時用字符串組合&#xff0c;特…