纳税服务系统【自动受理,Quartz任务调度】

需求

回到咱们的需求:javascript

自动投诉受理:在每月月底最后一天对本月以前的投诉进行自动处理;将投诉信息的状态改成 已失效。在后台管理中不能对该类型投诉进行回复。java

这个需求需求咱们要怎么弄呢????要在每月底最后一天对本月以前的投诉进行自动处理。。。。spring

记得咱们之前在学习Java基础的时候学过了一个Timer这么一个类,能够用规定的频率来执行咱们的代码。。。使用起来是很是简单的:ruby

这里写图片描述

这里写图片描述

可是呢,要精确到每月的月底,这就须要咱们人为去判断时间了,这就很是不方便了。markdown

所以,咱们引入了另外一个很是好用的框架:Quartz框架


Quartz

这是一个优秀的开源任务调度框架“quartz”,能够简单理解成他是Timer的升级版….Spring集成了该框架…ide

快速入门

咱们要使用它,就要导入其开发包:quartz-1.8.6.jar,和Spring对其支持的开发包:org.springframework.context.support-3.0.2.RELEASE学习

使用它的步骤是十分简单的,可分红三个步骤:spa

一、制定任务信息 beancode

  • ① 设置执行对象
  • ② 设置执行对象中对应的执行方法
  • ③ 是否能够同步执行

二、制定任务执行时机(执行触发器) bean

  • 2.一、简单触发器(SimpleTrigger)

    • ① 设置任务详细
    • ② 设置任务延迟执行时间
    • ③ 设置任务执行频率
  • 2.二、任务触发器(CronTrigger)

    • ① 设置任务详细
    • ② 设置执行时机(cronExpression)
    • cronExpression:秒 分 时 日 月 周 年(可选)

三、设置任务调度工厂 bean

  • 设置触发器们

jobDetail任务详细信息

一、jobDetail 任务详细信息;包括调用哪一个类;类中的哪一个方法;执行时是否可并行执行任务

<!-- 一、制定任务信息信息 -->
   <bean id="jobDetail1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
           <!-- 设置执行对象 -->
           <property name="targetObject" ref="quartzTask"></property>
           <!-- 设置执行对象中对应的执行方法 -->
           <property name="targetMethod" value="doSimpleTriggerTask"></property>
           <!-- 是否能够同步执行;不可同步执行 -->
           <property name="concurrent" value="false"></property>
   </bean>
   <bean id="jobDetail2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
           <!-- 设置执行对象 -->
           <property name="targetObject" ref="quartzTask"></property>
           <!-- 设置执行对象中对应的执行方法 -->
           <property name="targetMethod" value="doCronTriggerTask"></property>
           <!-- 是否能够同步执行;不可同步执行 -->
           <property name="concurrent" value="false"></property>
   </bean>

这里写图片描述


trigger任务调度触发器

二、trigger 任务调度触发器;主要用于定义jobDetail何时执行。触发器最经常使用的有两种:简单触发器SimpleTrigger 和 任务触发器CronTrigger 。SimpleTrigger和jdk的timer相似,只能指定任务执行以什么样的频率执行,但没法制定精确的执行时间。CronTrigger则既能够执行简单触发器所制定的以频率来执行的时间,也能够制定复杂的时间计划来执行

<!-- 二、制定任务执行时机(任务执行触发器) -->
   <bean id="simplerTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
        <!-- 设置任务详细 -->
        <property name="jobDetail" ref="jobDetail1"></property>
        <!-- 设置任务延迟执行时间 ;延迟2秒执行-->
        <property name="startDelay" value="2000"></property>
        <!-- 设置任务执行频率;执行频率为每4秒执行一下 -->
        <property name="repeatInterval" value="2000"></property>
   </bean>

   <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <!-- 设置任务详细 -->
        <property name="jobDetail" ref="jobDetail2"></property>
        <!-- 设置任务执行时机,cron表达式 -->
        <property name="cronExpression" value="* * * 18c * ?"></property>
   </bean>

这里写图片描述

这里咱们着重要了解表达式怎么写:秒 分 时 日 月 周 年【日和周不能同时出现】

这里写图片描述

  • ’ 字符能够用于全部字段,在“分”字段中设为”“表示”每一分钟”的含义。

  • ‘?’ 字符能够用在“日”和“周几”字段. 它用来指定 ‘不明确的值’. 这在你须要指定这两个字段中的某一个值而不是另一个的时候会被用到。在后面的例子中能够看到其含义。

  • ‘-’ 字符被用来指定一个值的范围,好比在“小时”字段中设为”10-12”表示”10点到12点”.

  • ‘,’ 字符指定数个值。好比在“周几”字段中设为”MON,WED,FRI”表示”the days Monday, Wednesday, and Friday”.

  • ‘/’ 字符用来指定一个值的的增长幅度. 好比在“秒”字段中设置为”0/15”表示”第0, 15, 30, 和 45秒”。而 “5/15”则表示”第5, 20, 35, 和 50”. 在’/’前加”*”字符至关于指定从0秒开始. 每一个字段都有一系列能够开始或结束的数值。对于“秒”和“分”字段来讲,其数值范围为0到59,对于“小时”字段来讲其为0到23, 对于“日”字段来讲为0到31, 而对于“月”字段来讲为1到12。”/”字段仅仅只是帮助你在容许的数值范围内从开始”第n”的值。 所以对于“月”字段来讲”7/6”只是表示7月被开启而不是“每六个月”, 请注意其中微妙的差异。

  • ‘L’字符可用在“日”和“周几”这两个字段。它是”last”的缩写, 可是在这两个字段中有不一样的含义。例如,“日”字段中的”L”表示”一个月中的最后一天” —— 对于一月就是31号对于二月来讲就是28号(非闰年)。而在“周几”字段中, 它简单的表示”7” or “SAT”,可是若是在“周几”字段中使用时跟在某个数字以后, 它表示”该月最后一个星期×” —— 好比”6L”表示”该月最后一个周五”。当使用’L’选项时,指定肯定的列表或者范围很是重要,不然你会被结果搞糊涂的。

  • ‘W’ 可用于“日”字段。用来指定历给定日期最近的工做日(周一到周五) 。好比你将“日”字段设为”15W”,意为: “离该月15号最近的工做日”。所以若是15号为周六,触发器会在14号即周五调用。若是15号为周日, 触发器会在16号也就是周一触发。若是15号为周二,那么当天就会触发。然而若是你将“日”字段设为”1W”, 而一号又是周六, 触发器会于下周一也就是当月的3号触发,由于它不会越过当月的值的范围边界。’W’字符只能用于“日”字段的值为单独的一天而不是一系列值的时候。

  • ‘L’和’W’能够组合用于“日”字段表示为’LW’,意为”该月最后一个工做日”。

  • ‘#’ 字符可用于“周几”字段。该字符表示“该月第几个周×”,好比”6#3”表示该月第三个周五( 6表示周五而”#3”该月第三个)。再好比: “2#1” = 表示该月第一个周一而 “4#5” = 该月第五个周三。注意若是你指定”#5”该月没有第五个“周×”,该月是不会触发的。

  • ‘C’ 字符可用于“日”和“周几”字段,它是”calendar”的缩写。它表示为基于相关的日历所计算出的值(若是有的话)。若是没有关联的日历, 那它等同于包含所有日历。“日”字段值为”5C”表示”日历中的第一天或者5号及其之后”,“周几”字段值为”1C”则表示”日历中的第一天或者周日及其之后”。

  • 对于“月份”字段和“周几”字段来讲合法的字符都不是大小写敏感的。


schedulerFactory 任务调度工厂

schedulerFactory 任务调度工厂;用于调度各个任务触发器。

任务调度工厂能够调度多个任务同时进行

<!-- 三、设置调度工厂 -->
   <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <!-- <ref bean="simplerTrigger"/> -->
                <ref bean="cronTrigger"/>
            </list>
        </property>
   </bean>

这里写图片描述


自动受理

回到咱们的需求,咱们已经大概了解了Quartz这么一个开源框架使用了。咱们就能够在每月的最后一天中去执行咱们对应的代码就好了。

  • 时机:
    • 每月月底最后一天;cronExpression:10 10 2 L * ?
  • 执行什么内容:
    • 对本月以前的待受理投诉进行自动处理;将投诉信息的状态改成 已失效
  • 如何执行:
    • 本月以前的待受理投诉:select * from Complain where 投诉时间 < 本月1号0时0分0秒

在Spring配置文件中加入Quartz框架….

咱们在Service中执行对应的代码

<!-- 一、制定任务信息信息 -->
    <bean id="jobDetail1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <!-- 设置执行对象 -->
        <property name="targetObject" ref="complainServiceImpl"></property>
        <!-- 设置执行对象中对应的执行方法 -->
        <property name="targetMethod" value="doTask"></property>
        <!-- 是否能够同步执行;不可同步执行 -->
        <property name="concurrent" value="false"></property>
    </bean>

    <!-- 二、制定任务执行时机(任务执行触发器) -->
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <!-- 设置任务详细 -->
        <property name="jobDetail" ref="jobDetail1"></property>
        <!-- 设置任务执行时机,cron表达式 -->
        <property name="cronExpression" value="10 10 2 L * ?"></property>
    </bean>

    <!-- 三、设置调度工厂 -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="cronTrigger"/>
            </list>
        </property>
    </bean>
</beans>

查询出未处理和是本月前的记录,修改为是失效的。

@Override
    public void doTask() {

        //查询全部待受理的信息
        QueryHelper queryHelper = new QueryHelper(Complain.class, "c");
        queryHelper.addCondition(" c.state=?", Complain.COMPLAIN_STATE_UNDONE);

        //只要在本月以前
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        queryHelper.addCondition(" c.compTime <?", calendar.getTime());

        //拿到本月以前全部未处理的数据
        List<Complain> complains = findObjects(queryHelper);

        //将数据所有改为是失效的了。
        for (Complain complain : complains) {
            complain.setState(Complain.COMPLAIN_STATE_INVALID);
        }
    }
}

若是已经失效了,那么咱们就不让管理员对其进行回复了。

<s:if test="state!=2"> <a href="javascript:doDeal('<s:property value='compId'/>')">受理</a></s:if>

这里写图片描述

相关文章
相关标签/搜索