本文将要介绍自己项目中如何使用本地数据表存储数据源并执行定时任务,同时实现将配置文件中的绝对路径改为相对路径。原理大致相同,参考的底层代码。
1.自定义一个Servlet来替换org.jcrontab.web.loadCrontabServlet加载JCrontab(方法就是仿照loadCrontabServlet)
public class ServletJcrontab extends HttpServlet {
private static final long serialVersionUID = 4105652442492674804L;
private Crontab crontab = null;
/**
* 初始化方法
*/
public void init() throws ServletException {
System.out.print("Working?...");
process();
System.out.println("OK");
}
/**
* 加载属性文件并启动定时任务
*/
@SuppressWarnings("unchecked")
public void process() {
String propz = "/WEB-INF/classes/crontab/jcrontab.properties";
String props = getServletConfig().getInitParameter("PROPERTIES_FILE");
if (props == null) {
props = propz;
}
props = this.getServletContext().getRealPath(props);
Properties propObj = new Properties();
try {
InputStream input = createPropertiesStream(props);
propObj.load(input);
} catch (IOException ioe) {
ioe.printStackTrace();
}
ServletConfig c = getServletConfig();
Enumeration keys = c.getInitParameterNames();
while (keys.hasMoreElements()) {
String key = (String) keys.nextElement();
propObj.setProperty(key, c.getInitParameter(key));
}
String log4jpath = propObj.getProperty("org.jcrontab.log.log4J.Properties");
if (log4jpath != null) {
log4jpath = this.getServletContext().getRealPath(log4jpath);
propObj.setProperty("org.jcrontab.log.log4J.Properties", log4jpath);
}
String jcrontabconfig = propObj.getProperty("org.jcrontab.config");
if (jcrontabconfig != null) {
jcrontabconfig = this.getServletContext().getRealPath(jcrontabconfig);
propObj.setProperty("org.jcrontab.config", jcrontabconfig);
}
String datafile = propObj.getProperty("org.jcrontab.data.file");
if (datafile != null) {
datafile = this.getServletContext().getRealPath(datafile);
propObj.setProperty("org.jcrontab.data.file", datafile);
}
crontab = Crontab.getInstance();
try {
ShutdownHook();
crontab.init(propObj);
} catch (Exception e) {
Log.error(e.toString(), e);
}
}
/*
* 关闭定时任务
*/
public void ShutdownHook() throws Exception {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
doStop();
}
});
}
public void destroy() {
doStop();
}
public void doStop() {
Log.info("Shutting down...");
crontab.uninit(100);
Log.info("Stoped");
}
protected InputStream createPropertiesStream(String name)
throws IOException {
return new FileInputStream(name);
}
}
2.web.xml文件配置
<servlet>
<servlet-name>ServletJcrontab</servlet-name>
<servlet-class>com.kang.timerandcron.cron.ServletJcrontab</servlet-class>
<load-on-startup>200</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletJcrontab</servlet-name>
<url-pattern>/Startup</url-pattern>
</servlet-mapping>
3.持久化文件,作用是从数据表中读取数据源
public class JcrontabSQLSource implements DataSource {
private CrontabParser cp = new CrontabParser();
private Environment env;
private static JcrontabSQLSource instance;
public JcrontabSQLSource() {
env = Environment.getEnv();
}
public DataSource getInstance() {
if (instance == null) {
instance = new JcrontabSQLSource();
}
return instance;
}
public CrontabEntryBean find(CrontabEntryBean ceb)
throws CrontabEntryException, ClassNotFoundException, SQLException,
DataNotFoundException {
CrontabEntryBean[] cebra = findAll();
for (int i = 0; i < cebra.length; i++) {
if (cebra[i].equals(ceb)) {
return cebra[i];
}
}
throw new DataNotFoundException("Unable to find :" + ceb);
}
/**
* 底层会调用findAll方法加载数据源
*/
@SuppressWarnings("unchecked")
public CrontabEntryBean[] findAll() throws CrontabEntryException,
ClassNotFoundException, SQLException, DataNotFoundException {
String nodeType = Crontab.getInstance().getProperty("org.jcrontab.data.nodetype");
Vector list = new Vector();
// 从指定的表中读取数据源
String queryAll = " SELECT id,second,minute,hour,dayofmonth,month,dayofweek, "
+ " year, task, extrainfo FROM T_DWK_CRONTABEVENTS "
+ " where nodetype = " + nodeType + " and startOrClose = 1 ";
Connection conn = null;
java.sql.Statement st = null;
java.sql.ResultSet rs = null;
try {
conn = env.getConnection();
st = conn.createStatement();
rs = st.executeQuery(queryAll);
if (rs != null) {
while (rs.next()) {
boolean[] bSeconds = new boolean[60];
boolean[] bYears = new boolean[2500];
int id = rs.getInt("id");
String second = rs.getString("second");
String minute = rs.getString("minute");
String hour = rs.getString("hour");
String dayofmonth = rs.getString("dayofmonth");
String month = rs.getString("month");
String dayofweek = rs.getString("dayofweek");
String year = rs.getString("year");
String task = rs.getString("task");
String extrainfo = rs.getString("extrainfo");
String line = minute + " " + hour + " " + dayofmonth + " "
+ month + " " + dayofweek + " " + task + " "
+ extrainfo;
CrontabEntryBean ceb = cp.marshall(line);
cp.parseToken(year, bYears, false);
ceb.setId(id);
ceb.setBYears(bYears);
ceb.setYears(year);
cp.parseToken(second, bSeconds, false);
ceb.setBSeconds(bSeconds);
ceb.setSeconds(second);
ceb.setBusinessDays(true);
list.add(ceb);
}
rs.close();
} else {
throw new DataNotFoundException("定时任务底层sql出错了 ");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
st.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
conn.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
CrontabEntryBean[] result = new CrontabEntryBean[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = (CrontabEntryBean) list.get(i);
}
return result;
}
public void remove(CrontabEntryBean[] arg0) throws Exception {
// TODO Auto-generated method stub
}
public void store(CrontabEntryBean[] arg0) throws Exception {
// TODO Auto-generated method stub
}
}
4.jcrontab.properties
#端口号(查询条件)
org.jcrontab.data.nodetype=6666
#指定持久化文件为Java类,会自动调用里面的findAll()方法
org.jcrontab.data.datasource = com.kang.timerandcron.cron.JcrontabSQLSource
org.jcrontab.Crontab.refreshFrequency = 3
org.jcrontab.log.Logger=org.jcrontab.log.Log4JLogger
org.jcrontab.log.log4J.Properties=WEB-INF/classes/log4j.properties
5.自定义的两个定时任务
public class CrontabMainTest {
public static void main(String[] args) {
System.out.println(new Date());
System.out.print("调用main方法 ");
if (args.length > 0 && args != null) {
for (String str : args) {
System.out.print(str + " ");
}
System.out.println();
}
}
}
/**
* 需要实现Runnable接口,可以接收参数
* @author kang
*
*/
public class CrontabRunTest implements Runnable {
private String[] args;
public CrontabRunTest(String[] args) {
this.args = args;
}
public void run() {
System.out.println(new Date());
System.out.print("调用run方法 ");
if (args.length > 0 && args != null) {
for (String str : args) {
System.out.print(str + " ");
}
System.out.println();
}
}
}
6.相关sql语句
--创建表
create table T_DWK_CRONTABEVENTS
(
id NUMBER(10) primary key not null,
nodetype NUMBER(4) default 33,
title VARCHAR2(255),
second VARCHAR2(64) default '0',
minute VARCHAR2(256) default '*',
hour VARCHAR2(64) default '*',
dayofmonth VARCHAR2(64) default '*',
month VARCHAR2(64) default '*',
dayofweek VARCHAR2(64) default '*',
year VARCHAR2(64) default '*',
task VARCHAR2(255),
extrainfo VARCHAR2(512),
startorclose NUMBER(2) default 1,
createtime DATE default sysdate
);
comment on table T_DWK_CRONTABEVENTS
is '定时任务表';
-- Add comments to the columns
comment on column T_DWK_CRONTABEVENTS.id
is '主键id';
comment on column T_DWK_CRONTABEVENTS.nodetype
is '节点';
comment on column T_DWK_CRONTABEVENTS.title
is '定时任务名';
comment on column T_DWK_CRONTABEVENTS.second
is '秒';
comment on column T_DWK_CRONTABEVENTS.minute
is '分';
comment on column T_DWK_CRONTABEVENTS.hour
is '小时';
comment on column T_DWK_CRONTABEVENTS.dayofmonth
is '日';
comment on column T_DWK_CRONTABEVENTS.month
is '月';
comment on column T_DWK_CRONTABEVENTS.dayofweek
is '星期';
comment on column T_DWK_CRONTABEVENTS.year
is '年';
comment on column T_DWK_CRONTABEVENTS.task
is '类路径#方法名';
comment on column T_DWK_CRONTABEVENTS.extrainfo
is '参数';
comment on column T_DWK_CRONTABEVENTS.startorclose
is '开启活关闭';
comment on column T_DWK_CRONTABEVENTS.createtime
is '创建时间';
/*
--插入数据 */
insert into T_DWK_CRONTABEVENTS (id, nodetype, title, task, extrainfo)
values (1, '6666', 'dwk自己测试定时任务', 'com.kang.timerandcron.cron.process.CrontabRunTest#run', 'hello world')
insert into T_DWK_CRONTABEVENTS (id, nodetype, title, minute, task, extrainfo)
values (2, '6666', 'dwk自己测试定时任务', '*/2', 'com.kang.timerandcron.cron.process.CrontabMainTest#main', '')
备注:配置数据源和获取数据源的代码这里没有给出,大家可以根据需求自己编写