1.Quartz簡介
Quartz框架的核心是調度器。調度器負責管理Quartz應用運行時環境。調度器不是靠自己做所有的工作,而是依賴框架內一些非常重要的部件。Quartz不僅僅是線程和線程管理。為確保可伸縮性,Quartz采用了基於多線程的架構。啟動時,框架初始化一套worker線程,這套線程被調度器用來執行預定的作業。這就是Quartz怎樣能並發運行多個作業的原理。Quartz依賴一套松耦合的線程池管理部件來管理線程環境。
2.項目相關
該定時器Demo用於定時執行制定路徑下的jar包的編譯,也可以用於普通的任務調度.通過對任務的查詢修改刪除來管理整個列表文件.可以通關開啟和關閉來更改jar的開始執行狀態(開啟后如果需要停止只能關閉或重啟服務器才能生效,具體的解決辦法還在改進中).相關的一整套的UI界面比較簡略,可以進行二次開發,主要整合了JPA的分頁查詢,可以查看相關代碼部分.

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地址
(喜歡記得點星支持哦,謝謝!)
