Quartz定時調度jar包的執行Demo分享


1.Quartz簡介

​ Quartz框架的核心是調度器。調度器負責管理Quartz應用運行時環境。調度器不是靠自己做所有的工作,而是依賴框架內一些非常重要的部件。Quartz不僅僅是線程和線程管理。為確保可伸縮性,Quartz采用了基於多線程的架構。啟動時,框架初始化一套worker線程,這套線程被調度器用來執行預定的作業。這就是Quartz怎樣能並發運行多個作業的原理。Quartz依賴一套松耦合的線程池管理部件來管理線程環境。

2.項目相關

​ 該定時器Demo用於定時執行制定路徑下的jar包的編譯,也可以用於普通的任務調度.通過對任務的查詢修改刪除來管理整個列表文件.可以通關開啟和關閉來更改jar的開始執行狀態(開啟后如果需要停止只能關閉或重啟服務器才能生效,具體的解決辦法還在改進中).相關的一整套的UI界面比較簡略,可以進行二次開發,主要整合了JPA的分頁查詢,可以查看相關代碼部分.

test.gif

3.測試路徑

//主頁路徑:
http://localhost:9090/
//啟動jar的路徑(這里的我只是建了一個簡單的springboot的helloword的Jar包,相關jar包在項目中可以找到)
http://localhost:8088/sayHello

4.代碼相關

QuartzServiceImpl:
@Service
public class QuartzServiceImpl implements QuartzService {

    @Autowired
    private JobEntityRepository repository;

    @Override
    public JobEntity getById(int id) {
        return repository.getById(id);
    }

    //通過Id獲取Job
    public JobEntity getJobEntityById(Integer id) {
        return repository.getById(id);
    }
    //從數據庫中加載獲取到所有Job
    public List<JobEntity> loadJobs() {
        List<JobEntity> list = new ArrayList<>();
        repository.findAll().forEach(list::add);
        return list;
    }
    //獲取JobDataMap.(Job參數對象)
    public JobDataMap getJobDataMap(JobEntity job) {
        JobDataMap map = new JobDataMap();
        map.put("name", job.getName());
        map.put("group", job.getGroup());
        map.put("cronExpression", job.getCron());
        map.put("parameter", job.getParameter());
        map.put("JobDescription", job.getDescription());
        map.put("vmParam", job.getVmParam());
        map.put("jarPath", job.getJarPath());
        map.put("status", job.getStatus());
        return map;
    }
    //獲取JobDetail,JobDetail是任務的定義,而Job是任務的執行邏輯,JobDetail里會引用一個Job Class來定義
    public JobDetail geJobDetail(JobKey jobKey, String description, JobDataMap map) {
        return JobBuilder.newJob(DynamicJob.class)
                .withIdentity(jobKey)
                .withDescription(description)
                .setJobData(map)
                .storeDurably()
                .build();
    }
    //獲取Trigger (Job的觸發器,執行規則)
    public Trigger getTrigger(JobEntity job) {
        return TriggerBuilder.newTrigger()
                .withIdentity(job.getName(), job.getGroup())
                .withSchedule(CronScheduleBuilder.cronSchedule(job.getCron()))
                .build();
    }
    //獲取JobKey,包含Name和Group
    public JobKey getJobKey(JobEntity job) {
        return JobKey.jobKey(job.getName(), job.getGroup());
    }
}
DynamicJob:
/**
 * :@DisallowConcurrentExecution : 此標記用在實現Job的類上面,意思是不允許並發執行.
 * :注意org.quartz.threadPool.threadCount線程池中線程的數量至少要多個,否則@DisallowConcurrentExecution不生效
 * :假如Job的設置時間間隔為3秒,但Job執行時間是5秒,設置@DisallowConcurrentExecution以后程序會等任務執行完畢以后再去執行,否則會在3秒時再啟用新的線程執行
 */
@DisallowConcurrentExecution
@PersistJobDataAfterExecution //沒有異常就更新數據 可用?
@Component
@Slf4j
public class DynamicJob implements Job {
    private Logger logger = LoggerFactory.getLogger(DynamicJob.class);

    /**
     * 核心方法,Quartz Job真正的執行邏輯.
     *   executorContext JobExecutionContext中封裝有Quartz運行所需要的所有信息
     * @throws JobExecutionException execute()方法只允許拋出JobExecutionException異常
     */
    @Override
    public void execute(JobExecutionContext executionContext) throws JobExecutionException {

        JobDataMap map = executionContext.getMergedJobDataMap();

        String jarPath = map.getString("jarPath");
        String parameter = map.getString("parameter");
        String vmParam = map.getString("vmParam");
        logger.info("Running Job name : {} ", map.getString("name"));
        logger.info("Running Job description : " + map.getString("JobDescription"));
        logger.info("Running Job group: {} ", map.getString("group"));
        logger.info("Running Job cron : " + map.getString("cronExpression"));
        logger.info("Running Job jar path : {} ", jarPath);
        logger.info("Running Job parameter : {} ", parameter);
        logger.info("Running Job vmParam : {} ", vmParam);

        long startTime = System.currentTimeMillis();
        if (!StringUtils.getStringUtil.isEmpty(jarPath)) {

            File jar = new File(jarPath);
            if (jar.exists()) {
                ProcessBuilder processBuilder = new ProcessBuilder();
                processBuilder.directory(jar.getParentFile());
                /**
                 * 這個是java的執行命令
                 * java -jar
                 */
                List<String> commands = new ArrayList<>();
                commands.add("java");
                if (!StringUtils.getStringUtil.isEmpty(vmParam)) {
                    commands.add(vmParam);
                }
                commands.add("-jar");
                commands.add(jarPath);
                commands.add(" &");
                System.out.println("commands->\n"+commands);

                if (!StringUtils.getStringUtil.isEmpty(parameter)) {

                    commands.add(parameter);
                    processBuilder.command(commands);
                    logger.info("Running Job details as follows >>>>>>>>>>>>>>>>>>>>: ");
                    logger.info("Running Job commands : {}  ", StringUtils.getStringUtil.getListString(commands));
                    try {
                        Process process = processBuilder.start();
                        logProcess(process.getInputStream(), process.getErrorStream());

                    } catch (Exception e) {

                        e.printStackTrace();
                    }
                } else {

                    throw new JobExecutionException("Job Jar not found >>  " + jarPath);
                }

                long endTime = System.currentTimeMillis();
                logger.info(">>>>>>>>>>>>> Running Job has been completed , cost time :  " + (endTime - startTime) + "ms\n");
            }


        }


    }

    //打印Job執行內容的日志
    private void logProcess(InputStream inputStream, InputStream errorStream) throws IOException {
        String inputLine;
        String errorLine;
        BufferedReader inputReader = new BufferedReader(new InputStreamReader(inputStream));
        BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream));
        while ((inputLine = inputReader.readLine()) != null){
            logger.info(inputLine);
        }
        while ((errorLine = errorReader.readLine()) != null) {
            logger.error(errorLine);
        }
    }

}

5.項目git地址

(喜歡記得點星支持哦,謝謝!)

https://github.com/fengcharly/quartz-jpa


免責聲明!

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



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