`

玩转 quartz quartz 教程 quartz 实现 quartz 封装

阅读更多

转载请表明出处,作者 keyboardsun

 

需要源代码,发邮件到keyboardsun@163.com

代码可以直接使用。

 

 

最近在开发JDF项目。项目中需要用到任务调度,自动任务等功能,想自己开发一个,但是看看 quartz    那么强劲,自己开发,开发加调试,可能需要些时日。如果用quartz可能一天就可以搞定,只需要配置点数据就可以了。

 

下面步入正题。讲解quartz的封装使用。

 

这里我把任务,以及任务的表达式配置到数据库里面。

 

如图:

 

如上图所示,配置了三个任务。

表结构介绍:

 

C-sharp代码 复制代码
  1. -- ----------------------------   
  2. -- Table structure for job_task   
  3. -- ----------------------------   
  4. CREATE TABLE `job_task` (   
  5.   `TASK_ID` int(11) NOT NULL,    
  6.   `TASK_CODE` varchar(255) default NULL,   
  7.   `TASK_TYPE` varchar(255) default NULL,   
  8.   `TASK_IMPL_CLASS` varchar(255) default NULL,   
  9.   `TASK_EXPRESS` varchar(50) default NULL,   
  10.   `STATE_DATE` datetime default NULL,   
  11.   `STATE` varchar(2) default NULL COMMENT 'U 使用中 O已结束',   
  12.   `PARMS` varchar(500) default NULL,   
  13.   `REMARK` varchar(2000) default NULL,   
  14.   `CREATE_DATE` datetime default NULL,   
  15.   PRIMARY KEY  (`TASK_ID`)   
  16. ) ENGINE=InnoDB DEFAULT CHARSET=gbk;  

 

字段介绍:

TASK_ID 任务的主键

TASK_CODE 任务编码 ,这里启动任务的时候,作为qz任务的名称

TASK_TYPE_CODE 任务类型,这里启动任务的时候,作为qz任务的分组

TASK_IMPL_CLASS 任务的类。

TASK_EXPRESS 任务执行表达式

STATE_DATE 任务更新时间,这里在任务运行中,如果需要使运行中的任务修改立马生效,需要把这个字段的值设置大于当前时间。

STATE 任务状态

PARMS 任务初始化参数,任务运行的时候,可以从JobDataMap对象中获取该字段的值。

CREATE_DATE 创建日期,没有什么实际意义。

 

下面需要记录任务执行的日志,如下图所示

如上图所示,log编号是12 的任务正在执行中... STATE是R =run

字段解释

 

C-sharp代码 复制代码
  1. -- ----------------------------   
  2. -- Table structure for task_log   
  3. -- ----------------------------   
  4. CREATE TABLE `task_log` (   
  5.   `TASK_LOG_ID` int(8) NOT NULL,   
  6.   `TASK_ID` int(8) default NULL,   
  7.   `STATE` varchar(2) default NULL COMMENT 'O结束,R运行中,E异常结束',   
  8.   `START_DATE` datetime default NULL,   
  9.   `FINISH_DATE` datetime default NULL,   
  10.   `REMARKS` varchar(2000) default NULL,   
  11.   PRIMARY KEY  (`TASK_LOG_ID`)   
  12. ) ENGINE=InnoDB DEFAULT CHARSET=gbk;  

 

 

TASK_LOG_ID 任务日志编号

TASK_ID 任务编号

STATE 执行状态,如果是E 的,说明异常了,异常信息会放在REMARKS字段中

START_DATE 执行开始时间

FINISH_DATE 执行结束时间

REMARKS 备注。

 

下面要开始贴代码啦:如下图所示,一共包括如下这么多的JAVA文件。

 

一共包括文件为:

ITask.java 业务系统需要实现的接口方法。

JDBC.java 简单的数据库操作类

JobEngine 用于修改运行中的job的信息,定时扫描JOB_TASK配置表的改变信息。

JobTaskBean.java 表JOB_TASK对应的bean

Mouse.java 入口类,启动qz引擎。

Task.java 抽象类,用于记录qz 任务的日志,业务系统的任务需要继承这个类。

TaskLogBean.java 任务日志表TASK_LOG对应的Bean.

Test.java 测试任务。

 

下面开始贴代码啦:

ITask.java

 

Java代码 复制代码
  1. package net.chinacsharp.jdf.quartz;   
  2.   
  3. import java.util.HashMap;   
  4.   
  5. /**  
  6.  * 业务系统需要实现的接口方法。  
  7.  *   
  8.  * @author keyboardsun  
  9.  */  
  10. public interface ITask{   
  11.   /**  
  12.    * 这里留了一个execute接口给业务系统使用,业务系统写任务的时候,只需要继承Task类就可以了。  
  13.    *   
  14.    * @param map 这里的map功能可强劲了噢,因为很多任务执行可能需要传入参数,这个参数可以配置在JOB_TASK表的PARMS字段里面  
  15.    * 比如配置   
  16.    * <item>  
  17.    * <key>sss</key>  
  18.    * <value>vvv</value>  
  19.    * </item>  
  20.    * <item>  
  21.    * <key>ss</key>  
  22.    * <value>vv</value>  
  23.    * </item>  
  24.    * 这里在程序运行中,启动业务系统job的时候,会吧上面的记录已MAP的形式传递过去。  
  25.    * 这个在PARMS字段里面,那么在业务系统实现这个方法的时候,可以通过  
  26.    * map.get("ss") 获得 vv 值  
  27.    */  
  28.   public void execute( HashMap map );   
  29. }  

 

 

JDBC.java

 

 

Java代码 复制代码
  1. package net.chinacsharp.jdf.quartz;   
  2.   
  3. import java.io.StringReader;   
  4. import java.sql.Connection;   
  5. import java.sql.DriverManager;   
  6. import java.sql.PreparedStatement;   
  7. import java.sql.ResultSet;   
  8. import java.sql.SQLException;   
  9. import java.sql.Time;   
  10. import java.sql.Timestamp;   
  11. import java.util.ArrayList;   
  12. import java.util.HashMap;   
  13. import java.util.List;   
  14. /**  
  15.  * 简单的数据库操作类  
  16.  * @author keyboardsun  
  17.  *  
  18.  */  
  19. public class JDBC{   
  20.        
  21.   /**  
  22.    * 获取数据库连接,这里的例子是用mysql的  
  23.    * @return  
  24.    * @throws Exception  
  25.    */  
  26.   public static Connection getConnection()throws Exception {   
  27.     try {   
  28.       Class.forName("com.mysql.jdbc.Driver").newInstance();   
  29.       Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/qz""root""admin");      
  30.       conn.setAutoCommit(true);   
  31.       return conn;   
  32.     } catch (Exception e) {   
  33.       throw e;   
  34.     }   
  35.   }   
  36.      
  37.   /**  
  38.    * 插入操作日志,返回操作日志的主键的值。  
  39.    * 这里用了同步,可能执行过程中会影响效率,当然这里可以选择用static变量都是可以了,反正这是一个解决办法而已,随便你怎么搞,  
  40.    * 这个只是一个超级简单的例子,能看明白怎么回事就好了。  
  41.    * @param sql  
  42.    * @param map  
  43.    * @return  
  44.    * @throws Exception  
  45.    */  
  46.   public synchronized static TaskLogBean insert(String sql,HashMap map) throws Exception{   
  47.     Connection con = getConnection();   
  48.     String sql_ = "SELECT MAX(TASK_LOG_ID)+1 FROM TASK_LOG"//获取最大的值+1 作为主键,这里方法比较土。   
  49.     PreparedStatement ps = con.prepareStatement(sql_);   
  50.     ResultSet rs = ps.executeQuery();   
  51.     rs.next();   
  52.     map.put("TASK_LOG_ID",new Long(rs.getLong(1)));   
  53.     rs.close();   
  54.     ps = execStatementValues(con,sql,map);   
  55.     ps.executeUpdate();   
  56.     sql_= "SELECT * FROM TASK_LOG WHERE TASK_LOG_ID=:TASK_LOG_ID";   
  57.     TaskLogBean[] bean = getTaskLogBean(con,sql_, map);   
  58.     return bean[0];       
  59.   }   
  60.      
  61.   /**  
  62.    * 获取JOB的任务列表。  
  63.    * @param sql  
  64.    * @param map  
  65.    * @return  
  66.    * @throws Exception  
  67.    */  
  68.   public static JobTaskBean[] getJobTaskBean(String sql,HashMap map) throws Exception{   
  69.     Connection con = getConnection();   
  70.     PreparedStatement ps = execStatementValues(con,sql,map);   
  71.     ResultSet rs = ps.executeQuery();   
  72.     List list = new ArrayList();   
  73.     while(rs.next()){   
  74.       JobTaskBean bean = new JobTaskBean();   
  75.       bean.setCreateDate(rs.getTimestamp("CREATE_DATE"));   
  76.       bean.setParms(rs.getString("PARMS"));   
  77.       bean.setRemark(rs.getString("REMARK"));   
  78.       bean.setState(rs.getString("STATE"));   
  79.       bean.setStateDate(rs.getTimestamp("STATE_DATE"));   
  80.       bean.setTaskCode(rs.getString("TASK_CODE"));   
  81.       bean.setTaskExpress(rs.getString("TASK_EXPRESS"));   
  82.       bean.setTaskId(rs.getLong("TASK_ID"));   
  83.       bean.setTaskImplClass(rs.getString("TASK_IMPL_CLASS"));   
  84.       bean.setTaskType(rs.getString("TASK_TYPE"));   
  85.       list.add(bean);   
  86.     }   
  87.     rs.close();   
  88.     con.close();   
  89.     return list.size()==0?null:(JobTaskBean[])list.toArray(new JobTaskBean[0]);   
  90.   }   
  91.      
  92.   /**  
  93.    * 获取任务日志记录  
  94.    * @param con  
  95.    * @param sql  
  96.    * @param map  
  97.    * @return  
  98.    * @throws Exception  
  99.    */  
  100.   public static TaskLogBean[] getTaskLogBean(Connection con,String sql,HashMap map) throws Exception{   
  101.     if(con==null)   
  102.      con = getConnection(); //这里连接可以传空,无所谓的。   
  103.     PreparedStatement ps = execStatementValues(con,sql,map);   
  104.     ResultSet rs = ps.executeQuery();   
  105.     List list = new ArrayList();   
  106.     while(rs.next()){   
  107.       TaskLogBean bean = new TaskLogBean();   
  108.       bean.setFinishDate(rs.getTimestamp("FINISH_DATE"));   
  109.       bean.setRemarks(rs.getString("REMARKS"));   
  110.       bean.setStartDate(rs.getTimestamp("START_DATE"));   
  111.       bean.setState(rs.getString("STATE"));        
  112.       bean.setTaskId(rs.getLong("TASK_ID"));   
  113.       bean.setTaskLogId(rs.getLong("TASK_LOG_ID"));   
  114.       list.add(bean);   
  115.     }   
  116.     rs.close();   
  117.     con.close();   
  118.     return list.size()==0?null:(TaskLogBean[])list.toArray(new TaskLogBean[0]);   
  119.   }   
  120.      
  121.   /**  
  122.    * 以下方法用于绑定变量的,没啥技术含量。  
  123.    * 可以参看我的另外的数据库绑定变量的blog。  
  124.    * 更多代码可以去sourceforge下载jdf项目看看。  
  125.    * @param con 数据库连接  
  126.    * @param sql 绑定变量类型的sql  
  127.    * @param map 绑定值和绑定名字  
  128.    * @return 赋值初始化好的  
  129.    * @throws SQLException  
  130.    */  
  131.   public static PreparedStatement execStatementValues(Connection con,String sql,HashMap map) throws Exception{   
  132.        
  133.     PreparedStatement stmt = null;   
  134.     ArrayList clumBandNameList = new ArrayList(); //存放绑定变量的名字   
  135.     sql = sql + " ";   
  136.     String [] temp = sql.split(":"); //这里把变量的名字给取出来   
  137.     for (int i = 1; i < temp.length; i++) {   
  138.       try{   
  139.       clumBandNameList.add(temp[i].substring(0,temp[i].indexOf(" ")));     
  140.       } catch(StringIndexOutOfBoundsException exception){   
  141.         clumBandNameList.add(temp[i]);     
  142.       }   
  143.     }      
  144.     sql = sql.replaceAll(":(.*?)\\s","?");//把绑定变量的名字:XXX 取出为 ?,生成标准SQL   
  145.        
  146.     stmt = con.prepareStatement(sql);   
  147.      
  148.     int index = 0;   
  149.        
  150.     for (int i = 0; i < clumBandNameList.size(); i++) {   
  151.       if(map==null||map.size()<1){           
  152.         throw new SQLException("有的变量的值没有赋,请确定每个绑定的都有值了:"+sql+"\n"+map.toString());   
  153.       }   
  154.       Object value = null;   
  155.       try{   
  156.         value = map.get(clumBandNameList.get(i));   
  157. //      log.debug("邦定变量的值:"+clumBandNameList.get(i)+"="+value.toString());       
  158.       }catch(Exception e){   
  159.         throw new Exception("变量:"+clumBandNameList.get(i)+" 没有对应绑定的值");   
  160.       }   
  161.              
  162.       String type = value.getClass().getName().substring(value.getClass().getName().lastIndexOf(".")); //获取绑定的类型   
  163.       index = i+1//绑定的索引       
  164.        if (type.equalsIgnoreCase("String")) {   
  165.             String content = value.toString();   
  166.             if (content.length() > 2000) {   
  167.               stmt.setCharacterStream(index, new StringReader(content), content.length());   
  168.             } else  {   
  169.               stmt.setString(index, content);   
  170.             }   
  171.           }  else if (type.equalsIgnoreCase("Short")) {              
  172.             stmt.setShort(index, Short.parseShort(value.toString()));              
  173.           } else if (type.equalsIgnoreCase("Integer")) {    
  174.             stmt.setInt(index, Integer.parseInt(value.toString()));   
  175.           }  else if (type.equalsIgnoreCase("Float")) {    
  176.             stmt.setFloat(index, Float.parseFloat(value.toString()));   
  177.           } else if (type.equalsIgnoreCase("Byte")) {    
  178.             stmt.setByte(index, Byte.parseByte(value.toString()));   
  179.           } else if (type.equalsIgnoreCase("Char")) {    
  180.             stmt.setString(index, value.toString());               
  181.           }   else if (type.equalsIgnoreCase("Long")) {    
  182.             stmt.setLong(index, Long.parseLong(value.toString()));   
  183.           } else if (type.equalsIgnoreCase("Double")) {    
  184.             stmt.setDouble(index, Double.parseDouble(value.toString()));   
  185.           }else if (type.equalsIgnoreCase("Boolean")) {   
  186.             stmt.setBoolean(index, Boolean.getBoolean(value.toString()));   
  187.           } else if (type.equalsIgnoreCase("Date")) {   
  188.             if (value instanceof java.sql.Date)   
  189.               stmt.setDate(index, (java.sql.Date)value);   
  190.             else  
  191.               stmt.setDate(index, java.sql.Date.valueOf(value.toString()));   
  192.           } else if (type.equalsIgnoreCase("Time")) {   
  193.             if (value instanceof Time)   
  194.               stmt.setTime(index, (Time)value);   
  195.             else  
  196.               stmt.setTime(index, Time.valueOf(value.toString()));   
  197.           } else if (type.equalsIgnoreCase("DateTime")) {   
  198.             if (value instanceof Timestamp)   
  199.               stmt.setTimestamp(index, (Timestamp)value);   
  200.             else if (value instanceof java.sql.Date)   
  201.               stmt.setTimestamp(index, new Timestamp(((java.sql.Date)value).getTime()));   
  202.             else  
  203.               stmt.setTimestamp(index, Timestamp.valueOf(value.toString()));   
  204.           }   
  205.           else if(type.equalsIgnoreCase("Timestamp")){   
  206.             stmt.setTimestamp(index, (Timestamp)value);   
  207.           }   
  208.           else if (value instanceof Character) {   
  209.             stmt.setString(index, value.toString());   
  210.           } else {   
  211.             stmt.setObject(index, value);   
  212.           }   
  213.     }   
  214.   
  215.     return stmt;   
  216.            
  217.   }   
  218.      
  219.      
  220. }  

 

 

JobEngine.java

 

 

C-sharp代码 复制代码
  1. package net.chinacsharp.jdf.quartz;   
  2.   
  3. import java.io.ByteArrayInputStream;   
  4. import java.sql.Connection;   
  5. import java.sql.PreparedStatement;   
  6. import java.util.Date;   
  7. import java.util.HashMap;   
  8. import java.util.Iterator;   
  9. import java.util.List;   
  10.   
  11. import org.dom4j.Document;   
  12. import org.dom4j.Element;   
  13. import org.dom4j.io.SAXReader;   
  14. import org.quartz.CronTrigger;   
  15. import org.quartz.Job;   
  16. import org.quartz.JobDataMap;   
  17. import org.quartz.JobDetail;   
  18. import org.quartz.JobExecutionContext;   
  19. import org.quartz.JobExecutionException;   
  20. import org.quartz.Scheduler;   
  21.   
  22. /**  
  23.  * 这只是一个简单的JOB而已,名字貌似很NB,这个任务用于实时的检测任务列表的状态,用于更新JOB。  
  24.  * 这样你改了个配置,可以立马生效的噢。  
  25.  * 这个类用于在JOB运行期间,使得修改立马生效。  
  26.  * @author keyboardsun  
  27.  *  
  28.  */  
  29. public class JobEngine   
  30.     implements Job{   
  31.   
  32.   public void execute( JobExecutionContext arg0 ) throws JobExecutionException{   
  33.   
  34.     try{   
  35.       Scheduler inScheduler = arg0.getScheduler();   
  36.       JobDetail job = null;   
  37.       JobDataMap map = null;   
  38.       CronTrigger trigger = null;   
  39.       /**  
  40.        * 这里根据状态U使用的,以及STATE_DATE日期大于当前日期,判断这个任务是刚更新的,如果你想使得修改的JOB立马生效。你需要吧JOB_TASK的字段的值改得大于当前日期,那样这里就会更新到了噢。  
  41.        */         
  42.       JobTaskBean[] bean = JDBC.getJobTaskBean( "SELECT * FROM JOB_TASK WHERE STATE='U' AND STATE_DATE>now()"new HashMap() );   
  43.       if( bean == null )   
  44.         return;   
  45.       forint i = 0; i < bean.length; i++ ){   
  46.         //这里使得修改的job更新,为了避免重复更新,需要吧STATE_DATE日期改过来。   
  47.         String update = "UPDATE JOB_TASK SET STATE_DATE=now() WHERE TASK_ID=:TASK_ID";   
  48.         Connection con = JDBC.getConnection();   
  49.         HashMap m = new HashMap();   
  50.         m.put( "TASK_ID"new Long( bean[i].getTaskId() ) );   
  51.         PreparedStatement ps = JDBC.execStatementValues( con, update, m );   
  52.         ps.executeUpdate();   
  53.         con.close();   
  54.         map = new JobDataMap();   
  55.      
    分享到:
    评论

相关推荐

    对Quartz的简单封装

    Quartz是一款广泛使用的开源任务调度框架,用于在Java应用程序中实现定时任务的执行。...如果你正在寻找一种方式来管理和调度Java应用程序中的定时任务,那么学习这个封装的Quartz实现可能会对你有所帮助。

    quartz封装

    4. **Quartz封装实现** - 可以创建一个JobFactory,用于生成自定义的Job实例。 - 设计一个JobStore,用于存储Job和Trigger的信息,可以选择内存型或数据库型。 - 提供配置文件,用于设置Scheduler的属性,如...

    quartz scheduler 入门教程

    quartz scheduler 入门教程 Quartz Scheduler 是一种功能丰富、开源的任务调度程序库,可以在任何 Java 程序中使用。它可以用来创建简单或者复杂的执行次数可以达成千上万的任务。任务可以是任何 Java 可以做的事情...

    定时任务quartz实现分组串行并行动态配置

    本篇文章将深入探讨如何利用Quartz实现定时任务的分组、串行和并行动态配置。 首先,理解Quartz的核心概念是必要的。`Job`是执行任务的基本单元,`Trigger`则决定了何时触发Job。Quartz提供了`Scheduler`来管理和...

    Quartz详细入门教程

    非常详细的Quartz详细入门教程。新手值得一看,高手请忽略。

    定时任务quartz及教程

    本教程将深入探讨Quartz的核心概念、配置、API使用以及如何在实际项目中集成和管理定时任务。 一、Quartz核心概念 1. 作业(Job):在Quartz中,作业是需要执行的任务的抽象,它是一个实现了`org.quartz.Job`接口...

    Quartz任务调度框架教程中文版

    Quartz任务调度框架教程中文版 chm格式

    SpringBoot 整合Quartz(集群)实现定时任务调度

    SpringBoot整合Quartz实现定时任务调度是企业级应用中常见的需求,主要用于自动化执行某些周期性的任务,例如数据备份、报表生成、系统维护等。Quartz是一个功能强大的开源作业调度框架,能够灵活地定义任务和调度...

    Autofac.Extras.Quartz, Quartz.Net的Autofac集成.zip

    Autofac.Extras.Quartz, Quartz.Net的Autofac集成 Autofac.Extras.Quartz用于 Quartz.Net的Autofac集成包。Autofac.Extras.Quartz 为每个石英作业创建嵌套的litefime作用域。 完成作业执行后释放嵌套作用域。这允许...

    Quartz源码+视频教程

    Quartz 是一种功能丰富的,开放源码的作业调度库,可以在几乎任何Java应用程序集成 - 从最小的独立的应用程序到规模最大电子商务系统。Quartz可以用来创建简单或复杂的日程安排执行几十,几百,甚至是十万的作业数 -...

    quartz 实现按天、按周、按月定时任务的简单demo

    Quartz 是一个强大的开源作业调度框架,用于在 Java 应用程序中实现复杂的时间调度任务。它允许开发者创建、调度和执行周期性任务,而无需直接处理线程或时间触发器。在这个“quartz 实现按天、按周、按月定时任务的...

    Quartz 定时WebForm和WinForm使用的dll

    在本例中,Quartz的核心功能就封装在这些DLL文件中。 1. Quartz.dll:这是Quartz的主要库文件,包含了所有用于创建、管理和执行定时任务的类和接口。例如,`IScheduler`接口用于管理和控制调度器,`ITrigger`接口...

    自开发实现Quartz Web管理工具

    从以上位置可以查看详细介绍。 网上能找到的Quartz Web管理的资料都是使用的一个国外人写...包括可以添加一个任务(添加的任务只能是实现了Quartz Job接口的任务),暂停、启动、删除任务。基本这些都能满足日常应用了。

    quartz整合springbatch动态集群定时实现mysql参考

    在Quartz中实现动态集群,主要是通过共享JobStore实现的,例如使用SQLJobStore,这样所有节点都可以访问同一个作业存储,从而确保任务的一致性和避免冲突。 在这个项目中,结合Quartz和Spring Batch,开发者可能...

    ASP.NET使用Quartz.NET实现定时任务调度

    Quartz.NET则是一个开源的作业调度库,适用于.NET平台,能够帮助开发者在.NET应用中实现复杂的时间驱动任务。结合使用Quartz.NET和TopShelf,我们可以构建一个在Windows服务中运行的定时任务调度系统。 Quartz.NET...

    Springboot整合Quartz实现定时任务数据库动态配置

    本篇文章将详细探讨如何在Spring Boot项目中整合Quartz,并通过MySQL数据库实现定时任务的动态配置。 首先,我们需要在项目中添加依赖。在Spring Boot的`pom.xml`文件中,引入Spring Boot的`spring-boot-starter-...

    quartz-2.2.3版本的quartz初始化sql语句

    - 配置Quartz的`JobStore`实现,例如使用`RAMJobStore`(内存存储,适合小型应用)或` JDBCJobStore`(数据库存储,适合大型分布式系统)。 - 对于`JDBCJobStore`,需要正确配置数据库连接参数,如URL、用户名、密码...

    quartz quartz-1.8.6 dbTables 建表sql

    正确设置并使用这些数据库表后,Quartz就可以在数据库中持久化作业和触发器的状态,即使应用程序重启,也能恢复之前设定的调度信息,实现任务的连续性和可靠性。 总之,"quartz quartz-1.8.6 dbTables" 提供了构建...

Global site tag (gtag.js) - Google Analytics