定時任務


定時任務

在實際項目開發中,除了Web應用、SOA服務外,還有一類不可缺少的,那就是定時任務調度。定時任務的場景可以說非常廣泛:

  • 某些網站會定時發送優惠郵件;

  • 銀行系統還款日信用卡催收款;

  • 某些應用的生日祝福短信等。

那究竟何為定時任務調度,一句話概括就是:基於給定的時間點、給定的時間間隔、自動執行的任務

 

 

2.3.1 入門案例

admin

  • 修改模塊引導類,開啟SpringTask功能支持

@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
@MapperScan("com.tanhua.admin.mapper")
@EnableScheduling //開啟定時任務支持
public class AdminServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(AdminServerApplication.class,args);
    }
}

配置定時任務類

@Component
public class AnalysisTask {
    
    /**
     * 配置時間規則
     */
    @Scheduled( cron = "0/20 * * * * ? ")
    public void analysis() throws ParseException {
        //業務邏輯
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        System.out.println("當前時間:"+time);
    }
    
}

CRON表達式

對於定時任務,我們使用的時候主要是注重兩個方面,一個是定時任務的業務,另一個就是Cron表達式。

Cron 表達式支持到六個域 

名稱 是否必須 允許值 特殊字符
0-59 , - * /
0-59 , - * /
0-23 , - * /
1-31 , - * ? / L W C
1-12 或 JAN-DEC , - * /
1-7 或 SUN-SAT , - * ? / L C #

 

 

月份和星期的名稱是不區分大小寫的。FRI 和 fri 是一樣的。

 

 

 

 

 

cron在線生成器地址:https://cron.qqe2.com/

定時統計

 

 

 

 

admin

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tanhua.model.admin.Log;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

@Repository
public interface LogMapper extends BaseMapper<Log> {

    /**
     * 根據操作時間和類型統計日志統計用戶數量
     *
     * @param type
     * @param logTime
     * @return
     */
    @Select("SELECT COUNT(DISTINCT user_id) FROM tb_log WHERE TYPE=#{type} AND log_time=#{logTime}")
    Integer queryByTypeAndLogTime(@Param("type") String type, @Param("logTime") String logTime);

    /**
     * 根據時間統計用戶數量
     *
     * @param logTime
     * @return
     */
    @Select("SELECT COUNT(DISTINCT user_id) FROM tb_log WHERE log_time=#{logTime}")
    Integer queryByLogTime(String logTime);

    /**
     * 查詢次日留存 , 從昨天活躍的用戶中查詢今日活躍用戶
     *
     * @param today
     * @param yestoday
     * @return
     */
    @Select("SELECT COUNT(DISTINCT user_id)  FROM tb_log WHERE log_time=#{today} AND user_id IN (SELECT user_id FROM tb_log WHERE TYPE='0102' AND log_time=#{yestoday})")
    Integer queryNumRetention1d(@Param("today") String today, @Param("yestoday") String yestoday);
}

為了方便操作,可以通過以下單元測試方法。保存若干操作數據

import com.tanhua.manager.domain.Log;
import com.tanhua.manager.mapper.LogMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Random;

@RunWith(SpringRunner.class)
@SpringBootTest
public class LogTest {

    @Autowired
    private LogMapper logMapper;
    
    private String logTime = "";

    //模擬登錄數據
    public void testInsertLoginLog() {
        for (int i = 0; i < 5; i++) {
            Log log = new Log();
            log.setUserId((long)(i+1));
            log.setLogTime(logTime);
            log.setType("0101");
            logMapper.insert(log);
        }
    }

    //模擬注冊數據
    public void testInsertRegistLog() {
        for (int i = 0; i < 10; i++) {
            Log log = new Log();
            log.setUserId((long)(i+1));
            log.setLogTime(logTime);
            log.setType("0102");
            logMapper.insert(log);
        }
    }
    //模擬其他操作
    public void testInsertOtherLog() {
        String[] types = new String[]{"0201","0202","0203","0204","0205","0206","0207","0301","0302","0303","0304"};
        for (int i = 0; i < 10; i++) {
            Log log = new Log();
            log.setUserId((long)(i+1));
            log.setLogTime(logTime);
            int index = new Random().nextInt(10);
            log.setType(types[index]);
            logMapper.insert(log);
        }
    }

    @Test
    public void generData() {
        testInsertLoginLog();
        testInsertRegistLog();
        testInsertOtherLog();
    }
}

 

 

 

 

  • 修改AnalysisTask類,調用service進行定時統計

@Component
public class AnalysisTask {

    @Autowired
    private AnalysisService analysisService;

    /**
     * 配置時間規則
     *   在學習測試時,可以將時間間隔設置相對短一些
     */
    @Scheduled( cron = "0/20 * * * * ? ")
    public void analysis() throws ParseException {
        //業務邏輯
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        System.out.println("開始統計:"+time);
        //調logService完成日志統計
        analysisService.analysis();
        System.out.println("結束統計");
    }
}



配置AnalysisService

import
cn.hutool.core.date.DateUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.tanhua.admin.mapper.AnalysisMapper; import com.tanhua.admin.mapper.LogMapper; import com.tanhua.model.admin.Analysis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.expression.ParseException; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.Date; /** * @author Administrator */ @Service public class AnalysisService { @Autowired private AnalysisMapper analysisMapper; @Autowired private LogMapper logMapper; /** * 定時統計日志數據到統計表中 * 1、查詢tb_log表中的數 (每日注冊用戶數,每日登陸用戶,活躍的用戶數據,次日留存的用戶) * 2、構造AnalysisByDay對象 * 3、完成統計數據的更新或者保存 */ public void analysis() throws ParseException { //1、定義查詢的日期 String todayStr = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); String yesdayStr = DateUtil.yesterday().toString("yyyy-MM-dd"); //2、統計數據-注冊數量 Integer regCount = logMapper.queryByTypeAndLogTime("0102", todayStr); //3、統計數據-登錄數量 Integer loginCount = logMapper.queryByTypeAndLogTime("0101", todayStr); //4、統計數據-活躍數量 Integer activeCount = logMapper.queryByLogTime(todayStr); //5、統計數據-次日留存 Integer numRetention1d = logMapper.queryNumRetention1d(todayStr, yesdayStr); //6、根據日期查詢數據 QueryWrapper<Analysis> qw = new QueryWrapper<Analysis>(); qw.eq("record_date",new SimpleDateFormat("yyyy-MM-dd").parse(todayStr)); //7、構造Analysis對象 Analysis analysis = analysisMapper.selectOne(qw); //8、如果存在,更新,如果不存在保存 if(analysis != null) { analysis.setNumRegistered(regCount); analysis.setNumLogin(loginCount); analysis.setNumActive(activeCount); analysis.setNumRetention1d(numRetention1d); analysisMapper.updateById(analysis); }else { analysis = new Analysis(); analysis.setNumRegistered(regCount); analysis.setNumLogin(loginCount); analysis.setNumActive(activeCount); analysis.setNumRetention1d(numRetention1d); analysis.setRecordDate(new SimpleDateFormat("yyyy-MM-dd").parse(todayStr)); analysis.setCreated(new Date()); analysisMapper.insert(analysis); } } }

創建LogMapper並配置查詢方法

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM