在我们工程中用到定时数据的时候一般都是使用数据库的定时调度功能实现的,最近做“客服现场管理工具”的时候是用了quartz来进行调度,把数据用json储存,这样对数据库就没有太大的压力了。Spring框架很好的整合了quartz,在web环境下使用起来也比较方便。废话少说,上代码(功能简单:每到0分或者30分钟的时候执行)
好了,只需要写着一个业务逻辑的类就OK了,接下来就是spring中的配置了。
前两个bean都是在声明一个任务,第三个相当于触发器,按时间只要是0分钟或者30分钟就执行(任务的执行条件),而最后一个是把这个这个任务注册。
看到这里是不是感觉非常熟悉啊!~~~跟线程太相似了啊!我们对比一下:
任务--一个runnable
条件--一个thread(带了条件的)
工厂注册--线程池
其实quartz也不难,我们可以自己模拟调度
首先我们写个业务逻辑(简单偷懒点)
然后写runnable来(任务)进行调用
最后一步,用线程池把这两个线程加进去,如果是在web开发中,要触发任务的话,就可以自己写个listener,注册在web.xml中去。
在web.xml中加入
OK了,只要启动之后任务就可以按时执行了。
看了下quartz的源代码,他也基本上是这么实现的,当然肯定比上面的例子麻烦点。不过知道了他的思想,那些配置就能更好的理解了。另外java自带的也有这种功能,不过不太完善,在java.util包中有个Timer和TimerTask类,可以好好看看。
public class XlzbServiceImpl extends QuartzJobBean {
private XlzbDao xlzbDao;
private String path;
@SuppressWarnings({ "deprecation", "unchecked" })
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
JSONObject content = null;
List list = xlzbDao.getXlzbDataByTime();
Date date = new Date();
Date date1 = new Date(date.getTime() - 1800000);
DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
String fileName = format.format(date);
File file = new File(path + fileName);
BufferedReader reader = null;
Writer writer = null ;
if(file.exists()) {
try {
reader = new BufferedReader(new FileReader(file));
try {
String str = reader.readLine();
content = JSONObject.fromObject(str);
content.put(date1.getHours() + ":" + date1.getMinutes() + "--" +date.getHours() + ":" + date.getMinutes(), list);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
Map map = new HashMap();
map.put(date1.getHours() + ":" + date1.getMinutes() + "--" +date.getHours() + ":" + date.getMinutes(), list);
content = JSONObject.fromObject(map);
}
try {
writer = new BufferedWriter(new FileWriter(file));
writer.write(content.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(writer != null)
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void setXlzbDao(XlzbDao xlzbDao) {
this.xlzbDao = xlzbDao;
}
public void setPath(String path) {
this.path = path;
}
}
好了,只需要写着一个业务逻辑的类就OK了,接下来就是spring中的配置了。
<bean id="xlzbDaoImpl" class="net.xxt.xcgl.dao.impl.XlzbDaoImpl" >
<property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
<bean id="jobDetailBean" class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass" value="net.xxt.xcgl.service.impl.XlzbServiceImpl" />
<property name="jobDataAsMap">
<map>
<entry key="xlzbDao" value-ref="xlzbDaoImpl" />
<entry key="path" value="E:/xx/xxt_bgadmin/xcgl/createRestFile/"></entry>
</map>
</property>
</bean>
<bean id="cronTriggerBean" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="jobDetailBean" />
<property name="cronExpression" value="0 0,30 * * * ?"></property>
</bean>
<bean id="xlzb" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronTriggerBean"/>
</list>
</property>
</bean>
前两个bean都是在声明一个任务,第三个相当于触发器,按时间只要是0分钟或者30分钟就执行(任务的执行条件),而最后一个是把这个这个任务注册。
看到这里是不是感觉非常熟悉啊!~~~跟线程太相似了啊!我们对比一下:
任务--一个runnable
条件--一个thread(带了条件的)
工厂注册--线程池
其实quartz也不难,我们可以自己模拟调度
首先我们写个业务逻辑(简单偷懒点)
public class JobData {
//从数据库中去数据
public List<Map<String,String>> getData() throws Exception {
List<Map<String,String>> connectors = new ArrayList<Map<String,String>>();
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1", "root", "admin");
PreparedStatement pstmt = conn.prepareStatement("select * from connector1");
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
String id = String.valueOf(rs.getInt("id"));
String name = rs.getString("name");
String mobile = rs.getString("mobile");
String birthday = rs.getDate("birthday").toLocaleString();
Map<String,String> map = new HashMap<String,String>();
map.put("id", id);
map.put("name", name);
map.put("mobile", mobile);
map.put("birthday", birthday);
connectors.add(map);
}
return connectors;
}
//简单返回一个字符串
public String say() {
return "It's amazing....";
}
}
然后写runnable来(任务)进行调用
public class DemoJob implements Runnable{
@Override
public void run() {
JobData job = JobFactory.create();
while(true) {
try {
Date date = new Date();
if(date.getSeconds()==30) {
List<Map<String,String>> list = job.getData();
for(Map<String,String> map:list) {
System.out.println("id---->" + map.get("id"));
System.out.println("name---->" + map.get("name"));
System.out.println("mobile---->" + map.get("mobile"));
}
try {
//注意这里必须休眠1秒钟,道理自己想。不过线程的休眠不太准确,我也没找到好的办法
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class DemoJob1 implements Runnable {
@Override
public void run() {
JobData job = JobFactory.create();
while(true) {
Date date = new Date();
if(date.getSeconds()==0) {
String str = job.say();
System.out.println(str);
try {
//注意这里必须休眠1秒钟,道理自己想,不过线程的休眠不太准确,我也没找到好的办法
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
最后一步,用线程池把这两个线程加进去,如果是在web开发中,要触发任务的话,就可以自己写个listener,注册在web.xml中去。
public class SysContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
@Override
public void contextInitialized(ServletContextEvent sce) {
ExecutorService executor = Executors.newCachedThreadPool();
DemoJob demoJob = new DemoJob();
DemoJob1 demoJob1 = new DemoJob1();
executor.submit(demoJob);
executor.submit(demoJob1);
executor.shutdown();
}
}
在web.xml中加入
<listener> <listener-class>cn.xxt.spring2.SysContextListener</listener-class>
</listener>
OK了,只要启动之后任务就可以按时执行了。
看了下quartz的源代码,他也基本上是这么实现的,当然肯定比上面的例子麻烦点。不过知道了他的思想,那些配置就能更好的理解了。另外java自带的也有这种功能,不过不太完善,在java.util包中有个Timer和TimerTask类,可以好好看看。