• spring定时器


    最近正在做一个月报告自动发布的项目,要求根据客户端的设置动态修改定时时间,如客户可以设置 每个月的2号10点自动生成月报告,就用到了spring定时器+quartz。在此感谢http://blog.sina.com.cn/s/blog_49742bac0101fg67.html以及https://blog.csdn.net/gy40235/article/details/41085601和https://www.cnblogs.com/huaxingtianxia/p/5931812.html对我写这篇文章的支持。

    用到的spring是4,quartz2.2.3

    我单独写了一个定时器的配置文件:applicationContext-time.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

    <!-- 被执行类 -->
    <bean id="timer" class="com.walkersoft.bigdata.timer.Timer">
    <!-- <property name="scheduler" ref="schedulerFactory"></property> -->
    </bean>

    <!-- 将类注入到job中 -->
    <bean id="timeJob" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
    <property name="targetObject" ref="timer"/>
    <property name="targetMethod" value="myTast" />
    <property name="concurrent" value="false" />
    </bean>

    <!-- job注入到定时触发器 -->
    <bean id="timeTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref ="timeJob" />
    <property name="cronExpression">
    <value>0 0 10 * * ?</value>
    </property>
    </bean>

    <!-- 总管理类 将触发器注入到任务工程 -->
    <bean id="schedulerFactory" lazy-init="true" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
    <list >
    <ref bean="timeTrigger"/>
    </list>
    </property>
    </bean>

    <!--  动态设置定时时间的类 -->
    <bean id="setTimer" class="com.walkersoft.bigdata.timer.setTimer" lazy-init="false" init-method="resetJob">
    <property name="scheduler" ref="schedulerFactory"></property>
    </bean>
    </beans>

    简单说明:定时器的配置文件 其实就是把你自定义的定时类:timer类放到job里面。再把job放到触发器trigger里面。然后把触发器放到spring总的任务管理类上,让spring替我们定时开启任务。如果要用到动态设置定时器。则还要实例化一个你动态设置时间的一个bean ,然后让spring总的任务管理类管理你的bean即可。

    可以用注解进行设置,但是注解好像不能支持动态设置定时(这个还没研究),所以用的是配置文件

    //执行任务的类

    package com.walkersoft.bigdata.timer;

    public class Timer {

    public void myTast() throws IOException {
    System.out.println("任务开始了");

    doSomething()//这个是要执行任务的业务逻辑

    }

    //动态获取定时时间类

    package com.walkersoft.bigdata.timer;

    public class setTimer {

    private org.quartz.Scheduler scheduler;

    // 设值注入,通过setter方法传入被调用者的实例scheduler
    public void setScheduler(org.quartz.Scheduler scheduler) {
    this.scheduler = scheduler;
    }


    public void resetJob() {

    String cronExpression = “从数据库里面获取前台设置的定时任务执行时间”;
    TriggerKey triggerKey = TriggerKey.triggerKey("timeTrigger", TriggerKey.DEFAULT_GROUP);
    try {
    org.quartz.CronTrigger trigger =(org.quartz.CronTrigger)scheduler.getTrigger(triggerKey);
    String originConExpression = trigger.getCronExpression(); //获取配置文件默认的设置时间
    if(!originConExpression.equals(cronExpression)) { //如果两者时间一样,不用处理,还按照配置文件的时间,如果不一样则把新的时间更新要配置文件上。

    //spring定时器启动时会先获取这个地方的时间

    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
    //按新的表达式重新构建trigger
    trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
    .withSchedule(scheduleBuilder).build();
    //按新的trigger设置job
    scheduler.rescheduleJob(triggerKey, trigger);
    System.out.println( new Date() );
    }

    } catch (SchedulerException e) {
    e.printStackTrace();
    }
    }
    }

    设置后就可以了。但是我放到服务器上后,定时器每次执行任务的时候,发现每次都实例化2次,这不是我想到的结果。于是考虑到同步锁。但是还是走不通。加上同步之后还是实例化2次。最后上网查,发现大部分网友都是修改tomcat的配置文件的server.xml文件。修改之后发现果然好了。但是这样做的话,如果项目几年之后更新到新的tomcat上运维工程师只记得把项目放到新的tomcat上,忘了也要修改tomcat的配置文件,这个问题还是会暴露出来啊。暂时还没有解决办法,希望广大网友能提出新的解决办法。这次就谢谢大家了。下面是我修改的tomcat 下面 conf/server.xml的配置

    修改前

    <Host name="localhost" appBase="webapps"
    unpackWARs="true" autoDeploy="true">

    <!-- SingleSignOn valve, share authentication between web applications
    Documentation at: /docs/config/valve.html -->
    <!--
    <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
    -->

    <!-- Access log processes all example.
    Documentation at: /docs/config/valve.html
    Note: The pattern used is equivalent to using pattern="common" -->
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    prefix="localhost_access_log." suffix=".txt"
    pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    <Context path="" debug="0" docBase="bigdata" reloadable="true"/>
    </Host>

    修改后

    <Host name="localhost" appBase=""
    unpackWARs="true" autoDeploy="true">

    <!-- SingleSignOn valve, share authentication between web applications
    Documentation at: /docs/config/valve.html -->
    <!--
    <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
    -->

    <!-- Access log processes all example.
    Documentation at: /docs/config/valve.html
    Note: The pattern used is equivalent to using pattern="common" -->
    <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
    prefix="localhost_access_log." suffix=".txt"
    pattern="%h %l %u %t &quot;%r&quot; %s %b" />
    <Context path="" debug="0" docBase="webapps/bigdata" reloadable="true"/>
    </Host>

    大家可以发现 只是把appBase="webapps"修改为空,然后把 docBase="webapps/bigdata"的路径改为以前的appBase+docBase的路径就可以了

    到此,spring定时器任务结束。经过几天的测试,正常。

    另外  :客户端设置的是每个月的2号十点执行任务。但我为了以防万一 用的是每天的10点执行。如果月报告有就不执行。如果没有就重新生成。看配置文件的时候要注意到这点哦

    定时任务时间格式(copy网上的)

    字段 允许值 允许的特殊字符 
    秒 0-59 , - * / 
    分 0-59 , - * / 
    小时 0-23 , - * / 
    日期 1-31 , - * ? / L W C 
    月份 1-12 或者 JAN-DEC , - * / 
    星期 1-7 或者 SUN-SAT , - * ? / L C # 
    年(可选) 留空, 1970-2099 , - * / 


    0 0 12 * * ?---------------在每天中午12:00触发 
    0 15 10 ? * *---------------每天上午10:15 触发 
    0 15 10 * * ?---------------每天上午10:15 触发 
    0 15 10 * * ? *---------------每天上午10:15 触发 
    0 15 10 * * ? 2005---------------在2005年中的每天上午10:15 触发 
    0 * 14 * * ?---------------每天在下午2:00至2:59之间每分钟触发一次 
    0 0/5 14 * * ?---------------每天在下午2:00至2:59之间每5分钟触发一次 
    0 0/5 14,18 * * ?---------------每天在下午2:00至2:59和6:00至6:59之间的每5分钟触发一次 
    0 0-5 14 * * ?---------------每天在下午2:00至2:05之间每分钟触发一次 
    0 10,44 14 ? 3 WED---------------每三月份的星期三在下午2:00和2:44时触发 
    0 15 10 ? * MON-FRI---------------从星期一至星期五的每天上午10:15触发 
    0 15 10 15 * ?---------------在每个月的每15天的上午10:15触发 
    0 15 10 L * ?---------------在每个月的最后一天的上午10:15触发 
    0 15 10 ? * 6L---------------在每个月的最后一个星期五的上午10:15触发 
    0 15 10 ? * 6L 2002-2005---------------在2002, 2003, 2004 and 2005年的每个月的最后一个星期五的上午10:15触发 
    0 15 10 ? * 6#3---------------在每个月的第三个星期五的上午10:15触发 
    0 0 12 1/5 * ?---------------从每月的第一天起每过5天的中午12:00时触发 
    0 11 11 11 11 ?---------------在每个11月11日的上午11:11时触发.?

  • 相关阅读:
    c#多线程
    [2017.02.05] 阅读《Efficient C++》思维导图
    [2017.02.04] C++学习记录(1)
    [2017.01.04] 经典排序算法思想及其实现
    [2017.01.04] 2017 新年展望
    [151225] Python3 实现最大堆、堆排序,解决TopK问题
    [160111] Python学习记录
    [151116 记录] 使用Python3.5爬取豆瓣电影Top250
    151111 sqlite3数据库学习
    20141127 测试使用Word2013书写博客(代码高亮+公式支持)。
  • 原文地址:https://www.cnblogs.com/xuanbo/p/8853727.html
Copyright © 2020-2023  润新知