- 浏览: 890218 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (687)
- java (127)
- servlet (38)
- struts (16)
- spring (22)
- hibernate (40)
- javascript (58)
- jquery (18)
- tomcat (51)
- 设计模式 (6)
- EJB (13)
- jsp (3)
- oracle (29)
- RUP (2)
- ajax (3)
- java内存管理 (4)
- java线程 (12)
- socket (13)
- path (5)
- XML (10)
- swing (2)
- UML (1)
- JBPM (2)
- 开发笔记 (45)
- Note参考 (15)
- JAXB (4)
- Quartz (2)
- 乱码 (2)
- CSS (2)
- Exception (4)
- Tools (7)
- sqlserver (3)
- DWR (7)
- Struts2 (47)
- WebService (2)
- 问题解决收藏 (7)
- JBOSS (7)
- cache (10)
- easyUI (19)
- jQuery Plugin (11)
- FreeMarker (6)
- Eclipse (2)
- Compass (2)
- JPA (1)
- WebLogic (1)
- powerdesigner (1)
- mybatis (1)
最新评论
-
bugyun:
受教了,谢谢
java 正则表达式 过滤html标签 -
xiongxingxing_123:
学习了,感谢了
java 正则表达式 过滤html标签 -
wanmeinange:
那如果无状态的。对同一个任务并发控制怎么做?比如继承Quart ...
quartz中参数misfireThreshold的详解 -
fanjieshanghai:
...
XPath 元素及属性查找 -
tianhandigeng:
还是没明白
quartz中参数misfireThreshold的详解
转载请表明出处,作者 keyboardsun
需要源代码,发邮件到keyboardsun@163.com
代码可以直接使用。
最近在开发JDF项目。项目中需要用到任务调度,自动任务等功能,想自己开发一个,但是看看 quartz 那么强劲,自己开发,开发加调试,可能需要些时日。如果用quartz可能一天就可以搞定,只需要配置点数据就可以了。
下面步入正题。讲解quartz的封装使用。
这里我把任务,以及任务的表达式配置到数据库里面。
如图:
如上图所示,配置了三个任务。
表结构介绍:
- -- ----------------------------
- -- Table structure for job_task
- -- ----------------------------
- CREATE TABLE `job_task` (
- `TASK_ID` int(11) NOT NULL,
- `TASK_CODE` varchar(255) default NULL,
- `TASK_TYPE` varchar(255) default NULL,
- `TASK_IMPL_CLASS` varchar(255) default NULL,
- `TASK_EXPRESS` varchar(50) default NULL,
- `STATE_DATE` datetime default NULL,
- `STATE` varchar(2) default NULL COMMENT 'U 使用中 O已结束',
- `PARMS` varchar(500) default NULL,
- `REMARK` varchar(2000) default NULL,
- `CREATE_DATE` datetime default NULL,
- PRIMARY KEY (`TASK_ID`)
- ) 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
字段解释
- -- ----------------------------
- -- Table structure for task_log
- -- ----------------------------
- CREATE TABLE `task_log` (
- `TASK_LOG_ID` int(8) NOT NULL,
- `TASK_ID` int(8) default NULL,
- `STATE` varchar(2) default NULL COMMENT 'O结束,R运行中,E异常结束',
- `START_DATE` datetime default NULL,
- `FINISH_DATE` datetime default NULL,
- `REMARKS` varchar(2000) default NULL,
- PRIMARY KEY (`TASK_LOG_ID`)
- ) 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
- package net.chinacsharp.jdf.quartz;
- import java.util.HashMap;
- /**
- * 业务系统需要实现的接口方法。
- *
- * @author keyboardsun
- */
- public interface ITask{
- /**
- * 这里留了一个execute接口给业务系统使用,业务系统写任务的时候,只需要继承Task类就可以了。
- *
- * @param map 这里的map功能可强劲了噢,因为很多任务执行可能需要传入参数,这个参数可以配置在JOB_TASK表的PARMS字段里面
- * 比如配置
- * <item>
- * <key>sss</key>
- * <value>vvv</value>
- * </item>
- * <item>
- * <key>ss</key>
- * <value>vv</value>
- * </item>
- * 这里在程序运行中,启动业务系统job的时候,会吧上面的记录已MAP的形式传递过去。
- * 这个在PARMS字段里面,那么在业务系统实现这个方法的时候,可以通过
- * map.get("ss") 获得 vv 值
- */
- public void execute( HashMap map );
- }
JDBC.java
- package net.chinacsharp.jdf.quartz;
- import java.io.StringReader;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.sql.Time;
- import java.sql.Timestamp;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- /**
- * 简单的数据库操作类
- * @author keyboardsun
- *
- */
- public class JDBC{
- /**
- * 获取数据库连接,这里的例子是用mysql的
- * @return
- * @throws Exception
- */
- public static Connection getConnection()throws Exception {
- try {
- Class.forName("com.mysql.jdbc.Driver").newInstance();
- Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/qz", "root", "admin");
- conn.setAutoCommit(true);
- return conn;
- } catch (Exception e) {
- throw e;
- }
- }
- /**
- * 插入操作日志,返回操作日志的主键的值。
- * 这里用了同步,可能执行过程中会影响效率,当然这里可以选择用static变量都是可以了,反正这是一个解决办法而已,随便你怎么搞,
- * 这个只是一个超级简单的例子,能看明白怎么回事就好了。
- * @param sql
- * @param map
- * @return
- * @throws Exception
- */
- public synchronized static TaskLogBean insert(String sql,HashMap map) throws Exception{
- Connection con = getConnection();
- String sql_ = "SELECT MAX(TASK_LOG_ID)+1 FROM TASK_LOG"; //获取最大的值+1 作为主键,这里方法比较土。
- PreparedStatement ps = con.prepareStatement(sql_);
- ResultSet rs = ps.executeQuery();
- rs.next();
- map.put("TASK_LOG_ID",new Long(rs.getLong(1)));
- rs.close();
- ps = execStatementValues(con,sql,map);
- ps.executeUpdate();
- sql_= "SELECT * FROM TASK_LOG WHERE TASK_LOG_ID=:TASK_LOG_ID";
- TaskLogBean[] bean = getTaskLogBean(con,sql_, map);
- return bean[0];
- }
- /**
- * 获取JOB的任务列表。
- * @param sql
- * @param map
- * @return
- * @throws Exception
- */
- public static JobTaskBean[] getJobTaskBean(String sql,HashMap map) throws Exception{
- Connection con = getConnection();
- PreparedStatement ps = execStatementValues(con,sql,map);
- ResultSet rs = ps.executeQuery();
- List list = new ArrayList();
- while(rs.next()){
- JobTaskBean bean = new JobTaskBean();
- bean.setCreateDate(rs.getTimestamp("CREATE_DATE"));
- bean.setParms(rs.getString("PARMS"));
- bean.setRemark(rs.getString("REMARK"));
- bean.setState(rs.getString("STATE"));
- bean.setStateDate(rs.getTimestamp("STATE_DATE"));
- bean.setTaskCode(rs.getString("TASK_CODE"));
- bean.setTaskExpress(rs.getString("TASK_EXPRESS"));
- bean.setTaskId(rs.getLong("TASK_ID"));
- bean.setTaskImplClass(rs.getString("TASK_IMPL_CLASS"));
- bean.setTaskType(rs.getString("TASK_TYPE"));
- list.add(bean);
- }
- rs.close();
- con.close();
- return list.size()==0?null:(JobTaskBean[])list.toArray(new JobTaskBean[0]);
- }
- /**
- * 获取任务日志记录
- * @param con
- * @param sql
- * @param map
- * @return
- * @throws Exception
- */
- public static TaskLogBean[] getTaskLogBean(Connection con,String sql,HashMap map) throws Exception{
- if(con==null)
- con = getConnection(); //这里连接可以传空,无所谓的。
- PreparedStatement ps = execStatementValues(con,sql,map);
- ResultSet rs = ps.executeQuery();
- List list = new ArrayList();
- while(rs.next()){
- TaskLogBean bean = new TaskLogBean();
- bean.setFinishDate(rs.getTimestamp("FINISH_DATE"));
- bean.setRemarks(rs.getString("REMARKS"));
- bean.setStartDate(rs.getTimestamp("START_DATE"));
- bean.setState(rs.getString("STATE"));
- bean.setTaskId(rs.getLong("TASK_ID"));
- bean.setTaskLogId(rs.getLong("TASK_LOG_ID"));
- list.add(bean);
- }
- rs.close();
- con.close();
- return list.size()==0?null:(TaskLogBean[])list.toArray(new TaskLogBean[0]);
- }
- /**
- * 以下方法用于绑定变量的,没啥技术含量。
- * 可以参看我的另外的数据库绑定变量的blog。
- * 更多代码可以去sourceforge下载jdf项目看看。
- * @param con 数据库连接
- * @param sql 绑定变量类型的sql
- * @param map 绑定值和绑定名字
- * @return 赋值初始化好的
- * @throws SQLException
- */
- public static PreparedStatement execStatementValues(Connection con,String sql,HashMap map) throws Exception{
- PreparedStatement stmt = null;
- ArrayList clumBandNameList = new ArrayList(); //存放绑定变量的名字
- sql = sql + " ";
- String [] temp = sql.split(":"); //这里把变量的名字给取出来
- for (int i = 1; i < temp.length; i++) {
- try{
- clumBandNameList.add(temp[i].substring(0,temp[i].indexOf(" ")));
- } catch(StringIndexOutOfBoundsException exception){
- clumBandNameList.add(temp[i]);
- }
- }
- sql = sql.replaceAll(":(.*?)\\s","?");//把绑定变量的名字:XXX 取出为 ?,生成标准SQL
- stmt = con.prepareStatement(sql);
- int index = 0;
- for (int i = 0; i < clumBandNameList.size(); i++) {
- if(map==null||map.size()<1){
- throw new SQLException("有的变量的值没有赋,请确定每个绑定的都有值了:"+sql+"\n"+map.toString());
- }
- Object value = null;
- try{
- value = map.get(clumBandNameList.get(i));
- // log.debug("邦定变量的值:"+clumBandNameList.get(i)+"="+value.toString());
- }catch(Exception e){
- throw new Exception("变量:"+clumBandNameList.get(i)+" 没有对应绑定的值");
- }
- String type = value.getClass().getName().substring(value.getClass().getName().lastIndexOf(".")); //获取绑定的类型
- index = i+1; //绑定的索引
- if (type.equalsIgnoreCase("String")) {
- String content = value.toString();
- if (content.length() > 2000) {
- stmt.setCharacterStream(index, new StringReader(content), content.length());
- } else {
- stmt.setString(index, content);
- }
- } else if (type.equalsIgnoreCase("Short")) {
- stmt.setShort(index, Short.parseShort(value.toString()));
- } else if (type.equalsIgnoreCase("Integer")) {
- stmt.setInt(index, Integer.parseInt(value.toString()));
- } else if (type.equalsIgnoreCase("Float")) {
- stmt.setFloat(index, Float.parseFloat(value.toString()));
- } else if (type.equalsIgnoreCase("Byte")) {
- stmt.setByte(index, Byte.parseByte(value.toString()));
- } else if (type.equalsIgnoreCase("Char")) {
- stmt.setString(index, value.toString());
- } else if (type.equalsIgnoreCase("Long")) {
- stmt.setLong(index, Long.parseLong(value.toString()));
- } else if (type.equalsIgnoreCase("Double")) {
- stmt.setDouble(index, Double.parseDouble(value.toString()));
- }else if (type.equalsIgnoreCase("Boolean")) {
- stmt.setBoolean(index, Boolean.getBoolean(value.toString()));
- } else if (type.equalsIgnoreCase("Date")) {
- if (value instanceof java.sql.Date)
- stmt.setDate(index, (java.sql.Date)value);
- else
- stmt.setDate(index, java.sql.Date.valueOf(value.toString()));
- } else if (type.equalsIgnoreCase("Time")) {
- if (value instanceof Time)
- stmt.setTime(index, (Time)value);
- else
- stmt.setTime(index, Time.valueOf(value.toString()));
- } else if (type.equalsIgnoreCase("DateTime")) {
- if (value instanceof Timestamp)
- stmt.setTimestamp(index, (Timestamp)value);
- else if (value instanceof java.sql.Date)
- stmt.setTimestamp(index, new Timestamp(((java.sql.Date)value).getTime()));
- else
- stmt.setTimestamp(index, Timestamp.valueOf(value.toString()));
- }
- else if(type.equalsIgnoreCase("Timestamp")){
- stmt.setTimestamp(index, (Timestamp)value);
- }
- else if (value instanceof Character) {
- stmt.setString(index, value.toString());
- } else {
- stmt.setObject(index, value);
- }
- }
- return stmt;
- }
- }
JobEngine.java
- package net.chinacsharp.jdf.quartz;
- import java.io.ByteArrayInputStream;
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import org.dom4j.Document;
- import org.dom4j.Element;
- import org.dom4j.io.SAXReader;
- import org.quartz.CronTrigger;
- import org.quartz.Job;
- import org.quartz.JobDataMap;
- import org.quartz.JobDetail;
- import org.quartz.JobExecutionContext;
- import org.quartz.JobExecutionException;
- import org.quartz.Scheduler;
- /**
- * 这只是一个简单的JOB而已,名字貌似很NB,这个任务用于实时的检测任务列表的状态,用于更新JOB。
- * 这样你改了个配置,可以立马生效的噢。
- * 这个类用于在JOB运行期间,使得修改立马生效。
- * @author keyboardsun
- *
- */
- public class JobEngine
- implements Job{
- public void execute( JobExecutionContext arg0 ) throws JobExecutionException{
- try{
- Scheduler inScheduler = arg0.getScheduler();
- JobDetail job = null;
- JobDataMap map = null;
- CronTrigger trigger = null;
- /**
- * 这里根据状态U使用的,以及STATE_DATE日期大于当前日期,判断这个任务是刚更新的,如果你想使得修改的JOB立马生效。你需要吧JOB_TASK的字段的值改得大于当前日期,那样这里就会更新到了噢。
- */
- JobTaskBean[] bean = JDBC.getJobTaskBean( "SELECT * FROM JOB_TASK WHERE STATE='U' AND STATE_DATE>now()", new HashMap() );
- if( bean == null )
- return;
- for( int i = 0; i < bean.length; i++ ){
- //这里使得修改的job更新,为了避免重复更新,需要吧STATE_DATE日期改过来。
- String update = "UPDATE JOB_TASK SET STATE_DATE=now() WHERE TASK_ID=:TASK_ID";
- Connection con = JDBC.getConnection();
- HashMap m = new HashMap();
- m.put( "TASK_ID", new Long( bean[i].getTaskId() ) );
- PreparedStatement ps = JDBC.execStatementValues( con, update, m );
- ps.executeUpdate();
- con.close();
- map = new JobDataMap();
-
发表评论
相关推荐
Quartz是一款广泛使用的开源任务调度框架,用于在Java应用程序中实现定时任务的执行。...如果你正在寻找一种方式来管理和调度Java应用程序中的定时任务,那么学习这个封装的Quartz实现可能会对你有所帮助。
4. **Quartz封装实现** - 可以创建一个JobFactory,用于生成自定义的Job实例。 - 设计一个JobStore,用于存储Job和Trigger的信息,可以选择内存型或数据库型。 - 提供配置文件,用于设置Scheduler的属性,如...
quartz scheduler 入门教程 Quartz Scheduler 是一种功能丰富、开源的任务调度程序库,可以在任何 Java 程序中使用。它可以用来创建简单或者复杂的执行次数可以达成千上万的任务。任务可以是任何 Java 可以做的事情...
本篇文章将深入探讨如何利用Quartz实现定时任务的分组、串行和并行动态配置。 首先,理解Quartz的核心概念是必要的。`Job`是执行任务的基本单元,`Trigger`则决定了何时触发Job。Quartz提供了`Scheduler`来管理和...
非常详细的Quartz详细入门教程。新手值得一看,高手请忽略。
本教程将深入探讨Quartz的核心概念、配置、API使用以及如何在实际项目中集成和管理定时任务。 一、Quartz核心概念 1. 作业(Job):在Quartz中,作业是需要执行的任务的抽象,它是一个实现了`org.quartz.Job`接口...
Quartz任务调度框架教程中文版 chm格式
SpringBoot整合Quartz实现定时任务调度是企业级应用中常见的需求,主要用于自动化执行某些周期性的任务,例如数据备份、报表生成、系统维护等。Quartz是一个功能强大的开源作业调度框架,能够灵活地定义任务和调度...
Autofac.Extras.Quartz, Quartz.Net的Autofac集成 Autofac.Extras.Quartz用于 Quartz.Net的Autofac集成包。Autofac.Extras.Quartz 为每个石英作业创建嵌套的litefime作用域。 完成作业执行后释放嵌套作用域。这允许...
Quartz 是一种功能丰富的,开放源码的作业调度库,可以在几乎任何Java应用程序集成 - 从最小的独立的应用程序到规模最大电子商务系统。Quartz可以用来创建简单或复杂的日程安排执行几十,几百,甚至是十万的作业数 -...
Quartz 是一个强大的开源作业调度框架,用于在 Java 应用程序中实现复杂的时间调度任务。它允许开发者创建、调度和执行周期性任务,而无需直接处理线程或时间触发器。在这个“quartz 实现按天、按周、按月定时任务的...
在本例中,Quartz的核心功能就封装在这些DLL文件中。 1. Quartz.dll:这是Quartz的主要库文件,包含了所有用于创建、管理和执行定时任务的类和接口。例如,`IScheduler`接口用于管理和控制调度器,`ITrigger`接口...
从以上位置可以查看详细介绍。 网上能找到的Quartz Web管理的资料都是使用的一个国外人写...包括可以添加一个任务(添加的任务只能是实现了Quartz Job接口的任务),暂停、启动、删除任务。基本这些都能满足日常应用了。
在Quartz中实现动态集群,主要是通过共享JobStore实现的,例如使用SQLJobStore,这样所有节点都可以访问同一个作业存储,从而确保任务的一致性和避免冲突。 在这个项目中,结合Quartz和Spring Batch,开发者可能...
Quartz.NET则是一个开源的作业调度库,适用于.NET平台,能够帮助开发者在.NET应用中实现复杂的时间驱动任务。结合使用Quartz.NET和TopShelf,我们可以构建一个在Windows服务中运行的定时任务调度系统。 Quartz.NET...
本篇文章将详细探讨如何在Spring Boot项目中整合Quartz,并通过MySQL数据库实现定时任务的动态配置。 首先,我们需要在项目中添加依赖。在Spring Boot的`pom.xml`文件中,引入Spring Boot的`spring-boot-starter-...
- 配置Quartz的`JobStore`实现,例如使用`RAMJobStore`(内存存储,适合小型应用)或` JDBCJobStore`(数据库存储,适合大型分布式系统)。 - 对于`JDBCJobStore`,需要正确配置数据库连接参数,如URL、用户名、密码...
正确设置并使用这些数据库表后,Quartz就可以在数据库中持久化作业和触发器的状态,即使应用程序重启,也能恢复之前设定的调度信息,实现任务的连续性和可靠性。 总之,"quartz quartz-1.8.6 dbTables" 提供了构建...