zoukankan      html  css  js  c++  java
  • 动态创建管理定时任务-已完成


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • 相关阅读:
    怎样做一个合格的程序猿
    error: No resource identifier found for attribute &#39;format24Hour&#39; in package &#39;android&#39;
    【Spark亚太研究院系列丛书】Spark实战高手之路-第一章 构建Spark集群(第五步)(4)
    Length of last word--LeetCode
    SmartController智能控制系统
    湘潭-1203-A simple problem
    android中检測网络连接状态简单总结
    AppDomain.CurrentDomain.BaseDirectory与Application.StartupPath的差别
    please set a system env PAODING_DIC_HOME or Config paoding.dic.home in paoding-dic-home.properties p
    与IBM的Lin Sun关于Istio 1.0和微服务的问答
  • 原文地址:https://www.cnblogs.com/xiaoshahai/p/11584013.html
Copyright © 2011-2022 走看看