动态创建管理定时任务-已完成


设计思路:
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())); // } }

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

  ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

 ========================================博客园对于代码块中的文字不算字数====================================================================

posted @ 2019-10-29 14:26  小傻孩丶儿  阅读(1162)  评论(0编辑  收藏  举报