Spring4.2.5完美整合Java定时器大哥Quartz

3 篇文章 0 订阅
2 篇文章 0 订阅

最近有业务需求要用户自定义一个定时器,最开始想用spring自带的@Scheduled,但是需要用户自定义且要求较高,果断放弃,最后使用Java的定时器大哥Quartz,完没解决需求。不多说直接上码:

pom.xml 中添加

其他的spring相关jar包项目开发应该都整合了

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.2.1</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
</dependency>

Quartz相关方法

import com.css.taskManage.bean.ScheduleJob;
import com.css.taskManage.service.ScheduleJobManageService;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QuartzManager {

    public final static transient Logger log = LoggerFactory.getLogger(QuartzManager.class);

    //这里可以用new的但是在服务器关闭后,定时器的线程没有关
    //private static SchedulerFactory schedulerFactory=new SchedulerFactory();

    private static Scheduler sched;
    //将定时器交给容器管理!
    static{
        sched = (Scheduler) SpringContextUtil.getBean("schedulerFactoryBean");
    }

    /**
     * @Description: 添加一个定时任务
     * @ jobName 任务名
     * @ jobGroupName  任务组名
     * @ triggerName 触发器名
     * @ triggerGroupName 触发器组名
     * @ jobClass  任务
     * @ cron   时间设置,参考quartz说明文档
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void addJob(ScheduleJob scheduleJob, Class jobClass, ScheduleJobManageService service) {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();
            // 任务名,任务组,任务执行类
            JobDetail jobDetail= JobBuilder.newJob(jobClass).withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup())
                    .build();
            jobDetail.getJobDataMap().put("ScheduleJobManageService", service);
            jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
            // 触发器
            TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
            // 触发器名,触发器组
            triggerBuilder.withIdentity(scheduleJob.getTriggerName(),scheduleJob.getTriggerGroupName());
            triggerBuilder.startNow();
            // 触发器时间设定
            triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression()));
            // 创建Trigger对象
            CronTrigger trigger = (CronTrigger) triggerBuilder.build();
            // 调度容器设置JobDetail和Trigger
            sched.scheduleJob(jobDetail, trigger);
            // 启动
            if (!sched.isShutdown()) {
                sched.start();
            }
           log.info(scheduleJob.getJobName()+scheduleJob.getJobGroup()+"定时器已经启动");
        } catch (Exception e) {
            log.error(scheduleJob.getJobName()+scheduleJob.getJobGroup()+"定时任务启动失败",e);
            throw new RuntimeException(e);
        }
    }
    /**
     * @Description: 修改一个任务的触发时间
     * @param jobName
     * @param jobGroupName
     * @param triggerName 触发器名
     * @param triggerGroupName 触发器组名
     * @param cron   时间设置,参考quartz说明文档
     */
    public static void modifyJobTime(String jobName,String jobGroupName, String triggerName, String triggerGroupName, String cron) {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(triggerName, triggerGroupName);
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);
            if (trigger == null) {
                return;
            }
            String oldTime = trigger.getCronExpression();
            if (!oldTime.equalsIgnoreCase(cron)) {
                /** 方式一 :调用 rescheduleJob 开始 */
                // 触发器
                TriggerBuilder<Trigger> triggerBuilder = TriggerBuilder.newTrigger();
                // 触发器名,触发器组
                triggerBuilder.withIdentity(triggerName, triggerGroupName);
                triggerBuilder.startNow();
                // 触发器时间设定
                triggerBuilder.withSchedule(CronScheduleBuilder.cronSchedule(cron));
                // 创建Trigger对象
                trigger = (CronTrigger) triggerBuilder.build();
                // 方式一 :修改一个任务的触发时间
                sched.rescheduleJob(triggerKey, trigger);
                /** 方式一 :调用 rescheduleJob 结束 */

                /** 方式二:先删除,然后在创建一个新的Job  */
                //JobDetail jobDetail = sched.getJobDetail(JobKey.jobKey(jobName, jobGroupName));
                //Class<? extends Job> jobClass = jobDetail.getJobClass();
                //removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
                //addJob(jobName, jobGroupName, triggerName, triggerGroupName, jobClass, cron);
                /** 方式二 :先删除,然后在创建一个新的Job */
            }
//            log.info(scheduleJob.getJobName()+scheduleJob.getJobGroup()+"定时器已经启动");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * @Description: 移除一个任务
     */
    public static void removeJob(ScheduleJob scheduleJob) {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();
            TriggerKey triggerKey = TriggerKey.triggerKey(scheduleJob.getTriggerName(), scheduleJob.getTriggerGroupName());
            sched.pauseTrigger(triggerKey);// 停止触发器
            sched.unscheduleJob(triggerKey);// 移除触发器
            sched.deleteJob(JobKey.jobKey(scheduleJob.getJobName(), scheduleJob.getJobGroup()));// 删除任务
            log.info(scheduleJob.getJobName()+scheduleJob.getJobGroup()+"定时任务已移除");
        } catch (Exception e) {
            log.error(scheduleJob.getJobName()+scheduleJob.getJobGroup()+"定时任务移除失败",e);
            throw new RuntimeException(e);
        }
    }
    /**
     * @Description:启动所有定时任务
     */
    public static void startJobs() {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();
            sched.start();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @Description:关闭所有定时任务
     */
    public static void shutdownJobs() {
        try {
//            Scheduler sched = schedulerFactory.getScheduler();
            if (!sched.isShutdown()) {
                sched.shutdown();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

spring-*的配置文件中加入

<!--定时器的bean-->
    <bean id="schedulerFactoryBean"
          class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!--    <property name="startupDelay" value="180"/>  启动服务器后延迟启动定时任务-->
    </bean>
    <!--获取spring上下文的bean,是为了获取schedulerFactoryBean,将定时器交给spring容器管理,如果new的话,服务器关闭后,定时器并不会关闭!-->
    <bean id="springContextUtil" class="com.css.commcon.util.SpringContextUtil" lazy-init="false"/>

springContextUtil类,获取spring所管理对象的工具类

package com.css.commcon.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class SpringContextUtil implements ApplicationContextAware {

    // Spring应用上下文环境
    private static ApplicationContext applicationContext;

    /**
     * 实现ApplicationContextAware接口的回调方法。设置上下文环境
     *
     * @param applicationContext
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextUtil.applicationContext = applicationContext;
    }

    /**
     * @return ApplicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object
     * @throws BeansException
     */
    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }
}

前端页面

前端jsp页面代码

前端部分数据不全!但业务功能是没有问题的。
前端框架是ligerUI,时间选择器是My97DatePicker

<table cellpadding="0" cellspacing="0" class="l-table-edit" style="margin:0 auto;">
                <tr class="l-table-edit-tr"> </tr>
                <tr class="l-table-edit-tr">
                    <td align="right" class="l-table-edit-td">起始时间:</td>
                    <td align="left" class="l-table-edit-td-input">
                        <%--<input id="Ddl_Year1" type="text" runat="server"  onfocus="WdatePicker({skin:'default',dateFmt:'yyyy'})"/>--%>
                        <input id="startTime" name="startTime" type="text" validate="{required:true}"
                               onfocus="WdatePicker({minDate:'%y-%M-{%d}',maxDate:'#F{$dp.$D(\'endTime\')||\'%y-%M-%ld\'}'})"/>
                    </td><%--开始时间不能小于结束时间--%>
                    <td align="left"></td>

                    <td align="right" class="l-table-edit-td">结束时间:</td>
                    <td align="left" class="l-table-edit-td-input">
                        <input id="endTime" name="endTime" type="text" validate="{required:true}"
                               onfocus="WdatePicker({minDate:'#F{$dp.$D(\'startTime\')}',maxDate:'%y-%M-%ld'})"/>
                    </td>
                    <td align="left"></td>

                    <td align="right" class="l-table-edit-td">下发时间:</td>
                    <td align="left" class="l-table-edit-td-input">
                        <input id="cycleTime" type="text" name="cycleTime"  validate="{required:true}"
                               onfocus="WdatePicker({skin:'default',dateFmt:'HH:mm'})"/>
                    </td>
                    <td align="left"></td>
                </tr>
            </table>
        </form>

        <div style="margin-right: 450px;margin-top:50px; ">
            <button type="button" id="sures" name="dsa" class="choses"
                    onclick="sureOutQuartz();">确定
            </button>
        </div>
前端js页面代码
function sureOutQuartz(){
     if(jobGrid.data.Rows.length>0){
        top.$.ligerDialog.warn("你已经有定时任务存在,无法再添加!请删除后添加");
        return;
    }
    var v = $("#taskOutManages").validate({
        debug : true,
        errorPlacement : function(lable, element) {
            if (element.hasClass("l-textarea")) {
                element.ligerTip({
                    content : lable.html(),
                    target : element[0]
                });
            } else if (element.hasClass("l-text-field")) {
                element.parent().ligerTip({
                    content : lable.html(),
                    target : element[0]
                });
            } else {
                lable.appendTo(element.parents("td:first").next("td"));
            }
        },
        success : function(lable) {
            lable.ligerHideTip();
            lable.remove();
        },
        submitHandler : function() {
            $("#" + routeName + " .l-text,.l-textarea").ligerHideTip();
            subScheduleJob();
        }
    });
    if($("#taskOutManages").valid()){
        subScheduleJob();
    }
}
function subScheduleJob() {
    var data =$("#taskOutManages").serializeArray();
    var url = basePath + "rest/scheduleJobManageAction/taskQuartz";
    $.ajax({
        url : url,
        type : "post",
        dataType : "json",
        data : $.param(data),
        success : function(json) {
            $("#taskOutManages :input").not(":button, :submit, :reset, :hidden").val("").removeAttr("checked").remove("selected");
            //回调,写自己需要的业务
        },
        error : function(json) {
            //回调失败,写自己需要的业务
        }
    });
}

业务controller

@Controller
@RequestMapping("/scheduleJobManageAction")
public class ScheduleJobManageAction extends BaseSpringSupportAction<ScheduleJob, ScheduleJobManageService> {

    //@Autowired
    private ScheduleJobManageService service;

    @Override
    public ScheduleJobManageService getEntityManager() {
        return service;
    }

    public ScheduleJobManageService getService() {
        return service;
    }

    @Resource(name="scheduleJobManageService")
    public void setService(ScheduleJobManageService service) {
        this.service = service;
    }

    @RequestMapping({ "taskQuartz" })
    @ResponseBody
    public HashMap<String, Object> taskQuartz(HttpServletRequest request, ScheduleJob scheduleJob,String groups,String groupsShow) {
        try {
            String cron = "";//定时表达式,看Quartz 的API,网上有相应的解释
            String startTime = scheduleJob.getStartTime();
            String endTime = scheduleJob.getEndTime();
            String cycleTime = scheduleJob.getCycleTime();

            String[] data=startTime.split("-");
            String day=data[2]+"-"+endTime.split("-")[2];
            String[] time =  cycleTime.split(":");
            cron = "0 "+time[1]+" "+time[0]+" "+day+" "+data[1]+" ? "+ data[0] +"-"+data[0];

            SysUser user= SessionUtils.getUser(request);//装配定时器的相关属性,可以根据自己的业务自行配制
            scheduleJob.setJobName(user.getId().toString());
            scheduleJob.setJobGroup(user.getName());
            scheduleJob.setTriggerName(user.getPcode());
            scheduleJob.setTriggerGroupName(user.getAreaCode());
            scheduleJob.setCronExpression(cron);
            scheduleJob.setGroupIds(groups);
            scheduleJob.setGroupNames(groupsShow);

            QuartzManager.removeJob(scheduleJob);
            QuartzManager.addJob(scheduleJob, MyJob.class,service);
            this.save(request,scheduleJob);
            return JsonWrapper.successWrapper(scheduleJob,"定时任务已启动!");
        } catch (Exception e) {
            this.log.error(e.getMessage(),e);
            return JsonWrapper.failureWrapperMsg("系统出错,请联系管理员");
        }
    }


    @RequestMapping({ "removeQuartzJob" })
    @ResponseBody
    public HashMap<String, Object> removeQuartzJob(HttpServletRequest request, Integer id) {
        try {
            if(id==null){
                return JsonWrapper.failureWrapperMsg("定时任务的不存在,请刷新后重试!");
            }
            ScheduleJob scheduleJob = this.getEntityManager().get(id);
            if(scheduleJob==null){
                return JsonWrapper.failureWrapperMsg("定时任务的不存在,请刷新后重试!");
            }
            this.delete(id.toString());
            QuartzManager.removeJob(scheduleJob);
            return JsonWrapper.successWrapper(scheduleJob,"定时任务已移除!");
        } catch (Exception e) {
            this.log.error(e.getMessage(),e);
            return JsonWrapper.failureWrapperMsg("系统出错,请联系管理员");
        }
    }
}

任务和业务的实体

package com.css.taskManage.bean;

import com.css.commcon.bean.BaseEntity;
import com.css.commcon.util.Constant;
import com.css.commcon.util.JsonDateSerializer;
import com.css.commcon.util.StringUtil;
import com.css.sysManage.bean.SysArea;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.format.annotation.DateTimeFormat;

import javax.persistence.*;
import java.util.Date;

@Entity
@Table(name = "schedule_job")
public class ScheduleJob implements BaseEntity {


    private Integer id;
    @Column(name = "create_date")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonSerialize(using = JsonDateSerializer.class)
    private Date createDate;
    @Column(name = "update_date")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonSerialize(using = JsonDateSerializer.class)
    private Date updateDate;
    @Column(name = "job_name")
    private String jobName;
    @Column(name = "job_group")
    private String jobGroup;
    @Column(name = "job_status")
    private String jobStatus;
    @Column(name = "cron_expression")
    private String cronExpression;
    @Column(name = "description")
    private String description;
    @Column(name = "trigger_name")
    private String triggerName;
    @Column(name = "trigger_group_name")
    private String triggerGroupName;
    @Column(name = "group_ids")
    private String groupIds;
    @Column(name = "group_names")
    private String groupNames;
    @Column(name = "amount")
    private Integer amount;
    @Column(name = "start_time")
    private String startTime;
    @Column(name = "end_time")
    private String endTime;
    @Column(name = "cycle_time")
    private String cycleTime;
//getter和setter
 public ScheduleJob() {
    }

    public ScheduleJob(String jobName, String jobGroup, String triggerName, String triggerGroupName, String cronExpression) {
        this.jobName = jobName;
        this.jobGroup = jobGroup;
        this.triggerName = triggerName;
        this.triggerGroupName = triggerGroupName;
        this.cronExpression = cronExpression;
    }

定时器的方法类具体的业务类

package com.css.taskManage.job;

import com.css.commcon.util.QuartzManager;
import com.css.taskManage.bean.ScheduleJob;
import com.css.taskManage.service.ScheduleJobManageService;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MyJob implements Job {

    //这里不能直接@Autowired,如果引用的话下面的方法不能用,需要的参数,要从QuartzManager传。
    //不知道是不是我没有在类上面加注解,这里不能引用Spring管理的Bean!有兴趣可以自己试一试!

    public final transient Logger log = LoggerFactory.getLogger(MyJob.class);

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        log.info("定时器开始运行!");
        ScheduleJob scheduleJob = null;
        String jobName ="" ;
        String jobGroupName ="";
        try {
            ScheduleJobManageService service = (ScheduleJobManageService) jobExecutionContext.getJobDetail().getJobDataMap().get("ScheduleJobManageService");
            scheduleJob = (ScheduleJob) jobExecutionContext.getJobDetail().getJobDataMap().get("scheduleJob");//接收QuartzManager传过来的参数,
            jobName = scheduleJob.getJobName();
            jobGroupName = scheduleJob.getJobGroup();
            String groupIds = scheduleJob.getGroupIds();
            Integer amount = scheduleJob.getAmount();

            service.timmerTask(groupIds,amount, jobGroupName,scheduleJob.getTriggerGroupName());//具体的业务操作,这里就粘贴出来了!根据自己的业务写!
            log.info(jobName +jobGroupName +"定时器运行结束!");
        }catch (Exception e){
            QuartzManager.removeJob(scheduleJob);
            log.error(e.getMessage(),e);
            throw new RuntimeException(jobName +jobGroupName +"定时器意外终止");
        }
    }


}

最后上图表示成功:

成功定时

以上部分代码有借鉴网上大神的。如有侵权请联系删帖。QQ:718563711

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值