定时器(quartz+spring)读取数据库配置
??? 今天把项目中的一部分移出来,主要是实现定时器任务,定时任务是从数据库配置的的,所以采用spring读取数据库配置文件来实现定时器。
需要的JAR包 见上传文件
数据建立? 见上传文件
数据库映射类:
package com.quartz;
public class DbsynConfigQuartz {
???
??? // Fields
??? private String triggername;
??? private String cronexpression;
??? private String jobdetailname;
??? private String targetobject;
??? private String methodname;
??? private String concurrent;
??? private String state;
??? private String readme;
??? private String isspringbean;
??? // Constructors
??? /** default constructor */
??? public DbsynConfigQuartz() {
??? }
??? /** minimal constructor */
??? public DbsynConfigQuartz(String triggername, String jobdetailname,
??? ??? ??? String targetobject, String concurrent, String state,String isspringbean) {
??? ??? this.triggername = triggername;
??? ??? this.jobdetailname = jobdetailname;
??? ??? this.targetobject = targetobject;
??? ??? this.concurrent = concurrent;
??? ??? this.state = state;
??? ??? this.isspringbean=isspringbean;
??? }
??? /** full constructor */
??? public DbsynConfigQuartz(String triggername, String cronexpression,
??? ??? ??? String jobdetailname, String targetobject, String methodname,
??? ??? ??? String concurrent, String state, String readme,String isspringbean) {
??? ??? this.triggername = triggername;
??? ??? this.cronexpression = cronexpression;
??? ??? this.jobdetailname = jobdetailname;
??? ??? this.targetobject = targetobject;
??? ??? this.methodname = methodname;
??? ??? this.concurrent = concurrent;
??? ??? this.state = state;
??? ??? this.readme = readme;
??? ??? this.isspringbean=isspringbean;
??? }
??? // Property accessors
??? public String getTriggername() {
??? ??? return this.triggername;
??? }
??? public void setTriggername(String triggername) {
??? ??? this.triggername = triggername;
??? }
??? public String getCronexpression() {
??? ??? return this.cronexpression;
??? }
??? public void setCronexpression(String cronexpression) {
??? ??? this.cronexpression = cronexpression;
??? }
??? public String getJobdetailname() {
??? ??? return this.jobdetailname;
??? }
??? public void setJobdetailname(String jobdetailname) {
??? ??? this.jobdetailname = jobdetailname;
??? }
??? public String getTargetobject() {
??? ??? return this.targetobject;
??? }
??? public void setTargetobject(String targetobject) {
??? ??? this.targetobject = targetobject;
??? }
??? public String getMethodname() {
??? ??? return this.methodname;
??? }
??? public void setMethodname(String methodname) {
??? ??? this.methodname = methodname;
??? }
??? public String getConcurrent() {
??? ??? return this.concurrent;
??? }
??? public void setConcurrent(String concurrent) {
??? ??? this.concurrent = concurrent;
??? }
??? public String getState() {
??? ??? return this.state;
??? }
??? public void setState(String state) {
??? ??? this.state = state;
??? }
??? public String getReadme() {
??? ??? return this.readme;
??? }
??? public void setReadme(String readme) {
??? ??? this.readme = readme;
??? }
??? public String getIsspringbean() {
??? ??? return isspringbean;
??? }
??? public void setIsspringbean(String isspringbean) {
??? ??? this.isspringbean = isspringbean;
??? }
???
}
连接数据库公共方法:
package com.util;
import java.io.File;
import java.sql.BatchUpdateException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
public class Connect {
??? private static int tag1 = 0;
??? private static Logger log = Logger.getLogger(Connect.class);
??? private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
??? /**
??? ?* 获得数据连接
??? ?*
??? ?* @return
??? ?*/
??? public static Connection getCon(String name) {
??? ??? Connection connection = null;
??? ??? try {// 保证只进行一次初始化
??? ??? ??? if (tag1 == 0) {
??? ??? ??? ??? tag1++;
??? ??? ??? ??? Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
??? ??? ??? }
??? ??? ??? connection = DriverManager.getConnection("proxool." + name);
??? ??? } catch (Exception e) {
??? ??? ??? e.printStackTrace();
??? ??? }
??? ??? return connection;
??? }
???
??? }
读取定时器触发类:
package com.quartz;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.scheduling.quartz.CronTriggerBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import com.util.Connect;
public class QuartzManager implements BeanFactoryAware {
??? private Logger log = Logger.getLogger(QuartzManager.class);
??? private Scheduler scheduler;
??? private static BeanFactory beanFactory = null;
??? // private ApplicationContext apc;
??? @SuppressWarnings("unused")
??? private void reScheduleJob() throws Exception, ParseException {
??? ??? // 通过查询数据库里计划任务来配置计划任务
??? ??? DbsynConfigQuartz d= new DbsynConfigQuartz();
??? ??? List<DbsynConfigQuartz> quartzList = this.getConfigQuartz();
??? ??? if (quartzList != null && quartzList.size() > 0) {
??? ??? ??? for (DbsynConfigQuartz tbcq : quartzList) {
??? ??? ??? ??? configQuatrz(tbcq);
??? ??? ??? }
??? ??? }
??? }
??? public boolean configQuatrz(DbsynConfigQuartz tbcq) {
??? ??? boolean result = false;
??? ??? try {
??? ??? ??? // 运行时可通过动态注入的scheduler得到trigger
??? ??? ??? CronTriggerBean trigger = (CronTriggerBean) scheduler.getTrigger(
??? ??? ??? ??? ??? tbcq.getTriggername(), Scheduler.DEFAULT_GROUP);
??? ??? ??? // 如果计划任务已存在则调用修改方法
??? ??? ??? if (trigger != null) {
??? ??? ??? ??? change(tbcq, trigger);
??? ??? ??? } else {
??? ??? ??? ??? // 如果计划任务不存在并且数据库里的任务状态为可用时,则创建计划任务
??? ??? ??? ??? if (tbcq.getState().equals("1")) {
??? ??? ??? ??? ??? this.createCronTriggerBean(tbcq);
??? ??? ??? ??? }
??? ??? ??? }
??? ??? ??? result = true;
??? ??? } catch (Exception e) {
??? ??? ??? result = false;
??? ??? ??? e.printStackTrace();
??? ??? }
??? ??? return result;
??? }
??? public void change(DbsynConfigQuartz tbcq, CronTriggerBean trigger)
??? ??? ??? throws Exception {
??? ??? // 如果任务为可用
??? ??? if (tbcq.getState().equals("1")) {
??? ??? ??? // 判断从DB中取得的任务时间和现在的quartz线程中的任务时间是否相等
??? ??? ??? // 如果相等,则表示用户并没有重新设定数据库中的任务时间,这种情况不需要重新rescheduleJob
??? ??? ??? if (!trigger.getCronExpression().equalsIgnoreCase(
??? ??? ??? ??? ??? tbcq.getCronexpression())) {
??? ??? ??? ??? trigger.setCronExpression(tbcq.getCronexpression());
??? ??? ??? ??? scheduler.rescheduleJob(tbcq.getTriggername(),
??? ??? ??? ??? ??? ??? Scheduler.DEFAULT_GROUP, trigger);
??? ??? ??? ??? log.info(new Date() + ": 更新" + tbcq.getTriggername() + "计划任务");
??? ??? ??? }
??? ??? } else {
??? ??? ??? // 不可用
??? ??? ??? scheduler.pauseTrigger(trigger.getName(), trigger.getGroup());// 停止触发器
??? ??? ??? scheduler.unscheduleJob(trigger.getName(), trigger.getGroup());// 移除触发器
??? ??? ??? scheduler.deleteJob(trigger.getJobName(), trigger.getJobGroup());// 删除任务
??? ??? ??? log.info(new Date() + ": 删除" + tbcq.getTriggername() + "计划任务");
??? ??? }
??? }
??? /**
??? ?* 创建/添加计划任务
??? ?*
??? ?* @param tbcq
??? ?*??????????? 计划任务配置对象
??? ?* @throws Exception
??? ?*/
??? public void createCronTriggerBean(DbsynConfigQuartz tbcq) throws Exception {
??? ??? // 新建一个基于Spring的管理Job类
??? ??? MethodInvokingJobDetailFactoryBean mjdfb = new MethodInvokingJobDetailFactoryBean();
??? ??? mjdfb.setName(tbcq.getJobdetailname());// 设置Job名称
??? ??? // 如果定义的任务类为Spring的定义的Bean则调用 getBean方法
??? ??? if (tbcq.getIsspringbean().equals("1")) {
??? ??? ??? mjdfb.setTargetObject(beanFactory.getBean(tbcq.getTargetobject()));// 设置任务类
??? ??? } else {
??? ??? ??? // 否则直接new对象
??? ??? ??? mjdfb.setTargetObject(Class.forName(tbcq.getTargetobject())
??? ??? ??? ??? ??? .newInstance());// 设置任务类
??? ??? }
??? ??? mjdfb.setTargetMethod(tbcq.getMethodname());// 设置任务方法
??? ??? mjdfb.setConcurrent(tbcq.getConcurrent().equals("0") ? false : true); // 设置是否并发启动任务
??? ??? mjdfb.afterPropertiesSet();// 将管理Job类提交到计划管理类
??? ??? // 将Spring的管理Job类转为Quartz管理Job类
??? ??? JobDetail jobDetail = new JobDetail();
??? ??? jobDetail = (JobDetail) mjdfb.getObject();
??? ??? jobDetail.setName(tbcq.getJobdetailname());
??? ??? scheduler.addJob(jobDetail, true); // 将Job添加到管理类
??? ??? // 新一个基于Spring的时间类
??? ??? CronTriggerBean c = new CronTriggerBean();
??? ??? c.setCronExpression(tbcq.getCronexpression());// 设置时间表达式
??? ??? c.setName(tbcq.getTriggername());// 设置名称
??? ??? c.setJobDetail(jobDetail);// 注入Job
??? ??? c.setJobName(tbcq.getJobdetailname());// 设置Job名称
??? ??? scheduler.scheduleJob(c);// 注入到管理类
??? ??? scheduler.rescheduleJob(tbcq.getTriggername(), Scheduler.DEFAULT_GROUP,
??? ??? ??? ??? c);// 刷新管理类
??? ??? log.info(new Date() + ": 新建" + tbcq.getTriggername() + "计划任务");
??? }
??? /**
??? ?* 查询数据库任务设置,返回列表
??? ?*
??? ?* @return 数据库任务设置列表
??? ?*/
??? public List<DbsynConfigQuartz> getConfigQuartz() {
??? ??? List<DbsynConfigQuartz> result = new ArrayList<DbsynConfigQuartz>();
??? ??? Connection con = null;
??? ??? Statement smt = null;
??? ??? ResultSet rs = null;
??? ???
??? ??? con = Connect.getCon("sys");
??? ??? try {
??? ??? ??? ? if(con!=null) {
??? ??? ??? ? smt = con.createStatement();
??? ??? ??? ? con.setAutoCommit(false);
??? ??? ??? ? rs? = smt
??? ??? ??? ??? ??? ??? .executeQuery("select triggername,cronexpression,jobdetailname,targetobject,methodname,concurrent,state,readme,isspringbean from dbsyn_config_quartz");
??? ??? ??? ? while (rs.next()) {
??? ??? ??? ??? ??? DbsynConfigQuartz tbcq = new DbsynConfigQuartz();
??? ??? ??? ??? ??? tbcq.setTriggername(rs.getString("triggername"));
??? ??? ??? ??? ??? tbcq.setCronexpression(rs.getString("cronexpression"));
??? ??? ??? ??? ??? tbcq.setJobdetailname(rs.getString("jobdetailname"));
??? ??? ??? ??? ??? tbcq.setTargetobject(rs.getString("targetobject"));
??? ??? ??? ??? ??? tbcq.setMethodname(rs.getString("methodname"));
??? ??? ??? ??? ??? tbcq.setConcurrent(rs.getString("concurrent"));
??? ??? ??? ??? ??? tbcq.setState(rs.getString("state"));
??? ??? ??? ??? ??? tbcq.setReadme(rs.getString("readme"));
??? ??? ??? ??? ??? tbcq.setIsspringbean(rs.getString("isspringbean"));
??? ??? ??? ??? ??? result.add(tbcq);
??? ??? ??? ??? }
??? ??? ??? ??? rs.close();
??? ??? ????? }
??? ??? ??? ? }catch (SQLException e) {
??? ??? ??? e.printStackTrace();
??? ??? }finally{
??? ??? ??? try {
??? ??? ??? ??? con.close();
??? ??? ??? } catch (SQLException e) {
??? ??? ??? ??? e.printStackTrace();
??? ??? ??? }
??? ??? }
??? ??? return result;
??? }
??? public Scheduler getScheduler() {
??? ??? return scheduler;
??? }
??? public void setScheduler(Scheduler scheduler) {
??? ??? this.scheduler = scheduler;
??? }
??? /*
??? ?* public ApplicationContext getApc() { return apc; }
??? ?*
??? ?* public void setApc(ApplicationContext apc) { this.apc = apc; }
??? ?*/
??? public void setBeanFactory(BeanFactory factory) throws BeansException {
??? ??? this.beanFactory = factory;
??? }
??? public BeanFactory getBeanFactory() {
??? ??? return beanFactory;
??? }
??
}
定时器调用方法类:
package com.client;
import org.apache.log4j.Logger;
public class DrvServiceImpl {
??? private static Logger log = Logger.getLogger(DrvServiceImpl.class);
??? public void getHz() {
??? ???
??? ??? System.out.println("调用成功");
???
??? ??? return;
??? }
???
}
applicationContext-quartz.xml? 配置定时器的spring文件
<?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:p="http://www.springframework.org/schema/p"
??? xmlns:context="http://www.springframework.org/schema/context"
??? xmlns:jee="http://www.springframework.org/schema/jee"
??? xmlns:tx="http://www.springframework.org/schema/tx"
??? xmlns:aop="http://www.springframework.org/schema/aop"
??? xsi:schemaLocation="
??? ??? ??? http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
??? ??? ??? http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
??? ??? ??? http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-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/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
??? <bean id="quartzManagerBean" ref="schedulerManager" />
??? </bean>
??? <bean id="quartzManagerJobDetail"
??? ??? ref="quartzManagerBean" />
??? ??? <property name="targetMethod" value="reScheduleJob" />
??? ??? <property name="concurrent" value="false" />
??? </bean>
??? <!-- 主定时计划 -->
??? <bean id="quartzManagerTrigger"
??? ??? ref="quartzManagerJobDetail" />
??? ??? <!-- 延时1分钟 执行任务 -->
??? ??? <property name="startDelay" value="1000" />
??? ??? <!-- 任务执行周期 5分钟 -->
??? ??? <property name="repeatInterval" value="6000" />
??? </bean>
??? <!-- 总管理类 如果将lazy-init='false'那么容器启动就会执行调度程序? -->
??? <bean id="schedulerManager" lazy-init="false" autowire="no"
??? ??? />
??? ??? ??? </list>
??? ??? </property>
??? </bean>
</beans>
proxool.xml数据库配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<something-else-entirely>
??? <proxool>
??? ??? <alias>sys</alias>
??? ??? <driver-url>
??? ??? ??? jdbc:oracle:thin:@localhost:1521:ajhz
??? ??? </driver-url>
??? ??? <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
??? ??? <driver-properties>
??? ??? ??? <property name="user" value="ajhz" />
??? ??? ??? <property name="password" value="ajhz" />
??? ??? ??? <property name="autoReconnect" value="true" />
??? ??? </driver-properties>
??? ??? <maximum-connection-count>70</maximum-connection-count>
??? ??? <minimum-connection-count>10</minimum-connection-count>
??? ??? <house-keeping-sleep-time>90000</house-keeping-sleep-time>
??? ??? <simultaneous-build-throttle>10</simultaneous-build-throttle>
??? ??? <prototype-count>5</prototype-count>
??? ??? <test-before-use>true</test-before-use>
??? ??? <house-keeping-test-sql>
??? ??? ??? select sysdate from dual
??? ??? </house-keeping-test-sql>
??? ??? <verbose>true</verbose>
??? ??? <statistics>10s,1m,1d</statistics>
??? ??? <statistics-log-level>ERROR</statistics-log-level>
??? </proxool>
???
</something-else-entirely>
log4j.properties日志配置文件:
log4j.rootLogger= info,logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
#log4j.appender.logfile.File=${catalina.base}/webapps/zdin/zdin.log
log4j.appender.logfile.MaxFileSize=512KB
log4j.appender.logfile.MaxBackupIndex=100
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
??? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
??? xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
??? http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
??? <!-- proxool连接池 -->
??? <servlet>
??? ??? <servlet-name>ServletConfigurator</servlet-name>
??? ??? <servlet-class>
??? ??? ??? org.logicalcobwebs.proxool.configuration.ServletConfigurator
??? ??? </servlet-class>
??? ??? <init-param>
??? ??? ??? <param-name>xmlFile</param-name>
??? ??? ??? <param-value>WEB-INF/classes/proxool.xml</param-value>
??? ??? </init-param>
??? ??? <load-on-startup>1</load-on-startup>
??? </servlet>
??? <servlet>
??? ??? <servlet-name>Admin</servlet-name>
??? ??? <servlet-class>
??? ??? ??? org.logicalcobwebs.proxool.admin.servlet.AdminServlet
??? ??? </servlet-class>
??? </servlet>
??? <servlet>
??? ??? <servlet-name>contextConfigLocation</servlet-name>
??? ??? <servlet-class>
??? ??? ??? org.springframework.web.context.ContextLoaderServlet
??? ??? </servlet-class>
??? ??? <load-on-startup>2</load-on-startup>
??? </servlet>
??? <context-param>
??? ??? <param-name>contextConfigLocation</param-name>
??? ??? <param-value>classpath:applicationContext*.xml</param-value>
??? </context-param>
???
??? <welcome-file-list>
??? ??? <welcome-file>index.jsp</welcome-file>
??? </welcome-file-list>
</web-app>