投诉受理的三圈问题
在信息管理模块的时候,我们就提出了三圈的问题了。何为三圈问题呢???就是当我们使用条件查询出数据的时候,再对查询出的数据进行操作【修改、保存】,当保存完之后回到列表显示页面上的时候,查询条件就会丢失掉了。也就是说,我们原来查询出的数据不见了。
首先,我们在Action中使用两个变量把有可能成为查询条件的变量记住:
/************三圈问题数据回显*************************/ private String compTitle; private String state; public String getCompTitle() { return compTitle; } public void setCompTitle(String compTitle) { this.compTitle = compTitle; } public String getState() { return state; } public void setState(String state) { this.state = state; }
接着,在跳转到处理投诉页面的JSP上的时候,把查询条件的数据查询出来,把它赋值给变量。然后使用request域对象把数据发给JSP页面
//把查询条件带过去给JSP页面 ActionContext.getContext().getContextMap().put("compTitle", complain.getCompTitle()); ActionContext.getContext().getContextMap().put("state", complain.getState()); ActionContext.getContext().getContextMap().put("startTime", startTime); ActionContext.getContext().getContextMap().put("endTime", endTime);
然后在处理投诉页面的JSP上,通过隐藏域把数据给回Action。。Action在重定向到listUI页面的时候,就通过配置文件,把参数带过去:
<!--返回列表展示页面,重定向到列表展示--> <result name="list" type="redirectAction"> <param name="actionName">complain_listUI</param> <param name="complain.state">${state}</param> <param name="complain.compTitle">${compTitle}</param> <param name="endTime">${startTime}</param> <param name="startTime">${startTime}</param> <param name="encode">true</param> </result>
这样一来,我们的查询条件就没有丢失了。当我们操作完数据的时候,我们的查询出来的数据还是原来那部分。
Quartz自动受理
回到我们的需求:
自动投诉受理:在每个月月底最后一天对本月之前的投诉进行自动处理;将投诉信息的状态改为 已失效。在后台管理中不能对该类型投诉进行回复。
这个需求需求我们要怎么弄呢????要在每个月底最后一天对本月之前的投诉进行自动处理。。。。
记得我们以前在学习Java基础的时候学过了一个Timer这么一个类,可以用规定的频率来执行我们的代码。。。使用起来是非常简单的:
但是呢,要精确到每个月的月底,这就需要我们人为去判断时间了,这就非常不方便了。
因此,我们引入了另一个非常好用的框架:Quartz
Quartz
这是一个优秀的开源任务调度框架“quartz”,可以简单理解成他是Timer的升级版….Spring集成了该框架…
快速入门
我们要使用它,就要导入其开发包:quartz-1.8.6.jar,和Spring对其支持的开发包:org.springframework.context.support-3.0.2.RELEASE
使用它的步骤是十分简单的,可分成三个步骤:
1、制定任务信息 bean
- ① 设置执行对象
- ② 设置执行对象中对应的执行方法
- ③ 是否可以同步执行
2、制定任务执行时机(执行触发器) bean
- 2.1、简单触发器(SimpleTrigger)
- ① 设置任务详细
- ② 设置任务延迟执行时间
- ③ 设置任务执行频率
- 2.2、任务触发器(CronTrigger)
- ① 设置任务详细
- ② 设置执行时机(cronExpression)
- cronExpression:秒 分 时 日 月 周 年(可选)
3、设置任务调度工厂 bean
- 设置触发器们
jobDetail任务详细信息
1、jobDetail 任务详细信息;包括调用哪个类;类中的哪个方法;执行时是否可并行执行任务。
<!-- 1、制定任务信息信息 --> <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任务调度触发器
2、trigger 任务调度触发器;主要用于定义jobDetail什么时候执行。触发器最常用的有两种:简单触发器SimpleTrigger 和 任务触发器CronTrigger 。SimpleTrigger和jdk的timer类似,只能指定任务执行以什么样的频率执行,但无法制定精确的执行时间。CronTrigger则既可以执行简单触发器所制定的以频率来执行的时间,也可以制定复杂的时间计划来执行。
<!-- 2、制定任务执行时机(任务执行触发器) --> <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>
这里我们着重要了解表达式怎么写:秒 分 时 日 月 周 年【日和周不能同时出现】
schedulerFactory 任务调度工厂
schedulerFactory 任务调度工厂;用于调度各个任务触发器。
任务调度工厂可以调度多个任务同时进行
<!-- 3、设置调度工厂 --> <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中执行对应的代码:
<!-- 1、制定任务信息信息 --> <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> <!-- 2、制定任务执行时机(任务执行触发器) --> <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> <!-- 3、设置调度工厂 --> <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>