首页 > 技术文章 > Quartz定时调度在Web中的应用

cowboys 2016-07-29 12:14 原文

1.在数据库中建一个job表和job日志表

job表

job_log表

2.选用一个ORM框架,编写一个查询语句,查询数据表中的所有job(略)

 

3.写一个Quartz.java配置Quartz的相关属性

public class QuartzJobConfig {

    //常量
    private static Scheduler sched;
    private final static String JOB_GROUP = "jobGroup";
    private final static String TRIGGER_GROUP = "triggerGroup";
    private final static Logger logger = Logger.getLogger(QuartzJobConfig.class);  //日志文件
    
    public static void registerQuartzJob() throws Exception{
        //先获取所有的生效jobs
        @SuppressWarnings("rawtypes")
        List<Map> jobList = BaseSupport.myBatisSessionTemplate.selectList("orm.mapper.JobMapper.selectJobList");
        logger.info("总共有"+jobList.size()+"个定时任务");
        // 获取Scheduler实例
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        sched = schedulerFactory.getScheduler();
        //在quartz里面带上servletContext
        
        
        if(jobList!=null&&jobList.size()>0){
            for(Map job : jobList){
                try{
                    String cronExpression = getCronExpression(job);
                    JobDetail jobDetail = new JobDetail(job.get("JOB_NAME").toString(), JOB_GROUP, QuartzJobBusiness.class);
            // 触发时间点 Trigger trigger
= new CronTrigger(job.get("ID").toString(), TRIGGER_GROUP, cronExpression); sched.scheduleJob(jobDetail, trigger); logger.info("注册名为"+job.get("JOB_NAME").toString()+",ID为"+job.get("ID").toString()+"的任务成功"); }catch (Exception e){ e.printStackTrace(); logger.error("注册名为"+job.get("JOB_NAME").toString()+",ID为"+job.get("ID").toString()+"的任务失败"); } } } sched.start(); logger.info("Quartz任务注册成功"); } private static String getCronExpression(Map job){ String cronExpression=null; //CronExpression格式:秒 分钟 小时 天数 月 星期 年份 详细说明 http://www.iteye.com/topic/582119 String flag = "*"; //表示所有值 不适用表达星期 String replaceFlag = "?"; // ? 号只能用在日和周域上,但是不能在这两个域上同时使用。 String year = job.get("YEAR").toString(); String month = job.get("MONTH").toString(); String date = job.get("DATE").toString(); String day = job.get("DAY").toString(); String hour = job.get("HOUR").toString(); String minute = job.get("MINUTE").toString(); String second = job.get("SECOND").toString(); if (day == flag) { day = replaceFlag; } //替换星期字符域 //如果星期字符域有数据,日期字符域替换为replaceFlag"?" if (!(day==flag||day==replaceFlag)) { date = replaceFlag; } cronExpression = second + " " + minute + " " + hour + " " + date + " " + month + " " + day + " " + year; return cronExpression; } public static void shutdownQuartzJob(){ try { if(!sched.isShutdown()){ sched.shutdown(); } } catch (SchedulerException e) { e.printStackTrace(); logger.error("关闭QuartzJob异常"); } } }

4.编写一个监听器,并在Web.xml文件中配置监听器

public class SystemInitListener implements ServletContextListener {

    private final static Logger logger = Logger.getLogger(SpringInitWeb.class);
    private MyBatisSessionTemplate jdbcTemplate; 
    private boolean success = true;
    private String retMessage;
    private ApplicationContext applicationContext = null;
    /* (non-Javadoc)
     * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
     */
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        if (logger.isDebugEnabled()) {
            logger.debug(new StringBuilder().append("---------- Start to Destroy ServletContextListener  at ")
                    .append(System.currentTimeMillis()).append(" --------------").toString());
        }
        //关闭Quartz
        logger.info("开始关闭Quartz");
        QuartzJobConfig.shutdownQuartzJob();
        logger.info("Quartz已关闭");    

    }

    /* (non-Javadoc)
     * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
     */
    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        if (logger.isDebugEnabled()) {
            logger.debug(new StringBuilder().append("---------- Start to init ServletContextListener  at ")
                    .append(System.currentTimeMillis()).append(" --------------").toString());
        }
        systemStartup(arg0.getServletContext());

    }
    
    /**
     * 初始化全局变量
     */
    private void systemStartup(ServletContext servletContext) {
        if (logger.isDebugEnabled()) {
            logger.debug(new StringBuilder().append("---------- Start to 初始化全局变量  at ")
                    .append(System.currentTimeMillis()).append(" --------------").toString());
        }
        
        try {
            applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
            this.jdbcTemplate = (MyBatisSessionTemplate)SpringContextUtils.getBean("myBatisSessionTemplate");
        } catch (Exception e) {
            success = false;
            logger.error(e.getMessage(),e);
        }
        
        if (success) {
            BaseSupport.CframeUtil.InitDict(servletContext);
            BaseSupport.CframeUtil.InitSysParams(servletContext);
            logger.info("开始注册定时任务");
            try{
                QuartzJobConfig.registerQuartzJob();
            }catch (Exception e){
                logger.info("定时任务注册失败");
            }
        }
    }

  <listener>
        <listener-class>com.cf.cfquartz.listener.SystemInitListener</listener-class>
    </listener>

 

5.编写注册registerQuartzJob的方法

 

public class QuartzJobBusiness implements Job {
    
    //资金账号充值(带辅助信息)属性字段:start----------
    private String channelCode="201510310ROADOORP2P888888";    
    
    String msg_id=BaseSupport.CommonUtil.getUUID();
    String cust_code="2015121513248272640496338";
    String acc_no ="20151215122140132482726402096770";
    String card_code ="6217002870012789549";
    
    private String msg ="{\"head\":{\"msg_id\":\""+msg_id+"\",\"channel_code\":\"201510310ROADOORP2P888888\",\"service_code\":\"PAY_TOPUP_AUX_REQ\",\"version\":\"1\",\"callback_url\":\"http://172.16.200.11:8080/PService/testServiceAction!testService\"},\"body\":{\"cust_code\":\""+cust_code+"\",\"acc_no\":\""+acc_no+"\",\"card_code\":\""+card_code+"\",\"amount\":100,\"fee_pay_type\":\"0\",\"memo\":\"testmemo\",\"biz_code\":\"00000000SYS0000240004\" ,\"ori_seqno\":\"ORI_SEQNO_TEST\"}}";
    //资金账号充值(带辅助信息)属性字段:end----------
    
    
    private final static Logger logger = Logger.getLogger(QuartzJobBusiness.class);

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {

        // 判断一下本机ip是多少,只在测试服务器和开发服务器上运行quartzjob
        InetAddress ia = null;
        String localname = null;
        String localip = null;
        try {
            ia = ia.getLocalHost();
            localname = ia.getHostName();
            localip = ia.getHostAddress();
            logger.info("本机名称是:" + localname);
            logger.info("本机的ip是 :" + localip);
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            logger.error(e.getMessage(),e);
        }
       
        // TB_JOB表ID作为Trigger的key名称
        String jobId = context.getTrigger().getName();
        Map job = null;
        String errorMsg="";
        try{
            job = (Map) BaseSupport.myBatisSessionTemplate.selectOne("orm.mapper.TbJobMapper.selectJob", jobId);
        }catch(Exception e){
            logger.error("读取数据库失败,失败原因:"+ e.getMessage());
            errorMsg=e.getMessage();
        }
        if (null == job) {
            logger.info("没有找到id为:" + jobId + "的任务");
        } else {
            if (!"1".equals(job.get("DEL"))) {
                logger.info("开始执行名为:" + job.get("JOB_NAME").toString() + "的任务");
                try {
                    executePServiceJob(job);
                    //int i=1/0;
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    logger.debug(e.getMessage(),e);
                    errorMsg=e.getMessage();
                }
            }
        }
        Map<String,String> jobRunStatus=new HashMap<>();
        jobRunStatus.put("LOG_ID", BaseSupport.CommonUtil.getUUID());
        jobRunStatus.put("IP", localip);
        jobRunStatus.put("JOB_ID", jobId);
        jobRunStatus.put("RUN_TIME", BaseSupport.CframeUtil.GetCurrentLongTime());
        if("".equals(errorMsg)){
            jobRunStatus.put("IS_SUCCESS", JonConstant.SUCCESS_YES);
        }else{
            jobRunStatus.put("IS_SUCCESS", JonConstant.SUCCESS_NO);
            jobRunStatus.put("ERROR_MESSAGE", errorMsg);
        }
        BaseSupport.myBatisSessionTemplate.selectOne("orm.mapper.TbJobLog.insertJobLog", jobRunStatus);
    }

    private void executePServiceJob(Map job) throws Exception{
        String jobType = job.get("JOB_TYPE").toString();
        switch (jobType) {
     //此处就是数据表中的job编号
case ("01"): 。。。。case ("02"): 。。。。case ("03"): TransDailyReport transDailyReport = SpringContextUtils.getBean(TransDailyReport.class); transDailyReport.execute(); case ("04"):        。。。 break; } } }

 

 

6.编写自己的业务方法,要实现的功能类。比如:TransDailyReport(excute方法)

 

public class TransDailyReport {
    private static final Logger logger = Logger.getLogger(TransDailyReport.class);
@Autowired
private MyBatisSessionTemplate myBatisSessionTemplate;
@Transactional(rollbackFor
=Exception.class) public void execute(){ 。。。。。 } }

 

推荐阅读