五. 使用 ServletContextListener
很值得一提的是你可以配置和集成 Quartz 到 Web 应用的另一种方式。从 2.3 版本的 Servlet API 开始,你能创建监听器,由容器在其生命周期中的某个特定时间回调。其中的一个监听器接口叫做 java.servlet.ServletContextListener,它包括有两个方法:
public void contextInitialized(ServletContextEvent sce);
public void contextDestroyed(ServeltContextEvent sce);
容器会在启动和关闭的时候相应的调用这两个方法。这就可以在 contextInitialized() 方法中初始化 Quartz Scheduler,并通过 contextDestroyed() 方法关闭它。代码 13.5 描述了这种用法:
代码 13.5. ServletContextListener 也能被用于初始化 Quartz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.SchedulerException; import org.quartz.impl.StdSchedulerFactory; public class QuartzServletContextListener implements ServletContextListener { private static Log logger = LogFactory .getLog(QuartzServletContextListener.class); public static final String QUARTZ_FACTORY_KEY = "org.quartz.impl.StdSchedulerFactory.KEY"; private ServletContext ctx = null; private StdSchedulerFactory factory = null; /** * Called when the container is shutting down. */ public void contextDestroyed(ServletContextEvent sce) { try { factory.getDefaultScheduler().shutdown(); } catch (SchedulerException ex) { logger.error("Error stopping Quartz", ex); } } /** * Called when the container is first started. */ public void contextInitialized(ServletContextEvent sce) { ctx = sce.getServletContext(); try { factory = new StdSchedulerFactory(); // Start the scheduler now factory.getScheduler().start(); logger.info("Storing QuartzScheduler Factory at" + QUARTZ_FACTORY_KEY); ctx.setAttribute(QUARTZ_FACTORY_KEY, factory); } catch (Exception ex) { logger.error("Quartz failed to initialize", ex); } } } |
正如我们在 QuartzInitializerServlet 中所做的,我们需要为这个监听器加入一些配置信息到 Web 部署描术文件(web.xml) 中。针对我们的监听器,我们需要加一个 <listener> 元素到部署描述中。如下片断中显示:
1 2 3 4 5 6 7 8 |
<web-app> <listener> <listener-class> org.cavaness.jobconsole.web.QuartzServletContextListener </listener-class> </listener> <!--Other deployment descriptor info not shown --> </web-app> |
·新的 QuartzInitializerListener 已加入到 Quartz 中
ServletContextListener 为顺应用户社区而来的呼声被加入到 Quartz 框架中。13.5 中的代码应当认为是一个例子,实际应用时你需要开发你自己的监听器。
本文链接 https://yanbin.blog/quartz-job-scheduling-framework-13-4/, 来自 隔叶黄莺 Yanbin Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
今天我又拜读了你的翻译大作!呵呵!
tomcat运行一段时间后,控制台报以下错误2009-03-06 09:38:21 [org.quartz.core.ErrorLogger]-[ERROR] An error occured while scanning for the next trigger to fire.org.quartz.JobPersistenceException: Couldn't rollback jdbc connection. Io 异常: Connection reset by peer: socket write error [See nested exception: java.sql.SQLException: Io 异常: Connection reset by peer: socket write error] at org.quartz.impl.jdbcjobstore.JobStoreSupport.rollbackConnection(JobStoreSupport.java:2319) at org.quartz.impl.jdbcjobstore.JobStoreTX.acquireNextTrigger(JobStoreTX.java:1222) at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:233)* Nested Exception (Underlying Cause) ---------------java.sql.SQLException: Io 异常: Connection reset by peer: socket write error at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134) at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179) at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:333) at oracle.jdbc.driver.OracleConnection.rollback(OracleConnection.java:1380) at org.apache.commons.dbcp.DelegatingConnection.rollback(DelegatingConnection.java:328) at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.rollback(PoolingDataSource.java:312) at org.quartz.impl.jdbcjobstore.JobStoreSupport.rollbackConnection(JobStoreSupport.java:2317) at org.quartz.impl.jdbcjobstore.JobStoreTX.acquireNextTrigger(JobStoreTX.java:1222) at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:233)2009-03-06 09:38:46 [org.quartz.impl.jdbcjobstore.JobStoreTX]-[ERROR] MisfireHandler: Error handling misfires: Couldn't rollback jdbc connection. Io 异常: Connection reset by peer: socket write errororg.quartz.JobPersistenceException: Couldn't rollback jdbc… Read more »
基本采用就该博文思路制作,根据
at org.quartz.impl.jdbcjobstore.JobStoreSupport.rollbackConnection(JobStoreSupport.java:2319)
查quartz源码,发现connection并不为空,但不知为何不能回滚,以及如何解决该问题,望赐教
必要时用 netstat -na 观察一下连接,异常看起来像连接被断开了。
//JobStoreSupport.java源码段
2315 if (conn != null) {
2316 try {
2317 conn.rollback();
2318 } catch (SQLException e) {
2319 throw new JobPersistenceException(
2320 "Couldn't rollback jdbc connection. "+e.getMessage(), e);
2321 }
2322 }
2324 }
以上信息发现conn并不为空,但不知为何不能回滚,以及如何解决该问题,望赐教
再附:数据库采用是oracle 11g
物理连接断了, conn 也不会为 null 的,用 conn.isClosed() 判断一下看看,必要时观察一下那个特定的连接是不是还通着的。
我故意拔掉客户端网线,重新打开IE,其他页面正常,唯独停止点击执行如下代码
currScheduler.pauseTrigger(trigVO.getTriggerID(),currScheduler.DEFAULT_GROUP);
就会出错,出错信息同上
注:currScheduler不为空,参数也正确
望再赐教,3q
按理说,quartz是tomcat服务器自动运行的东东,不受客户端影响才对呀
那你要检查为什么连接会被断掉