Commit 68e62678 authored by 郑杰's avatar 郑杰
Browse files

v1.4 版本发布,修复bug、优化细节、新增定时任务管理,详细信息查看发行版说明

parent 588bff02
package me.zhengjie.quartz.service.query;
import me.zhengjie.common.utils.PageUtil;
import me.zhengjie.quartz.domain.QuartzJob;
import me.zhengjie.quartz.repository.QuartzJobRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
/**
* @author jie
* @date 2019-01-07
*/
@Service
@CacheConfig(cacheNames = "quartzJob")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class QuartzJobQueryService {
@Autowired
private QuartzJobRepository quartzJobRepository;
@Cacheable(keyGenerator = "keyGenerator")
public Object queryAll(QuartzJob quartzJob, Pageable pageable){
return PageUtil.toPage(quartzJobRepository.findAll(new Spec(quartzJob),pageable));
}
class Spec implements Specification<QuartzJob> {
private QuartzJob quartzJob;
public Spec(QuartzJob quartzJob){
this.quartzJob = quartzJob;
}
@Override
public Predicate toPredicate(Root<QuartzJob> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
List<Predicate> list = new ArrayList<Predicate>();
if(!ObjectUtils.isEmpty(quartzJob.getJobName())){
/**
* 模糊
*/
list.add(cb.like(root.get("jobName").as(String.class),"%"+quartzJob.getJobName()+"%"));
}
Predicate[] p = new Predicate[list.size()];
return cb.and(list.toArray(p));
}
}
}
package me.zhengjie.quartz.service.query;
import me.zhengjie.common.utils.PageUtil;
import me.zhengjie.quartz.domain.QuartzLog;
import me.zhengjie.quartz.repository.QuartzLogRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
/**
* @author jie
* @date 2019-01-07
*/
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class QuartzLogQueryService {
@Autowired
private QuartzLogRepository quartzLogRepository;
public Object queryAll(QuartzLog quartzLog, Pageable pageable){
return PageUtil.toPage(quartzLogRepository.findAll(new Spec(quartzLog),pageable));
}
class Spec implements Specification<QuartzLog> {
private QuartzLog quartzLog;
public Spec(QuartzLog quartzLog){
this.quartzLog = quartzLog;
}
@Override
public Predicate toPredicate(Root<QuartzLog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
List<Predicate> list = new ArrayList<Predicate>();
if(!ObjectUtils.isEmpty(quartzLog.getJobName())){
/**
* 模糊
*/
list.add(cb.like(root.get("jobName").as(String.class),"%"+quartzLog.getJobName()+"%"));
}
if (!ObjectUtils.isEmpty(quartzLog.getIsSuccess())) {
list.add(cb.equal(root.get("isSuccess").as(Boolean.class), quartzLog.getIsSuccess()));
}
Predicate[] p = new Predicate[list.size()];
return cb.and(list.toArray(p));
}
}
}
package me.zhengjie.quartz.task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 测试用
* @author jie
* @date 2019-01-08
*/
@Slf4j
@Component
public class TestTask {
public void run(){
log.info("执行成功");
}
public void run1(String str){
log.info("执行成功,参数为: {}" + str);
}
}
package me.zhengjie.monitor.config;
package me.zhengjie.quartz.task;
import me.zhengjie.monitor.service.VisitsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
......@@ -11,17 +9,12 @@ import org.springframework.stereotype.Component;
* @date 2018-12-25
*/
@Component
@Async
public class VisitsScheduling {
public class VisitsTask {
@Autowired
private VisitsService visitsService;
/**
* 每天0点运行
*/
@Scheduled(cron = "0 0 0 * * ?")
public void save(){
public void run(){
visitsService.save();
}
}
package me.zhengjie.quartz.utils;
import me.zhengjie.common.utils.SpringContextHolder;
import me.zhengjie.common.utils.ThrowableUtil;
import me.zhengjie.quartz.domain.QuartzJob;
import me.zhengjie.quartz.domain.QuartzLog;
import me.zhengjie.quartz.repository.QuartzLogRepository;
import me.zhengjie.quartz.service.QuartzJobService;
import org.quartz.JobExecutionContext;
import org.quartz.Scheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.quartz.QuartzJobBean;
import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
/**
* 参考人人开源,https://gitee.com/renrenio/renren-security
* @author
* @date 2019-01-07
*/
@Async
public class ExecutionJob extends QuartzJobBean {
@Resource(name = "scheduler")
private Scheduler scheduler;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private ExecutorService executorService;
@Override
protected void executeInternal(JobExecutionContext context) {
QuartzJob quartzJob = (QuartzJob) context.getMergedJobDataMap().get(QuartzJob.JOB_KEY);
// 获取spring bean
QuartzLogRepository quartzLogRepository = SpringContextHolder.getBean("quartzLogRepository");
QuartzJobService quartzJobService = SpringContextHolder.getBean("quartzJobService");
QuartzManage quartzManage = SpringContextHolder.getBean("quartzManage");
QuartzLog log = new QuartzLog();
log.setJobName(quartzJob.getJobName());
log.setBeanName(quartzJob.getBeanName());
log.setMethodName(quartzJob.getMethodName());
log.setParams(quartzJob.getParams());
long startTime = System.currentTimeMillis();
log.setCronExpression(quartzJob.getCronExpression());
try {
// 执行任务
logger.info("任务准备执行,任务名称:{}", quartzJob.getJobName());
QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(),
quartzJob.getParams());
Future<?> future = executorService.submit(task);
future.get();
long times = System.currentTimeMillis() - startTime;
log.setTime(times);
// 任务状态
log.setIsSuccess(true);
logger.info("任务执行完毕,任务名称:{} 总共耗时:{} 毫秒", quartzJob.getJobName(), times);
} catch (Exception e) {
logger.error("任务执行失败,任务名称:{}" + quartzJob.getJobName(), e);
long times = System.currentTimeMillis() - startTime;
log.setTime(times);
// 任务状态 0:成功 1:失败
log.setIsSuccess(false);
log.setExceptionDetail(ThrowableUtil.getStackTrace(e));
//出错就暂停任务
quartzManage.pauseJob(quartzJob);
//更新状态
quartzJobService.updateIsPause(quartzJob);
} finally {
quartzLogRepository.save(log);
}
}
}
package me.zhengjie.quartz.utils;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.common.exception.BadRequestException;
import me.zhengjie.quartz.domain.QuartzJob;
import org.quartz.*;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import static org.quartz.TriggerBuilder.newTrigger;
/**
* @author jie
* @date 2019-01-07
*/
@Slf4j
@Component
public class QuartzManage {
private static final String JOB_NAME = "TASK_";
@Resource(name = "scheduler")
private Scheduler scheduler;
public void addJob(QuartzJob quartzJob){
try {
// 构建job信息
JobDetail jobDetail = JobBuilder.newJob(ExecutionJob.class).
withIdentity(JOB_NAME + quartzJob.getId()).build();
//通过触发器名和cron 表达式创建 Trigger
Trigger cronTrigger = newTrigger()
.withIdentity(JOB_NAME + quartzJob.getId())
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression()))
.build();
cronTrigger.getJobDataMap().put(QuartzJob.JOB_KEY, quartzJob);
//重置启动时间
((CronTriggerImpl)cronTrigger).setStartTime(new Date());
//执行定时任务
scheduler.scheduleJob(jobDetail,cronTrigger);
// 暂停任务
if (quartzJob.getIsPause()) {
pauseJob(quartzJob);
}
} catch (Exception e){
log.error("创建定时任务失败", e);
throw new BadRequestException(e.getMessage());
}
}
/**
* 更新job cron表达式
* @param quartzJob
* @throws SchedulerException
*/
public void updateJobCron(QuartzJob quartzJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(quartzJob.getCronExpression());
trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
//重置启动时间
((CronTriggerImpl)trigger).setStartTime(new Date());
scheduler.rescheduleJob(triggerKey, trigger);
// 暂停任务
if (quartzJob.getIsPause()) {
pauseJob(quartzJob);
}
} catch (Exception e){
log.error("更新定时任务失败", e);
throw new BadRequestException(e.getMessage());
}
}
/**
* 删除一个job
* @param quartzJob
* @throws SchedulerException
*/
public void deleteJob(QuartzJob quartzJob){
try {
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.deleteJob(jobKey);
} catch (Exception e){
log.error("删除定时任务失败", e);
throw new BadRequestException(e.getMessage());
}
}
/**
* 恢复一个job
* @param quartzJob
* @throws SchedulerException
*/
public void resumeJob(QuartzJob quartzJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 如果不存在则创建一个定时任务
if(trigger == null){
addJob(quartzJob);
}
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.resumeJob(jobKey);
} catch (Exception e){
log.error("恢复定时任务失败", e);
throw new BadRequestException(e.getMessage());
}
}
/**
* 立即执行job
* @param quartzJob
* @throws SchedulerException
*/
public void runAJobNow(QuartzJob quartzJob){
try {
TriggerKey triggerKey = TriggerKey.triggerKey(JOB_NAME + quartzJob.getId());
CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
// 如果不存在则创建一个定时任务
if(trigger == null){
addJob(quartzJob);
}
JobDataMap dataMap = new JobDataMap();
dataMap.put(QuartzJob.JOB_KEY, quartzJob);
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.triggerJob(jobKey,dataMap);
} catch (Exception e){
log.error("定时任务执行失败", e);
throw new BadRequestException(e.getMessage());
}
}
/**
* 暂停一个job
* @param quartzJob
* @throws SchedulerException
*/
public void pauseJob(QuartzJob quartzJob){
try {
JobKey jobKey = JobKey.jobKey(JOB_NAME + quartzJob.getId());
scheduler.pauseJob(jobKey);
} catch (Exception e){
log.error("定时任务暂停失败", e);
throw new BadRequestException(e.getMessage());
}
}
}
package me.zhengjie.quartz.utils;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.common.utils.SpringContextHolder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
/**
* 执行定时任务
* @author
*/
@Slf4j
public class QuartzRunnable implements Runnable {
private Object target;
private Method method;
private String params;
QuartzRunnable(String beanName, String methodName, String params)
throws NoSuchMethodException, SecurityException {
this.target = SpringContextHolder.getBean(beanName);
this.params = params;
if (StringUtils.isNotBlank(params)) {
this.method = target.getClass().getDeclaredMethod(methodName, String.class);
} else {
this.method = target.getClass().getDeclaredMethod(methodName);
}
}
@Override
public void run() {
try {
ReflectionUtils.makeAccessible(method);
if (StringUtils.isNotBlank(params)) {
method.invoke(target, params);
} else {
method.invoke(target);
}
} catch (Exception e) {
log.error("定时任务执行失败",e);
}
}
}
......@@ -162,13 +162,15 @@ public class MenuServiceImpl implements MenuService {
if(menuDTO.getPid().equals(0L)){
//一级目录需要加斜杠,不然访问不了
menuVo.setPath("/" + menuDTO.getPath());
menuVo.setRedirect("noredirect");
menuVo.setComponent(StrUtil.isEmpty(menuDTO.getComponent())?"Layout":menuDTO.getComponent());
}else if(!StrUtil.isEmpty(menuDTO.getComponent())){
menuVo.setComponent(menuDTO.getComponent());
}
menuVo.setComponent(StrUtil.isEmpty(menuDTO.getComponent())?"Layout":menuDTO.getComponent());
}
menuVo.setMeta(new MenuMetaVo(menuDTO.getName(),menuDTO.getIcon()));
if(menuDTOList!=null && menuDTOList.size()!=0){
menuVo.setAlwaysShow(true);
menuVo.setRedirect("noredirect");
menuVo.setChildren(buildMenus(menuDTOList));
// 处理是一级菜单并且没有子菜单的情况
} else if(menuDTO.getPid().equals(0L)){
......
......@@ -13,6 +13,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
......
......@@ -46,7 +46,6 @@ spring:
jpa:
properties:
hibernate:
show_sql: true
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
hibernate:
ddl-auto: update
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment