设计思路:
1:通过任务名称结合反射动态拼接组成任务(jobdetail),并注入参数,实现真正的动态创建定时任务
2:可以修改时间在不重启服务的基础上
3:可以立即执行某个任务
4:重启服务后要扫描所有有效任务并启动
5:支持再不重启服务的基础上 暂停,恢复,删除任务
6: 只需要一张表
7: 代码不能上传,只能硬贴啦,对于伸手党抱歉,代码均已运行保证正确,若有错误可以给我留言
定时任务的表
--定时任务 oracle版的sql --job_status 是任务的状态 0启用1暂停 --task_parameter代表任务的方法参数 用逗号分割,按照顺序 CREATE TABLE quartz_config ( job_name VARCHAR2(50 BYTE), job_group VARCHAR2(50 BYTE), job_description VARCHAR2(500 BYTE), cron_expression VARCHAR2(500 BYTE), job_status NUMBER(10, 0), create_time DATE, update_time DATE, create_user VARCHAR2(255 BYTE), task_parameter VARCHAR2(4000 BYTE), PRIMARY KEY ( job_name, job_group ) )
这个是定时任务的目录
TaskRunner.java package com.itstyle.quartz.config; import java.util.List; import javax.annotation.Resource; import org.quartz.Scheduler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import com.itstyle.quartz.dynamicquery.Service.QuartzConfigService; import com.itstyle.quartz.entity.QuartzConfigModel; import com.itstyle.quartz.web.JobService; /** * 启动时扫描所有的有效定时任务并启动 */ @Component public class TaskRunner implements ApplicationRunner { private final static Logger LOGGER = LoggerFactory.getLogger(TaskRunner.class); private final Integer VALID = 0; @Resource Scheduler scheduler; @Resource QuartzConfigService quartzConfigService; @Resource JobService jobService; @Override public void run(ApplicationArguments var) throws Exception { LOGGER.info("初始化任务"); List<QuartzConfigModel> quartzs = quartzConfigService.findByCondition(null, null, VALID); if (!CollectionUtils.isEmpty(quartzs)) { quartzs.forEach(n -> { try { jobService.startJob(n.getId().getJobName(), n.getId().getJobGroup(), n.getJobDescription(), n.getTaskParameter(), n.getCronExpression()); } catch (Exception e) { LOGGER.error("初始化任务失败"); } }); } } }
GenericRepository.java package com.itstyle.quartz.dynamicquery.Repository; import java.io.Serializable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.repository.NoRepositoryBean; /** * * * @param <T> * @param <ID> */ @NoRepositoryBean public interface GenericRepository<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> { }
QuartzConfigRepository.java package com.itstyle.quartz.dynamicquery.Repository; import org.springframework.stereotype.Repository; import com.itstyle.quartz.entity.QuartzConfigModel; import com.itstyle.quartz.entity.identity.QuartzConfigIdentity; @Repository public interface QuartzConfigRepository extends GenericRepository<QuartzConfigModel, QuartzConfigIdentity> { }
QuartzConfigServiceImpl.java package com.itstyle.quartz.dynamicquery.Service.Impl; import java.util.ArrayList; import java.util.List; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import com.itstyle.quartz.dynamicquery.Repository.QuartzConfigRepository; import com.itstyle.quartz.dynamicquery.Service.GenericRepositoryServiceImpl; import com.itstyle.quartz.dynamicquery.Service.QuartzConfigService; import com.itstyle.quartz.entity.QuartzConfigModel; import com.itstyle.quartz.entity.identity.QuartzConfigIdentity; @SuppressWarnings("all") @Service public class QuartzConfigServiceImpl extends GenericRepositoryServiceImpl<QuartzConfigModel, QuartzConfigIdentity, QuartzConfigRepository> implements QuartzConfigService { @Autowired QuartzConfigRepository repository; @Override public List<QuartzConfigModel> findByCondition(String jobName, String jobGroup, Integer jobStatus) { return findAll(findByConditionSpec(jobName, jobGroup, jobStatus)); } private Specification<QuartzConfigModel> findByConditionSpec(String jobName, String jobGroup, Integer jobStatus) { return new Specification<QuartzConfigModel>() { @Override public Predicate toPredicate(Root<QuartzConfigModel> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { List<Predicate> predicates = new ArrayList<Predicate>(); if (!StringUtils.isEmpty(jobName)) { predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("id").get("jobName"), jobName))); } if (!StringUtils.isEmpty(jobGroup)) { predicates .add(criteriaBuilder.and(criteriaBuilder.equal(root.get("id").get("jobGroup"), jobGroup))); } if (jobStatus != null) { predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("jobStatus"), jobStatus))); } query.where(predicates.toArray(new Predicate[predicates.size()])); return query.getRestriction(); } }; } }
GenericRepositoryService.java package com.itstyle.quartz.dynamicquery.Service; import java.io.Serializable; import java.util.HashMap; import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import com.itstyle.quartz.dynamicquery.Repository.GenericRepository; /** * * * @param <CT> * @param <KT> * @param <RT> */ public interface GenericRepositoryService<CT, KT extends Serializable, RT extends GenericRepository<CT, KT>> { List<CT> findAll(); Page<CT> findAll(Pageable pageable); Page<CT> findAll(String searchTerm, Pageable pageable); Page<CT> findAll(Specification<CT> spec, Pageable pageable); List<CT> findAll(Specification<CT> spec); CT findOne(KT id); CT save(CT entity); List<CT> save(List<CT> entities); long count(); long count(Specification<CT> spec); void delete(CT entity); void delete(KT id); void deleteAll(); void deleteInBatch(List<CT> entities); CT saveAndFlush(CT entity); boolean exists(KT id); void executeQuery(String sqlString); CT findOneByPrimaryKeyValue(String fieldName, Object value); void executeNamedQuery(String sqlString); void executeNamedQuery(String sqlString, HashMap<String, String> map); CT findOne(Specification<CT> spec); }
GenericRepositoryServiceImpl.java package com.itstyle.quartz.dynamicquery.Service; import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Optional; import javax.persistence.LockModeType; import org.hibernate.exception.ConstraintViolationException; import org.hibernate.id.IdentifierGenerationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.Lock; import org.springframework.transaction.annotation.Transactional; import com.itstyle.quartz.dynamicquery.Repository.GenericRepository; public abstract class GenericRepositoryServiceImpl<CT, KT extends Serializable, RT extends GenericRepository<CT, KT>> implements GenericRepositoryService<CT, KT, RT> { private final Logger LOGGER = LoggerFactory.getLogger(getClass()); @Autowired private GenericRepository<CT, KT> repository; @Override public List<CT> findAll() { LOGGER.debug("findAll"); return repository.findAll(); } @Override public Page<CT> findAll(Pageable pageable) { LOGGER.debug("findAll"); return repository.findAll(pageable); } @Override public Page<CT> findAll(String searchTerm, Pageable pageable) { return null; } @Override public Page<CT> findAll(Specification<CT> spec, Pageable pageable) { LOGGER.debug("findAll->Specification:{}, Pageable:{}", spec, pageable); return repository.findAll(spec, pageable); } @Override public List<CT> findAll(Specification<CT> spec) { LOGGER.debug("findAll->Specification:{}", spec); return repository.findAll(spec); } @Override @Transactional @Lock(LockModeType.WRITE) public CT save(CT entity) { LOGGER.debug("GenericRepositoryService#save"); try { return repository.save(entity); } catch (IdentifierGenerationException e) { // 未定义数据主键值 } catch (ConstraintViolationException e) { // 外键关联数据不存在 } return null; } @Override @Transactional @Lock(LockModeType.WRITE) public List<CT> save(List<CT> entities) { LOGGER.debug("GenericRepositoryService#save"); try { return repository.saveAll(entities); } catch (IdentifierGenerationException e) { // 未定义数据主键值 } catch (ConstraintViolationException e) { // 外键关联数据不存在 } catch (IllegalArgumentException e) { // 非法参数异常 } return null; } @Override @Transactional @Lock(LockModeType.WRITE) public CT saveAndFlush(CT entity) { LOGGER.debug("saveAndFlush"); return repository.saveAndFlush(entity); } @Override // @Transactional(readOnly = true) public long count() { LOGGER.debug("count"); return repository.count(); } @Override // @Transactional(readOnly = true) public long count(Specification<CT> spec) { LOGGER.debug("count"); return repository.count(spec); } @Override // @Transactional(readOnly = true) public boolean exists(KT id) { LOGGER.debug("exists"); return repository.existsById(id); } @Override @Transactional @Lock(LockModeType.WRITE) public void delete(CT entity) { LOGGER.debug("delete# Parameter:{}", entity); if (entity != null) { repository.delete(entity); } } @Override @Transactional @Lock(LockModeType.WRITE) public void delete(KT id) { LOGGER.debug("delete# Parameter:{}", id); repository.deleteById(id); } @Override @Transactional @Lock(LockModeType.WRITE) public void deleteAll() { LOGGER.debug("deleteAll"); repository.deleteAll(); } @Override @Transactional @Lock(LockModeType.WRITE) public void deleteInBatch(List<CT> entities) { LOGGER.debug("deleteInBatch"); repository.deleteInBatch(entities); } @Override public void executeQuery(String sqlString) { } @Override public void executeNamedQuery(String sqlString) { } @Override public void executeNamedQuery(String sqlString, HashMap<String, String> map) { } @Override public CT findOne(KT id) { LOGGER.debug("GenericRepositoryService#findOne(KT)"); Optional<CT> bean = repository.findById(id); if (bean.isPresent()) { return bean.get(); } else { return null; } // return repository.findById(id).get(); } @Override public CT findOneByPrimaryKeyValue(String fieldName, Object value) { return null; } @Override public CT findOne(Specification<CT> spec) { Optional<CT> option = repository.findOne(spec); if (option.isPresent()) { return option.get(); } else { return null; } } }
QuartzConfigService.java package com.itstyle.quartz.dynamicquery.Service; import java.util.List; import com.itstyle.quartz.dynamicquery.Repository.QuartzConfigRepository; import com.itstyle.quartz.entity.QuartzConfigModel; import com.itstyle.quartz.entity.identity.QuartzConfigIdentity; public interface QuartzConfigService extends GenericRepositoryService<QuartzConfigModel, QuartzConfigIdentity, QuartzConfigRepository> { List<QuartzConfigModel> findByCondition(String jobName, String jobGroup, Integer jobStatus); }
QuartzConfigIdentity.java package com.itstyle.quartz.entity.identity; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable public class QuartzConfigIdentity implements Serializable { /** * */ private static final long serialVersionUID = -6107873034694904498L; @Column(name = "JOB_NAME") private String jobName;// 任务名称 @Column(name = "JOB_GROUP") private String jobGroup;// 任务分组 public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobGroup() { return jobGroup; } public void setJobGroup(String jobGroup) { this.jobGroup = jobGroup; } public QuartzConfigIdentity(String jobName, String jobGroup) { super(); this.jobName = jobName; this.jobGroup = jobGroup; } public QuartzConfigIdentity() { super(); // TODO Auto-generated constructor stub } }
QuartzConfigModel.java package com.itstyle.quartz.entity; import java.io.Serializable; import java.util.Date; import javax.persistence.Column; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import javax.persistence.Table; import com.itstyle.quartz.entity.identity.QuartzConfigIdentity; /** * 任务类 创建者 */ @Entity @Table(name = "QUARTZ_CONFIG") public class QuartzConfigModel implements Serializable { /** * */ private static final long serialVersionUID = 2001992304078127000L; @EmbeddedId private QuartzConfigIdentity id; @Column(name = "JOB_DESCRIPTION") private String jobDescription;// 任务描述 @Column(name = "CRON_EXPRESSION") private String cronExpression;// 执行时间 @Column(name = "JOB_STATUS") private Integer jobStatus;// 任务状态 @Column(name = "CREATE_TIME") private Date createTime;// 创建时间 @Column(name = "UPDATE_TIME") private Date updateTime;// 更新时间 @Column(name = "CREATE_USER") private String createUser;// 创建者 @Column(name = "TASK_PARAMETER") private String taskParameter; public String getTaskParameter() { return taskParameter; } public void setTaskParameter(String taskParameter) { this.taskParameter = taskParameter; } public String getJobDescription() { return jobDescription; } public void setJobDescription(String jobDescription) { this.jobDescription = jobDescription; } public String getCronExpression() { return cronExpression; } public void setCronExpression(String cronExpression) { this.cronExpression = cronExpression; } public Integer getJobStatus() { return jobStatus; } public void setJobStatus(Integer jobStatus) { this.jobStatus = jobStatus; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime = createTime; } public Date getUpdateTime() { return updateTime; } public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } public String getCreateUser() { return createUser; } public void setCreateUser(String createUser) { this.createUser = createUser; } public QuartzConfigIdentity getId() { return id; } public void setId(QuartzConfigIdentity id) { this.id = id; } @PrePersist public void save() { createTime = new Date(); jobStatus = 0; } @PreUpdate public void update() { updateTime = new Date(); } }
ResponseData.java package com.itstyle.quartz.entity; import org.springframework.http.ResponseEntity; public class ResponseData<T> { public int code; public Boolean success; public T data; public T getData() { return data; } public void setData(T data) { this.data = data; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public Boolean getSuccess() { return success; } public void setSuccess(Boolean success) { this.success = success; } public ResponseData() { super(); this.code = 0; this.success = Boolean.TRUE; } public ResponseData(T data) { super(); this.code = 0; this.success = Boolean.TRUE; this.data = data; } public ResponseData(int code, Boolean success, T data) { super(); this.code = code; this.success = success; this.data = data; } public static <T> ResponseEntity<?> ok() { return ResponseEntity.ok(new ResponseData()); } public static <T> ResponseEntity<?> ok(T data) { return ResponseEntity.ok(new ResponseData(data)); } public static ResponseEntity<?> error() { return ResponseEntity.ok(new ResponseData(-1, false, null)); } public static ResponseEntity<?> error(String errorCode) { return ResponseEntity.ok(new ResponseData(-1, false, errorCode)); } public static ResponseEntity<?> error(Throwable t) { return ResponseEntity.ok(new ResponseData(-1, false, t)); } }
DynamicQuartzJob.java package com.itstyle.quartz.job; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.PersistJobDataAfterExecution; import org.quartz.impl.JobDetailImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.util.StringUtils; /** * 动态定时任务Job * * @author linrx1 * */ @PersistJobDataAfterExecution @DisallowConcurrentExecution // 不允许并发执行 public class DynamicQuartzJob extends QuartzJobBean { private static final Logger logger = LoggerFactory.getLogger(DynamicQuartzJob.class); @Autowired private ApplicationContext applicationContext; @Override protected void executeInternal(JobExecutionContext jobexecutioncontext) throws JobExecutionException { // use JobDetailImpl replace JobDetail for get jobName JobDetailImpl jobDetail = (JobDetailImpl) jobexecutioncontext.getJobDetail(); String name = jobDetail.getName(); if (StringUtils.isEmpty(name)) { throw new JobExecutionException("can not find service info, because desription is empty"); } String[] serviceInfo = name.split("\."); // serviceInfo[0] is JOB_NAME_PREFIX String beanName = serviceInfo[1]; String methodName = serviceInfo[2]; Object serviceImpl = applicationContext.getBean(beanName); JobDataMap dataMap = jobDetail.getJobDataMap(); Method method; try { Class<?> clazz = serviceImpl.getClass(); Method[] methods = clazz.getDeclaredMethods(); Class<?>[] parameterTypes = null; for (Method n : methods) { if (methodName.equals(n.getName())) { parameterTypes = n.getParameterTypes(); } } Object[] array = parameterTypeConvert(parameterTypes, dataMap.get("data")); method = serviceImpl.getClass().getMethod(methodName, parameterTypes); logger.info("dynamic invoke {}.{}()", serviceImpl.getClass().getName(), methodName); System.out.println(parameterTypes[0]); method.invoke(serviceImpl, array); } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { logger.error("reflect invoke service method error", e); } } private Object[] parameterTypeConvert(Class<?>[] parameterTypes, Object obj) { Object[] temp = new Object[parameterTypes.length]; String[] array = (String[]) obj; for (int i = 0; i < parameterTypes.length; i++) { if (parameterTypes[i].toString().equals("class java.lang.String")) { System.out.println("String"); temp[i] = String.valueOf(array[i]); } if (parameterTypes[i].toString().equals("class java.lang.Integer")) { System.out.println("Integer"); temp[i] = Integer.valueOf(array[i]); } if (parameterTypes[i].toString().equals("class java.lang.Double")) { System.out.println("Double"); temp[i] = Double.valueOf(array[i]); } } return temp; } }
改进 package com.sony.sie.hrevaluate.quartz.job; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.PersistJobDataAfterExecution; import org.quartz.impl.JobDetailImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.util.StringUtils; import net.sf.json.JSONObject; /** * 动态定时任务Job * * @author linrx1 * */ @PersistJobDataAfterExecution @DisallowConcurrentExecution // 不允许并发执行 public class DynamicQuartzJob extends QuartzJobBean { private static final Logger logger = LoggerFactory.getLogger(DynamicQuartzJob.class); @Autowired private ApplicationContext applicationContext; @Override protected void executeInternal(JobExecutionContext jobexecutioncontext) throws JobExecutionException { // use JobDetailImpl replace JobDetail for get jobName JobDetailImpl jobDetail = (JobDetailImpl) jobexecutioncontext.getJobDetail(); String name = jobDetail.getName(); if (StringUtils.isEmpty(name)) { throw new JobExecutionException("can not find service info, because desription is empty"); } String[] serviceInfo = name.split("\."); // serviceInfo[0] is JOB_NAME_PREFIX String beanName = serviceInfo[1]; // methodName & modelName String methodName = serviceInfo[2]; Object beanNameContext = applicationContext.getBean(beanName); Object modelNameContext = applicationContext.getBean(methodName); // method parameter JobDataMap dataMap = jobDetail.getJobDataMap(); try { Class beanNameCls = beanNameContext.getClass(); Class modelNameCls = modelNameContext.getClass(); Object object = JSONObject.toBean(JSONObject.fromObject(dataMap.get("data")), modelNameCls); Class<?>[] parameterTypes = null; Method[] methods = beanNameCls.getMethods(); Parameter[] invokeMethodParams; // the array size may be not enough for (Method n : methods) { if (methodName.equals(n.getName())) { parameterTypes = n.getParameterTypes(); invokeMethodParams = n.getParameters(); Object[] invokeParam = new Object[invokeMethodParams.length]; for (int i = 0; i < invokeMethodParams.length; i++) { String parameterName = invokeMethodParams[i].getName(); Field field = modelNameCls.getDeclaredField(parameterName); field.setAccessible(true); invokeParam[i] = field.get(object); } Method method = beanNameCls.getMethod(methodName, parameterTypes); method.invoke(beanNameCls.newInstance(), invokeParam); } } logger.info("dynamic invoke {}.{}()", beanNameContext.getClass().getName(), methodName); } catch (Exception e) { logger.error("reflect invoke service method error", e); } } }
改进 package com.itstyle.quartz.job; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.PersistJobDataAfterExecution; import org.quartz.impl.JobDetailImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.scheduling.quartz.QuartzJobBean; import org.springframework.util.StringUtils; import net.sf.json.JSONObject; /** * 动态定时任务Job * * */ @PersistJobDataAfterExecution @DisallowConcurrentExecution // 不允许并发执行 public class DynamicQuartzJob extends QuartzJobBean { private static final Logger logger = LoggerFactory.getLogger(DynamicQuartzJob.class); @Autowired private ApplicationContext applicationContext; @Override protected void executeInternal(JobExecutionContext jobexecutioncontext) throws JobExecutionException { // use JobDetailImpl replace JobDetail for get jobName JobDetailImpl jobDetail = (JobDetailImpl) jobexecutioncontext.getJobDetail(); String name = jobDetail.getName(); if (StringUtils.isEmpty(name)) { throw new JobExecutionException("can not find service info, because desription is empty"); } String[] serviceInfo = name.split("\."); // serviceInfo[0] is JOB_NAME_PREFIX String beanName = serviceInfo[1]; // methodName & modelName String methodName = serviceInfo[2]; Object beanNameContext = applicationContext.getBean(beanName); Object modelNameContext = applicationContext.getBean(methodName); // method parameter JobDataMap dataMap = jobDetail.getJobDataMap(); try { Class beanNameCls = beanNameContext.getClass(); Class modelNameCls = modelNameContext.getClass(); Object object = modelNameCls.newInstance(); object = JSONObject.toBean(JSONObject.fromObject(dataMap.get("data")), modelNameCls); Class<?>[] parameterTypes = null; Method[] methods = beanNameCls.getMethods(); Parameter[] invokeMethodParams; // the array size may be not enough for (Method n : methods) { if (methodName.equals(n.getName())) { parameterTypes = n.getParameterTypes(); invokeMethodParams = n.getParameters(); Object[] invokeParam = new Object[invokeMethodParams.length]; try { for (int i = 0; i < invokeMethodParams.length; i++) { String parameterName = invokeMethodParams[i].getName(); Field field = modelNameCls.getDeclaredField(parameterName); field.setAccessible(true); invokeParam[i] = field.get(object); } } catch (NoSuchFieldException e) { int i = 0; invokeParam = new Object[invokeMethodParams.length]; for (Field field : modelNameCls.getDeclaredFields()) { field.setAccessible(true); if ("serialVersionUID".equals(field.getName())) { continue; } invokeParam[i] = field.get(object); i++; } } Method method = beanNameCls.getMethod(methodName, parameterTypes); method.invoke(beanNameCls.newInstance(), invokeParam); } } logger.info("dynamic invoke {}.{}()", beanNameContext.getClass().getName(), methodName); } catch (Exception e) { logger.error("reflect invoke service method error", e); } } }
AddJobRequest.java package com.itstyle.quartz.request; public class AddJobRequest { private String jobName;// 任务名称 private String jobGroup;// 任务分组 private String jobDescription;// 任务描述 private String cronExpression;// 执行时间 private String taskParameter; public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobGroup() { return jobGroup; } public void setJobGroup(String jobGroup) { this.jobGroup = jobGroup; } public String getJobDescription() { return jobDescription; } public void setJobDescription(String jobDescription) { this.jobDescription = jobDescription; } public String getCronExpression() { return cronExpression; } public void setCronExpression(String cronExpression) { this.cronExpression = cronExpression; } public String getTaskParameter() { return taskParameter; } public void setTaskParameter(String taskParameter) { this.taskParameter = taskParameter; } } FindAllJobRequest.java package com.itstyle.quartz.request; public class FindAllJobRequest { private Integer pageSize; private Integer pageNo; public Integer getPageSize() { return pageSize; } public void setPageSize(Integer pageSize) { this.pageSize = pageSize; } public Integer getPageNo() { return pageNo; } public void setPageNo(Integer pageNo) { this.pageNo = pageNo; } } PauseAndResumeRequest.java package com.itstyle.quartz.request; public class PauseAndResumeRequest { private String jobName;// 任务名称 private String jobGroup;// 任务分组 public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobGroup() { return jobGroup; } public void setJobGroup(String jobGroup) { this.jobGroup = jobGroup; } } RemoveJobRequest.java package com.itstyle.quartz.request; public class RemoveJobRequest { private String jobName; private String jobGroup; public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobGroup() { return jobGroup; } public void setJobGroup(String jobGroup) { this.jobGroup = jobGroup; } } TriggerRequest.java package com.itstyle.quartz.request; public class TriggerRequest { private String jobName; private String jobGroup; public String getJobName() { return jobName; } public void setJobName(String jobName) { this.jobName = jobName; } public String getJobGroup() { return jobGroup; } public void setJobGroup(String jobGroup) { this.jobGroup = jobGroup; } }
HelloService.java package com.itstyle.quartz.service; import org.springframework.stereotype.Service; @Service public class HelloService { public void sayHello(String aa, Integer bb) { System.out.format("%s %d", aa, bb); } }
JobController.java package com.itstyle.quartz.web; import javax.annotation.Resource; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import com.itstyle.quartz.dynamicquery.Service.QuartzConfigService; import com.itstyle.quartz.entity.ResponseData; import com.itstyle.quartz.request.AddJobRequest; import com.itstyle.quartz.request.FindAllJobRequest; import com.itstyle.quartz.request.PauseAndResumeRequest; import com.itstyle.quartz.request.RemoveJobRequest; import com.itstyle.quartz.request.TriggerRequest; @RestController public class JobController { private final static Logger LOGGER = LoggerFactory.getLogger(JobController.class); @Resource Scheduler scheduler; @Resource QuartzConfigService quartzConfigService; @Resource JobService jobService; @PostMapping("/add") public ResponseEntity<?> addJob(@RequestBody AddJobRequest req) throws Exception { LOGGER.info("add quartz job"); String result = jobService.addjob(req.getJobName(), req.getJobGroup(), req.getCronExpression(), req.getJobDescription(), req.getTaskParameter()); return ResponseData.ok(result); } @PostMapping("/list") public ResponseEntity<?> findAllJob(@RequestBody FindAllJobRequest req) { LOGGER.info("任务列表"); Page page = quartzConfigService.findAll(PageRequest.of(req.getPageNo(), req.getPageSize())); return ResponseData.ok(page); } @PostMapping("/trigger") public ResponseEntity<?> trigger(@RequestBody TriggerRequest req) throws Exception { LOGGER.info("触发任务"); String result = jobService.triggerJob(req.getJobName(), req.getJobGroup()); return ResponseData.ok(result); } @PostMapping("/remove") public ResponseEntity<?> remove(@RequestBody RemoveJobRequest req) throws SchedulerException { LOGGER.info("移除任务"); String result = jobService.deleteJob(req.getJobName(), req.getJobGroup()); return ResponseData.ok(result); } @PostMapping("/pause") public ResponseEntity<?> pause(@RequestBody PauseAndResumeRequest req) throws SchedulerException { LOGGER.info("停止任务"); String result = jobService.pause(req.getJobName(), req.getJobGroup()); return ResponseData.ok(result); } @PostMapping("/resume") public ResponseEntity<?> resume(@RequestBody PauseAndResumeRequest req) throws SchedulerException { LOGGER.info("恢复任务"); String result = jobService.resume(req.getJobName(), req.getJobGroup()); return ResponseData.ok(result); } }
JobService.java package com.itstyle.quartz.web; import java.security.Principal; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.transaction.Transactional; import org.quartz.CronScheduleBuilder; import org.quartz.JobBuilder; import org.quartz.JobDetail; import org.quartz.JobKey; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.Trigger; import org.quartz.TriggerBuilder; import org.quartz.TriggerKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import com.itstyle.quartz.dynamicquery.Service.QuartzConfigService; import com.itstyle.quartz.entity.QuartzConfigModel; import com.itstyle.quartz.entity.identity.QuartzConfigIdentity; @Service @SuppressWarnings("all") public class JobService { private final Logger logger = LoggerFactory.getLogger(getClass()); private final String JOBCLASSNAME = "com.itstyle.quartz.job.DynamicQuartzJob"; private final Integer VALID = 0; private final Integer INVALID = 1; @Resource ApplicationContext applicationContext; @Resource Scheduler scheduler; @Resource QuartzConfigService quartzConfigService; @Transactional public String pause(String jobName, String jobGroup) throws SchedulerException { JobKey key = new JobKey(jobName, jobGroup); if (scheduler.checkExists(key)) { scheduler.pauseJob(key); QuartzConfigModel quartzConfigModel = quartzConfigService .findOne(new QuartzConfigIdentity(jobName, jobGroup)); quartzConfigModel.setJobStatus(INVALID); quartzConfigService.save(quartzConfigModel); return "ok"; } else { return "任务不存在"; } } @Transactional public String resume(String jobName, String jobGroup) throws SchedulerException { JobKey key = new JobKey(jobName, jobGroup); if (scheduler.checkExists(key)) { scheduler.resumeJob(key); QuartzConfigModel quartzConfigModel = quartzConfigService .findOne(new QuartzConfigIdentity(jobName, jobGroup)); quartzConfigModel.setJobStatus(VALID); quartzConfigService.save(quartzConfigModel); return "ok"; } else { return "任务不存在"; } } public String triggerJob(String jobName, String jobGroup) throws Exception { JobKey jobKey = new JobKey(jobName, jobGroup); if (scheduler.checkExists(jobKey)) { scheduler.triggerJob(jobKey); return "ok"; } else { return "任務不存在"; } } @Transactional public String addjob(String jobName, String jobGroup, String cronExpression, String jobDescription, String taskParameter) throws Exception { JobKey jobKey = new JobKey(jobName, jobGroup); boolean isExists = scheduler.checkExists(jobKey); if (isExists) { return "已存在"; } startJob(jobName, jobGroup, jobDescription, taskParameter, cronExpression); saveQuartzConfigMoel(jobName, jobGroup, cronExpression, jobDescription, taskParameter); return null; } @Transactional public String deleteJob(String jobName, String jobGroup) throws SchedulerException { TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup); // ‘停止触发器 if (scheduler.checkExists(triggerKey)) { scheduler.pauseTrigger(triggerKey); // ’ 移除触发器 scheduler.unscheduleJob(triggerKey); } JobKey jobKey = new JobKey(jobName, jobGroup); if (scheduler.checkExists(jobKey)) { // ‘删除任务 scheduler.deleteJob(jobKey); quartzConfigService.delete(new QuartzConfigIdentity(jobName, jobGroup)); return "ok"; } else { return "任务不存在"; } } public void startJob(String jobName, String jobGroup, String description, String taskParameter, String cronExpression) throws Exception { Class cls = Class.forName(JOBCLASSNAME); cls.newInstance(); JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, jobGroup).withDescription(description) .build(); jobDetail.getJobDataMap().put("data", taskParameter.split(",")); CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression); Trigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup).startNow() .withSchedule(cronScheduleBuilder).build(); scheduler.scheduleJob(jobDetail, trigger); } private void saveQuartzConfigMoel(String jobName, String jobGroup, String cronExpression, String jobDescription, String taskParameter) { QuartzConfigModel quartzConfigModel = new QuartzConfigModel(); QuartzConfigIdentity id = new QuartzConfigIdentity(jobName, jobGroup); quartzConfigModel.setId(id); quartzConfigModel.setCronExpression(cronExpression); quartzConfigModel.setJobDescription(jobDescription); quartzConfigModel.setTaskParameter(taskParameter); HttpServletRequest req = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); quartzConfigModel.setCreateUser(getHttpRequestUserGid(req)); quartzConfigService.save(quartzConfigModel); } /** * 获取token中的用户 * * @param request HttpServletRequest情報 * @return */ private String getHttpRequestUserGid(HttpServletRequest request) { Principal principal = request.getUserPrincipal(); if (principal == null) { return ""; } else { String userName = principal.getName(); if (userName != null && userName.indexOf("@") > 0) { return userName.split("@")[0]; } else { return userName; } } } }
DateToCronUtil.java
//转化date到cron package com.itstyle.quartz; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import org.quartz.CronExpression; public class DateToCronUtil { private static final String DATEFORMAT = "ss mm HH dd MM ? yyyy"; /*** * * @param date * @param dateFormat : e.g:yyyy-MM-dd HH:mm:ss * @return * @throws ParseException */ public static String formatDateByPattern(Date date, String dateFormat) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); String formatTimeStr = null; if (date != null) { formatTimeStr = sdf.format(date); } if (checkCronValid(formatTimeStr, date)) { return formatTimeStr; } else { return "输入有效日期"; } } /*** * convert Date to cron ,eg. "0 06 10 15 1 ? 2014" * * @param date : 时间点 * @return * @throws ParseException */ public static String getCron(Date date) throws ParseException { return formatDateByPattern(date, DATEFORMAT); } /** * 验证是否有效的cron表达式 * * @param cron * @param date * @throws ParseException */ private static boolean checkCronValid(String cron, Date date) throws ParseException { CronExpression cronExpression = new CronExpression(cron); return cronExpression.isSatisfiedBy(date); } // public static void main(String[] args) throws ParseException { // System.out.println(getCron(new Date())); // } }
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================
========================================博客园对于代码块中的文字不算字数====================================================================