A few days ago received a project need to periodically rebuild the index task, first try the Java with the timer, do not know that it is not enough for the timer's understanding of the reasons, I feel that the timer function is a little weak, can not meet my needs: a certain period of time to be in a certain cycle to carry out the task, And these times are available for the customer to configure. Finally, the spring timer is used to solve the problem.
Here, incidentally, the problem of rebuilding the Lucene index with multiple instances if a project deploys multiple instances on the same server, and multiple instances share the same index file, it is important to prevent several instances from triggering and rebuilding the index at timed times, if you want to implement the function of timing indexing. The obvious problem: there are multiple processes at the same time operating on the same index file, which can cause conflicts, and there is simply no need and resources. So my solution here is that every time we arrive, I randomly get a time before the task, such as any one in the middle of 1-100 seconds, and then rebuild the index after this random time, so that multiple instances can be prevented from triggering the task at the same time. Then the first one to do a timed task creates an identity file on the server disk. Indicates that there is currently an instance executing a task, and other instances after a random time have found that the identity file is not a task, of course, the file must be in the execution of the task or the task during the process of an exception to stop the operation to be deleted.
Step One: Write the class that executes the task, inherit Quartzjobbean, my task content does not write here, as follows:
[java] View Plain Copy public class rebuildluceneindex extends quartzjobbean{ log log = logfactory.getlog (Rebuildluceneindex.class); private KbsEntryManager kbsEntryManager; int timeout; @Override Protected void executeinternal (JOBEXECUTIONCONTEXT JEC) throws JobExecutionException { //get the configuration information, if the customer does not configure the timer will not start, you should turn it off: if (timer not configured) { try { jec.getscheduler (). Shutdown (); } catch (schedulerexception e) { log.error (E.getMessage (), E); } }else{ //to perform your task } } }
Oh yes, you should inject a class, you need to provide a set method, the above code increases:
[Java] View plain copy public void Setkbsentrymanager (Kbsentrymanager manager) {This.kbsentrymanager = manager; }
Step Two: Write the timer configuration file, such as my schedule-context.xml:
[html] View Plain Copy <?xml version= "1.0" encoding= "UTF-8"?> <! doctype beans public "-//spring//dtd bean//en" "http://www.springframework.org/dtd/ Spring-beans.dtd "> <beans> <bean Name= "Schedulerjobdetail" class= "Org.springframework.scheduling.quartz.JobDetailBean" > <property name= "Jobclass" > <value> com.syni.im800.kb.schedule.rebuildluceneindex</value> </property> < Property name= "Jobdataasmap" > <map> <entry key= " Kbsentrymanager " value-ref=" Kbsentrymanager "/> </map> </property> </bean> <bean id= " Rebuildindextrigger " class=" Com.syni.im800.kb.schedule.InitializingCronTrigger "> <property name= "Jobdetail" > <ref bean= "Schedulerjobdetail"/> </property> <property name= "Cronexpression" > &NBSP;&Nbsp; <value>0 0 2 * * ?</value> </property> </bean> <bean id= "schedulerfactory" class= " Org.springframework.scheduling.quartz.SchedulerFactoryBean "> <property name= "triggers" > < list> <ref local= " Crontrigger "/> <ref local=" Rebuildindextrigger "/> </list> </property> </bean> </beans>
The above configuration explains, because Cronexpression needs to provide the configurable function, cannot write dead in the XML, therefore has written a initializingcrontrigger, inherits Crontriggerbean, Reconfigure the cronexpression in it, so the 0 0 2 * * is configured here just to keep the container from starting the error.
Step three: Write the Rebuildindextrigger in the second step:
[java] View Plain Copy Public class initializingcrontrigger extends crontriggerbean implements Serializable{ Log log = Logfactory.getlog (initializingcrontrigger.class); String cronexpression; public initializingcrontrigger () {}; public void setcronexpression ( String cronexpression_) { string day = appconfig.getproperty (appconfig.rebuildindex_day_of_week); string hour = appconfig.getproperty (Appconfig.rebuildindex_hour_of_day) ; if (day!=null && hour!=null) { &NBSP;&NBSP;&NBSP;&Nbsp; cronexpression = "0 0 " +hour+ " "? * "+day; Log.debug ("###### #cronExpression:" +cronexpression); }else{ //Set a value here, Time to turn off the timer cronexpression = "0 0 1 ? * *"; } try { super.setcronexpression ( cronexpression); } catch (exception e) &NBSP;{&NBSP;&NBSp log.error (E.getMessage (), E); } } }
Description: Because cronexpression is injected into the chedule-context.xml for Initializingcrontrigger, the set method is provided here so that the method is invoked each time the timer is triggered, and then we can read the actual match in our config file To build our cronexpression, above day,hour is my program to read the user configuration information from the configuration file.
Finally, in the Web.xml configuration chedule-context.xm, this step should not be much, such as:
[HTML] View Plain copy <!--context Configuration locations for Spring XML files--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/web-inf/schedule-context.x ML </param-value> </context-param>
In addition, for the detailed use of spring timers, such as configuration expressions, refer to other articles, the following is a simple description of the configuration of the expression: