[整理]在 Web App 中使用 Quartz 替换 Java 定时器
来源:互联网 发布:小米笔记本12.5编程 编辑:程序博客网 时间:2024/05/21 21:37
之前的项目里有使用定时器,每隔一段时间去 MQ 服务器拉取新的消息。
使用的是Java 自身的 TimerTask 以及监听器实现的,因为项目需求变更,回头查看代码时,发现原来的实现不是很合理(一个Task里面做了多项操作),就找到Quarts这个开源框架了。
首先,看看原来使用Java提供的TimerTask 来实现定时触发的方法:
1.新建一个继承自java.util.TimerTask的类,重写其run()方法,这就是我们要定时执行的任务了:
import java.util.TimerTask;public class GetMessageTask extends TimerTask {@Overridepublic void run() {System.out.println("Ho ho, GetMessageTask is running @ "+ new java.util.Date());}}
2.新建一个定时器类,在这个类中定义一个java.util.Timer类型的属性用来定义我们的执行任务的开始时间以及,时间间隔:
public class GetMessageTimer {java.util.Timer timer;public void startTimer() {timer = new java.util.Timer();/** * 系统启动1分钟后开始执行任务 */java.util.GregorianCalendar gc = new java.util.GregorianCalendar();gc.setTime(new java.util.Date());gc.add(java.util.Calendar.MINUTE, 1);System.out.println("定时器 @ " + new java.util.Date() + "开启了!");/** * 每30000毫秒执行一次取数任务 */timer.schedule(new GetMessageTask(), gc.getTime(), 30000);}public void stopTimer() {if (timer != null)timer.cancel();System.out.println("定时器 @ " + new java.util.Date() + "关闭了!");}}
3.新建一个监听器,用于应用部署时,启动我们的定时器:
public class GetMessageListener implements ServletContextListener {GetMessageTimer timer = new GetMessageTimer();@Overridepublic void contextDestroyed(ServletContextEvent sce) {timer.stopTimer();}@Overridepublic void contextInitialized(ServletContextEvent sce) {timer.startTimer();}}
4.在web.xml中配置监听器:
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><listener><display-name>定时取数</display-name><listener-class>com.abc.web.timertask.GetMessageListener</listener-class></listener><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list></web-app>
这样我们就完成了,部署至Web 容器,查看控制台输出如下图:
由图所示,定时器开启1分钟以后,我们的任务每隔30秒执行一次。
接下来,我们看一下,怎样使用 Quartz 来实现上面的功能。
1.首先下载 Quartz 不必多说了。
Quartz官网:http://quartz-scheduler.org/
我下的版本为2.1.3
2.新建 java web app,将所需jar包导入项目:
3.我们是要在web app中使用quartz,查看官网文档http://quartz-scheduler.org/documentation/quartz-2.1.x/cookbook/ServletInitScheduler,我们可以看出,可以使用2种方法来启动quartz,这里我们使用servlert的方式来启动,修改web.xml如下:
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><servlet><servlet-name>QuartzInitializer</servlet-name><servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class><init-param><param-name>shutdown-on-unload</param-name><param-value>true</param-value></init-param><!-- 加载及启动定时任务 true --><init-param><param-name>start-scheduler-on-load</param-name><param-value>true</param-value></init-param><!-- 启动延迟时间 60秒 --><init-param><param-name>start-delay-seconds</param-name><param-value>60</param-value></init-param><load-on-startup>1</load-on-startup></servlet><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list></web-app>4.查看相关文档,我们要先创建我们要执行的Job:
public class GetMessageJob implements Job {@Overridepublic void execute(JobExecutionContext context)throws JobExecutionException {System.out.println("Hello, GetMessageJob is Executing @ "+ new java.util.Date());}}5.接着我们要新建Trigger,来告诉Schedule神马时候执Job,因为是测试没有集成其他框架,所以我就想到了quartz自带的QuartzInitializarServlet,这里我们改写这个Servlet。这个Servlet的源码,可以在下载的文档里找到,下面是我改写的Servlet:
public class InitializerQuartzServlet extends HttpServlet {private static final long serialVersionUID = 1L;public static final String QUARTZ_FACTORY_KEY = "org.quartz.impl.StdSchedulerFactory.KEY";private boolean performShutdown = true;private boolean waitOnShutdown = false;private transient Scheduler scheduler = null;@Overridepublic void init(ServletConfig cfg) throws javax.servlet.ServletException {super.init(cfg);System.out.println("Quartz Initializer Servlet 加载成功, initializing Scheduler...");StdSchedulerFactory factory;try {String configFile = cfg.getInitParameter("config-file");String shutdownPref = cfg.getInitParameter("shutdown-on-unload");if (shutdownPref != null) {performShutdown = Boolean.valueOf(shutdownPref).booleanValue();}String shutdownWaitPref = cfg.getInitParameter("wait-on-shutdown");if (shutdownPref != null) {waitOnShutdown = Boolean.valueOf(shutdownWaitPref).booleanValue();}factory = getSchedulerFactory(configFile);scheduler = factory.getScheduler();String startOnLoad = cfg.getInitParameter("start-scheduler-on-load");int startDelay = 0;String startDelayS = cfg.getInitParameter("start-delay-seconds");try {if (startDelayS != null && startDelayS.trim().length() > 0)startDelay = Integer.parseInt(startDelayS);} catch (Exception e) {log("Cannot parse value of 'start-delay-seconds' to an integer: "+ startDelayS + ", defaulting to 5 seconds.", e);startDelay = 5;}/* * 告诉scheduler要执行的任务,以及执行间隔时间,这里是30秒 */JobDetail getMessageJob = newJob(GetMessageJob.class).withIdentity("getDetailsJob", "group1").build();Trigger getMessageTrigger = newTrigger().withIdentity("getDetailsTrigger", "group1").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(30).repeatForever()).build();scheduler.scheduleJob(getMessageJob, getMessageTrigger);if (startOnLoad == null|| (Boolean.valueOf(startOnLoad).booleanValue())) {if (startDelay <= 0) {// Start nowscheduler.start();System.out.println("Scheduler has been started...");} else {// Start delayedscheduler.startDelayed(startDelay);System.out.println("Scheduler will start in " + startDelay+ " seconds.");}} else {System.out.println("Scheduler has not been started. Use scheduler.start()");}String factoryKey = cfg.getInitParameter("servlet-context-factory-key");if (factoryKey == null) {factoryKey = QUARTZ_FACTORY_KEY;}System.out.println("Storing the Quartz Scheduler Factory in the servlet context at key: "+ factoryKey);cfg.getServletContext().setAttribute(factoryKey, factory);String servletCtxtKey = cfg.getInitParameter("scheduler-context-servlet-context-key");if (servletCtxtKey != null) {System.out.println("Storing the ServletContext in the scheduler context at key: "+ servletCtxtKey);scheduler.getContext().put(servletCtxtKey,cfg.getServletContext());}} catch (Exception e) {System.out.println("Quartz Scheduler 初始化失败: "+ e.toString());throw new ServletException(e);}}protected StdSchedulerFactory getSchedulerFactory(String configFile)throws SchedulerException {StdSchedulerFactory factory;// get Propertiesif (configFile != null) {factory = new StdSchedulerFactory(configFile);} else {factory = new StdSchedulerFactory();}return factory;}@Overridepublic void destroy() {if (!performShutdown) {return;}try {if (scheduler != null) {scheduler.shutdown(waitOnShutdown);}} catch (Exception e) {System.out.println("Quartz Scheduler 停止失败: "+ e.toString());e.printStackTrace();}System.out.println("Quartz Scheduler 停止了.");}@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.sendError(HttpServletResponse.SC_FORBIDDEN);}@Overridepublic void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.sendError(HttpServletResponse.SC_FORBIDDEN);}}
6.这里我们看到初始化时需要一个quartz.properties的配置文件,我们从demo里面copy一个过来,稍作修改:
org.quartz.scheduler.instanceName: ExampleSchedulerorg.quartz.threadPool.threadCount: 3org.quartz.threadPool.class: org.quartz.simpl.SimpleThreadPoolorg.quartz.jobStore.class:org.quartz.simpl.RAMJobStore
7.不要忘了把web.xml中的servlet-class改成我们改写的servlet,最后配一个log4j.properties。部署到应用服务器查看控制台输出如下图:
上图所示,定时器在应用部署1分钟后开始启动,任务每隔30秒执行一次。
更高级的使用Quartz的方法,请大家参考cookbook。
- [整理]在 Web App 中使用 Quartz 替换 Java 定时器
- Quartz 在Java Web Application中使用
- Quartz 在Java Web Application中使用
- Quartz 在Java Web Application中使用
- Quartz-Java Web项目中使用Quartz
- java 定时器quartz使用
- Quartz 在Java Web Application中使用 定时任务
- 在WEB中,Quartz使用配置文件调用
- 在WEB中,Quartz使用配置文件调用
- spring 中使用Quartz 定时器
- SSM中使用Quartz定时器
- java 定时器 quartz的使用
- java定时器,在web工程中执行
- Web App使用Quartz实现java schedule job
- java的web项目中使用定时器
- 定时器Quartz在Spring中的使用
- Quartz使用 在程序中启停定时器
- Quartz使用 在程序中启停定时器
- BIZTALK 实践
- nginx 源码学习笔记(七)——内存分配相关源码分析
- 120315 QC案例导出
- jvm学习篇1- java类编译
- 第10章 DOM (四)
- [整理]在 Web App 中使用 Quartz 替换 Java 定时器
- VC小技巧20个
- android完美退出程序(创建单例管理所有打开的activity)
- 正则表达式使用
- HTTPS Everywhere Rulesets (zz)
- 数据结构——基本数据结构之栈
- 第10章 DOM (五)
- 数据结构——基本数据结构之队列
- 《C#异常处理》