【问题标题】:Appropriate use of a ServletContextListener in Java / Apache Tomcat web application在 Java / Apache Tomcat Web 应用程序中适当使用 ServletContextListener
【发布时间】:2009-09-10 11:08:43
【问题描述】:

谁能告诉我是否适合使用 ServletContextListener 来满足特定要求?

我有一个 Web 应用程序,它每小时运行一个特定的作业来轮询多个 RSS 提要,并且用户可以随时定义一个新的 RSS 提要进行轮询。

我要避免的是用户在当前的每小时轮询周期中添加提要并将此提要包含在该周期中。

所以我正在考虑使用带有静态布尔变量的 ServletContextListener,该变量记录轮询周期是否正在运行。如果每小时轮询周期正在运行,则用户定义的新提要不会包含在此周期中;如果轮询未运行,则可以在下一小时运行中包含提要。

谁能给点建议?我看到的唯一替代方法是在数据库表上使用标志或更新属性文件中的值(如果可以这样做的话)。

谢谢

马丁·奥谢。

【问题讨论】:

    标签: java rss


    【解决方案1】:

    这听起来是个坏主意。为什么不简单地为您的网络应用使用ServletContext 来保存网络应用的属性(“polling-cycle-running”)? Web 应用程序中启动作业的组件在上下文中设置属性;所有感兴趣的组件(例如您的 AddRSS 操作,理所当然地会在上下文中检查该属性。

    servletCtx.setAttribute(POLLING_CYCLE_FLAG_ATTR, true);
    

    if(!servletCtx.getAttribute((POLLING_CYCLE_FLAG_ATTR)) {
       // let the user add the feed ...
    }
    

    ServletContextListener 是关于网络应用程序的生命周期以及网络应用程序ServletContext 的更改。典型用途是为应用程序的模块初始化和清理资源。但基本上,如果您需要密切关注 ServletContext 中发生的事情,ServletContextListener 是您的朋友。

    【讨论】:

    • 这听起来正是需要的。那么 POLLING_CYCLE_FLAG_ATTR 成为 servlet 上下文中的全局变量?
    • 一个问题;我可以使用 servlet 在系统启动时将轮询设置为 no,但运行每小时轮询的类不是 servlet。可以从标准类访问 ServletContext 吗?还是应该转换轮询类?对我来说,如果 servlet 主要是请求/响应工具,这毫无意义。
    • 您说您的网络应用程序“每小时运行一项特定作业”,因此假设该作业是在网络应用程序内启动的。如果是这种情况,那么在启动作业时,您应该可以访问 servlet 上下文。您始终可以使用 Servlet 的 getServletContext() 方法访问 ServletContext。最好将上下文视为您的网络应用程序的命名空间。如果应用程序集群在许多节点上的容器上,那么您必须使用侦听器中的生命周期挂钩来同步来自共享资源(通常是 db)的上下文属性。
    【解决方案2】:

    您将提要数据保存在数据库中?不知道您如何访问数据库,但使用普通 jdbc,您可以选择要轮询和迭代结果集的提要。任何新添加的提要(在选择之后)都不会出现在此结果集中,因此不会被包含在内。

    如果由于某种原因这不适用于您的问题,您可以将这些专长读入一个集合并使用它。

    还是我完全错过了你的问题?

    【讨论】:

    • 你没有错过这个问题。我只是试图通过在轮询处于活动状态时设置一个标志来为事物增加一层安全性。这将通过将新的提要设置为在另一个时间轮询来防止在轮询时将新定义的提要添加到结果集中。
    • OP 是对的,这是数据库应该能够处理的事情。您只需要在读取提要的 JDBC 连接上设置隔离级别 SERIALIZABLE。但如果你真的想这样做......
    【解决方案3】:

    同意上一篇文章,ServletContext 属性是在 Servlet API 中创建某种“全局变量”的方式。

    这不适用于 servlet 容器实例,甚至是一个容器中的 Web 应用程序。每个都有自己的 ServletContext。如果您只有一个实例,它可以工作。否则我猜你需要一个数据库标志。

    Servlet 可以通过 init() 方法访问 ServletContext 对象。 ServletContextListeners 还通过 contextInitialized(ServletContextEvent sce) 生命周期事件获得访问权限。我认为你的 poll 类作为一个监听器存在是合理的,它以 ServletContext 生命周期开始和停止,是的。并且它在初始化时可以访问 ServletContext,是的。

    【讨论】:

    • 有一件事让我很困惑:我最终会得到两个课程; (1) 在应用程序启动时运行并将轮询设置为 no 的侦听器,以及 (2) 轮询类。您是说 (2) 应该转换为 servlet 还是侦听器?
    • 或者单个侦听器可以处理初始化和轮询吗?
    • 它很容易成为一类。它只需要实现监听器方法来接收启动/停止信号,并访问 ServletContext。除此之外,它可以做任何你喜欢的事情,没有理由必须是两个类。
    猜你喜欢
    • 1970-01-01
    • 2013-12-29
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 2011-11-07
    相关资源
    最近更新 更多