1.业务需求:预约表中有一个状态字段status,有5种状态,0发起,1待核销,2驳回,3核销,4超时,后台要不断地去更新status的状态值,如果当前时间超过预约的创建时间30分钟,就将status的状态值修改为4
2.解决方法:方法1:配置一个监听器,然后在方法中单独开一个线程,不断地去循环修改状态值;方法2:利用quartz计时框架处理后台状态值修改,这里利用quartz去实现
3.在applicationContext.xml中添加配置文件:
<!--要调度的对象-->
<bean id="jobBean" class="com.waka.reservation.action.ReservationAction" />
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="jobBean" />
<property name="targetMethod" value="execute" />
<!--将并发设置为false-->
<property name="concurrent" value="false" />
</bean>
<bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<!--表达式,我的是每 30s 执行一次-->
<property name="cronExpression" value="0/30 * * * * ?" />
</bean>
<!-- 总管理类如果将lazy-init='false'那么容器启动就会执行调度程序 -->
<bean id="startQuertz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false" >
<property name="triggers">
<list>
<!--作业调度器,list下可加入其他的调度器-->
<ref bean="trigger"/>
</list>
</property>
</bean>
分析下:
<bean id="jobBean" class="com.waka.reservation.action.ReservationAction" />
class的值指向的类就是我们要调度的对象,定时器会每隔多长时间/每到指定时间点就会执行的对象
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="jobBean" />
<property name="targetMethod" value="execute" />
<!--将并发设置为false-->
<property name="concurrent" value="false" />
</bean>
targetMethod的值指向的是ReservationAction中的方法
<bean id="trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail" />
<!--表达式,我的是每 30s 执行一次-->
<property name="cronExpression" value="0/30 * * * * ?" />
</bean>
定时器,jobDetail指向的是我们刚定义的bean,cronExpression的值就是定时器的表达式
ReservationAction.java中新建一个execute()方法,输出一句话,启动服务器,控制台每隔30s输出打印一次,quartz框架测试成功,然后可以在方法中去实现更新预约表的status的操作。
需要注意的一点是项目中需要导入quartz的jar包,我用的是IDEA开发工具,需要手动将jar包添加到项目的依赖中,项目右键–>Open Module Setting–>Module–>Dependencies添加jar
对于quartz还有另一种注解的实现方式,也是需要在applicationContext.xml中添加配置,然后直接在某个方法名上加上注解
实际开发过程中,spring整合quartz后,项目跑起来之后会出现每次调用的任务方法都会重复两次的情况,如果任务中有大量的数据查询或者是增删改,无疑会对性能造成一定的影响。百度并分析原因,是因为tomcat服务器和spring本身都加载了这个定时器,所以会出现两个实例,但是百度的解决方案说的是在tomcat的server.xml配置文件中将host中的一个属性值置空,但是对于我项目的情况来说并不适用。
只有找其他的解决方案了:
private static int flag=0;
public void before(){
if(flag==0){
execute();
}else {
flag=0;
}
}
定义一个静态变量,然后通过修改它的值让程序只执行一次定时任务