This article describes job visualizations (management, imperfect visual management of this article) when using the job framework of spring (spring inherited and simplified quartz)
The solution is to use listeners to implement job history, job statistics, exception logging, manual trigger Job
Let's take a look at the implementation process
Here you only need to implement several listeners and register to
-Statisticschedulerlistener listener trigger rule triggers, typically triggered when spring starts and refreshes
-Statisticjoblistener Job Listener (monitor job before and after execution)
-Statistictriggerlistener
The main use of statisticjoblistener here
public class Statisticjoblistener implements Joblistener {private static Logger log = Logger.getlogger (statisticjoblis Tener.class); private static threadlocal<jobstatisticbean> ThreadLocal = new threadlocal<jobstatisticbean> (); private String name; public void SetName (String name) {this.name = name; } @Override Public String getName () {return this.name; }//beginging @Override public void jobtobeexecuted (Jobexecutioncontext context) {Log.info ("job will execute ... "+context.getjobdetail (). GetName ()); Jobstatisticbean Jobstatisticbean = new Jobstatisticbean (); Jobstatisticbean.setjobname (Context.getjobdetail (). GetName ()); Jobstatisticbean.setjobdetail (Context.getjobdetail ()); Jobstatisticbean.settrigger (Context.gettrigger ()); Jobstatisticbean.setstarttime (New Timestamp (System.currenttimemillis ())); Jobstatisticbean.setjobexecutioncontext (context); Jobstatisticbean.setjobintance (cOntext.getjobinstance ()); Threadlocal.set (Jobstatisticbean); } @Override public void jobexecutionvetoed (Jobexecutioncontext context) {Log.info ("jobexecutionvetoed" +cont Ext.getjobdetail (). GetName ()); } @Override public void jobwasexecuted (Jobexecutioncontext context, jobexecutionexception jobexception) {log . info ("Job execution completed" +context.getjobdetail (). GetName ()); Jobstatisticbean Jobstatisticbean = Threadlocal.get (); if (jobstatisticbean!=null) {jobstatisticbean.setendtime (New Timestamp (System.currenttimemillis ())); Jobstatisticbean.settakestime (Jobstatisticbean.getendtime (). GetTime ()-jobstatisticbean.getstarttime (). GetTime ( )); Statisticprocessor.add (Jobstatisticbean); } }}
The specific cache can be extended by itself, which is simply using the current JVM cache and can expand the Redis
public class Statisticprocessor extends Thread implements Applicationcontextaware, Initializingbean, Disposablebean {p Rivate static Logger logjob = Logger.getlogger (loggercategory.job_statistic); private static Logger Logjobhistory = Logger.getlogger (loggercategory.job_statistic_history); private static Logger logjobexception = Logger.getlogger (loggercategory.job_statistic_exception); private static volatile queue<jobstatisticbean> Jobqueue = new concurrentlinkedqueue<jobstatisticbean> (); private static volatile queue<schedulerexceptionbean> Exceptionqueue = new concurrentlinkedqueue< Schedulerexceptionbean> (); private static volatile map<string, jobstatisticbean> jobmap = new concurrenthashmap<string, jobstatisticbean& gt; (); /** * Manual Trigger Job * @param Jobstatisticbean * @return * @throws Exception */public static Boolean Runb Yhand (Jobstatisticbean Jobstatisticbean) throws exception{if (JoBstatisticbean==null) return false; Jobexecutioncontext context = Jobstatisticbean.getjobexecutioncontext (); Job Job = Jobstatisticbean.getjobintance (); Job.execute (context); return true; }/** * Add an instance of the job (use map to prevent duplication) and record the job execution record (Queue) * @param jobstatisticbean * @return * */public static Boolean Add (Jobstatisticbean Jobstatisticbean) {if (!jobmap.containskey (Jobstatisticbean.getjobname ())) { Logjob.info ("Add Job" + jacksonutil.tojsonstring (Jobstatisticbean)); } jobmap.put (Jobstatisticbean.getjobname (), Jobstatisticbean); Logjobhistory.info (jacksonutil.tojsonstring (Jobstatisticbean)); Return Jobqueue.add (Jobstatisticbean); }/** * Add execution Exception Log * @param Schedulerexceptionbean * @return * */public static Boolean add (Schedulerex Ceptionbean Schedulerexceptionbean) {logjobexception.info (jacksonutil.tojsonstring (SchedulerExceptionBean)); return exceptIonqueue.add (Schedulerexceptionbean); } public static list<jobstatisticbean> getalljobs () {int size = Jobmap.size (); Size = size>100? 100:size; Return Arrays.aslist (Jobmap.values (). ToArray (new jobstatisticbean[size]); } public static list<jobstatisticbean> getalljobhistory () {int size = Jobqueue.size (); Size = size>100? 100:size; Return Arrays.aslist (Jobqueue.toarray (new jobstatisticbean[size])); } public static list<schedulerexceptionbean> getallexceptions () {int size = Exceptionqueue.size (); Size = size>100? 100:size; Return Arrays.aslist (Exceptionqueue.toarray (new schedulerexceptionbean[size])); } private Volatile Boolean exit = FALSE; Private ApplicationContext applicationcontext = null; private static volatile statisticprocessor processorintance = null; Public synchronized void init () {if (processorintance==null) {logjob.info ("---------------------"+new Date (). toLocaleString () +"--------------------------"); Logjobhistory.info ("---------------------" +new Date (). toLocaleString () + "--------------------------"); Logjobexception.info ("---------------------" +new Date (). toLocaleString () + "--------------------------"); Processorintance = new Statisticprocessor (); Processorintance.setname (Gconstants.threa_head + "jobstatisticprocessor"); Processorintance.setdaemon (TRUE); Processorintance.start (); }} @Override public void Run () {do{try {thread.sleep (1000*30); Synchronized (jobqueue) {if (!jobqueue.isempty ()) {Long outsize = Jobqueue. Size ()-100; while (outsize--> 0) {jobqueue.poll (); }}} synchronized (Exceptionqueue) { if (!exceptionqueue.isempty ()) {Long outsize = exceptionqueue.size ()-100; while (outsize--> 0) {exceptionqueue.poll (); }}}}catch (Exception e) {e.printstacktrace (); }}while (!this.exit); } @Override public void Setapplicationcontext (ApplicationContext applicationcontext) throws Beansexception { This.applicationcontext = ApplicationContext; } @Override public void Afterpropertiesset () throws Exception {This.init (); } @Override public void Destroy () {this.exit = true; }}
public class Jobstatisticbean implements Serializable { private static long serialversionuid = -1l; Private String jobName; Private String className; Private Timestamp startTime; Private Timestamp endTime; Private Long takestime; Private Jobdetail Jobdetail; Private Trigger Trigger; Private Jobexecutioncontext Jobexecutioncontext; Private Job jobintance; //.. Getter & Setter}
Job.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-2.0.xsd "> <bean id=" Schedulerfactorybean "class=" Org.springframework.scheduling.quartz.SchedulerFactoryBean "lazy-init=" false "> <property name=" Schedulernam E "value=" Ezhe-taks "/> <property name=" triggers "> <list> <ref bean=" ta Sk1 "/> <ref bean=" Task2 "/> </list> </property> <property Name= "Globaljoblisteners" > <list> <bean class= "Com.gozap.ezhe.task.listener.Statis Ticjoblistener "> <property name=" name "value=" Job statistics "/> </bean> </list> </property&Gt <property name= "Schedulerlisteners" > <list> <bean class= "com.gozap.ezhe.task.list Ener. Statisticschedulerlistener "> </bean> </list> </property> < Property Name= "Autostartup" value= "true"/> <property name= "configlocation" value= "classpath:quartz.properties "/> </bean> <!--automatically update the exchange rate task--<bean id=" Task1 "class=" Org.springframework.scheduling.quartz.Cron Triggerbean "> <property name=" jobdetail "> <bean id=" jobupdatecurrencytask "class=" Org.sprin Gframework.scheduling.quartz.JobDetailBean "> <property name=" name "value=" Automatically update exchange rate Tasks "/> <property name= "Jobclass" value= "Com.gozap.ezhe.task.CurrencyUpdateTask" ></property> </bean& Gt </property> <property name= "cronexpression" value= "0 0/30 * * *?" /> </bean> <!--auto Xx Tasks--<bean id= "Task2" class= "Org.springframework.scheduling.quartz.CronTriggerBean" > <property na Me= "Jobdetail" > <bean id= "logisticsscheduletask" class= "Org.springframework.scheduling.quartz.JobDetailB Ean "> <property name=" name "value=" Automatic xx task "/> <property name=" Jobclass "value=" Com.gozap.ezhe.task.LogisticsScheduleTask "></property> </bean> </property> & Lt;property name= "cronexpression" value= "0 0 0/2 * *?" /> </bean></beans>
Jobstatisticaction.java
public class Jobstatisticaction extends Baseaction { private list<jobstatisticbean> joblist; Private list<jobstatisticbean> jobhistorylist; Private list<schedulerexceptionbean> jobexceptionlist; Public String jobstatistic () throws Exception { joblist = Statisticprocessor.getalljobs (); Jobhistorylist = Statisticprocessor.getalljobhistory (); Collections.reverse (jobhistorylist); Jobexceptionlist = Statisticprocessor.getallexceptions (); return action.success; } ============================ public list<jobstatisticbean> getjoblist () { return joblist; } Public list<jobstatisticbean> getjobhistorylist () { return jobhistorylist; } Public list<schedulerexceptionbean> getjobexceptionlist () { return jobexceptionlist; }}
job.jsp
<%@ page contenttype= "Text/html;charset=utf-8" language= "java"%><%@ taglib uri= "/struts-tags" prefix= "s"% ><%@ page import= "java.text.SimpleDateFormat"%><%@ page import= "Java.util.Date"%><% SimpleDateFormat SDF = new SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss. SSS "); String nowtime = Sdf.format (New Date ());%>