Quartz集成Spring的2個方法
關於Spring集成Quartz有2種方法:
1. JobDetailBean.
2. MethodInvokeJobDetailFactoryBean.
以下從自身使用和理解以及掌握的知識對其進行闡述。
需要注意的是,在使用Spring集成Quartz的時候,一定不要忘記引入spring-support這個包:
1、使用 MethodInvokeJobDetailFactoryBean
applicationTask.xml 配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <!-- 定時任務 下游回調任務--> <!-- ======================== 1、定義需要執行的任務類。 ======================== --> <bean id="notifyQuartz" class="com.hsmpay.mobile.timerTask.NotifyTimerAction"> </bean> <!-- ======================== 2、將需要執行的定時任務注入JOB中。 ======================== --> <bean id="notifyQuartzDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <!--引入執行任務的類--> <property name="targetObject"><ref bean="notifyQuartz"/></property> <!--定義要執行具體類的方法--> <property name="targetMethod"><value>remoteNotify</value></property> </bean> <!-- ======================== 3、調度觸發器 ======================== --> <bean id="notifyTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"><ref bean="notifyQuartzDetail"/></property> <property name="cronExpression"> <!--每五分鍾執行一次--> <!--<value>0 08 10 * * ?</value>--> <value>0 0/5 * * * ?</value><!--<value>秒 分 時 天 月 周 年</value> 0 55 17 ? * MON-FRI--> </property> </bean> <!--================================================================================================--> <!-- 半分鍾執行定時任務 --> <!-- ======================== 1、定義需要執行的任務類。 ======================== --> <bean id="messageTask" class="com.hsmpay.mobile.timerTask.MessageTask"></bean> <!-- ======================== 2、將需要執行的定時任務注入JOB中。 ======================== --> <bean id="oneMessageRollBackTaskJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"><ref bean="messageTask"/></property> <property name="targetMethod"><value>oneTaskJob</value></property> </bean> <!-- ======================== 3、調度觸發器 ======================== --> <bean id="oneMessageStreamRollBackTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"> <ref bean="oneMessageRollBackTaskJobDetail"/> </property> <property name="cronExpression"> <value>*/30 * * * * ?</value> </property> </bean> <!-- ======================== 4、調度工廠 ======================== --> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="notifyTrigger"/> </list> </property> </bean> <bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 線程池維護線程的最少數量 --> <property name="corePoolSize" value="10" /> <!-- 線程池維護線程所允許的空閑時間 --> <property name="keepAliveSeconds" value="200" /> <!-- 線程池維護線程的最大數量 --> <property name="maxPoolSize" value="50" /> <!-- 線程池所使用的緩沖隊列 --> <property name="queueCapacity" value="100" /> <property name="rejectedExecutionHandler"> <!-- AbortPolicy:直接拋出java.util.concurrent.RejectedExecutionException異常 --> <!-- CallerRunsPolicy:主線程直接執行該任務,執行完之后嘗試添加下一個任務到線程池中,可以有效降低向線程池內添加任務的速度 --> <!-- DiscardOldestPolicy:拋棄舊的任務、暫不支持;會導致被丟棄的任務無法再次被執行 --> <!-- DiscardPolicy:拋棄當前任務、暫不支持;會導致被丟棄的任務無法再次被執行 --> <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /> </property> </bean> </beans>
相關代碼配置
@Controller("notifyTimerAction") public class NotifyTimerAction { private Logger log = LoggerFactory.getLogger(this.getClass()); @Resource(name="transOrderService") TransOrderService transOrderService;//查詢訂單service //設置核心池大小 int corePoolSize = 5; //設置線程池最大能接受多少線程 int maximumPoolSize=20; //當前線程數大於corePoolSize、小於maximumPoolSize時,超出corePoolSize的線程數的生命周期 long keepActiveTime = 200; //設置時間單位,秒 TimeUnit timeUnit = TimeUnit.SECONDS; public String url ="http://localhost:8080/mobile/forwardPort/port.action"; /** * 下游回調通知,繼續發送 */ public void remoteNotify() throws Exception{ log.debug("test定時任務啟動了!!!!!!!!"); System.out.println("test定時任務啟動了!!!!!!!!"); TransOrder order=new TransOrder(); order.setStatus(1);//設置成功狀態 order.setClientType(7);//設置客戶類型 7外放接口類型 order.setOrderTypeId(1L);//收款類型 //設置線程池緩存隊列的排隊策略為FIFO,並且指定緩存隊列大小為5 BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<Runnable>(5); //創建ThreadPoolExecutor線程池對象,並初始化該對象的各種參數 ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepActiveTime, timeUnit,workQueue); try { List<TransOrder> orderList = transOrderService.searchEntityList(order); Map<String,Object> map=new HashMap<String,Object> (); //准備給下游發送數據 for(TransOrder transOrder:orderList){ Thread thread=new Thread(new Runnable() { public void run() { map.put("status",transOrder.getStatus());//交易狀態 map.put("orderNum",transOrder.getOrderNum());//訂單號 JSONObject jsonObject = JSONObject.fromObject(map); HttpClientUtil.submitPost(transOrder.getOtherData(), map.toString(), "UTF-8",60000, 60000); } }); executor.execute(thread); } executor.shutdown();//關閉線程池 } catch (Exception e) { e.printStackTrace(); throw e; } } }
==================================================================================================================================================================
二、JobDetailBean
1. 創建一個Job方法,此方法必須繼承QuartzJobBean或者實現Job方法。
public class TestJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { System.out.println(TimeUtils.getCurrentTime()); } }
2. XML配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="jobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean"> <property name="jobClass" value="com.mc.bsframe.job.TestJob"></property> <property name="durability" value="true"></property> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean"> <property name="jobDetail" ref="jobDetail" /> <property name="startDelay" value="3000" /> <property name="repeatInterval" value="2000" /> </bean> <!-- 總管理類 如果將lazy-init='false'那么容器啟動就會執行調度程序 --> <bean id="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <!-- 管理trigger --> <property name="triggers"> <list> <ref bean="simpleTrigger" /> </list> </property> </bean> </beans>
綜上:定時任務的基本配置完成。
三、兩種方法的說明
使用QuartzJobBean,需要繼承。而使用MethodInvokeJobDetailFactoryBean則需要指定targetObject(任務實例)和targetMethod(實例中要執行的方法)
后者優點是無侵入,業務邏輯簡單,一目了然,缺點是無法持久化(目前還不太清楚這點!)
從我使用的經驗來說,我更推薦的第一種,其中一個很重要的原因就是因為定時任務中注入相關Service的時候,后者可以直接注入,而前者還需要進行Schedular的替換修改。