納稅服務系統【自動受理,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>

這裏寫圖片描述

相關文章
相關標籤/搜索