【问题标题】:java ee background servicejava ee后台服务
【发布时间】:2011-04-09 23:27:04
【问题描述】:

如果我描述不正确,请原谅我,但本质上,我试图让一个类似服务的类在服务器启动时仅实例化一次,并在后台“存在”直到它在服务器停止时被杀死。至少据我所知,这与典型的 servlet 并不完全相同(尽管我可能对此有误)。更重要的是,我还需要能够在以后访问此服务/对象。

例如,在我参与的另一个项目中,我们使用 Spring 框架来完成类似的事情。本质上,我们使用配置 XML 文件和内置注释让 Spring 知道实例化我们的一些服务的实例。稍后,我们使用注解 @Autowired 来“抓取”这个预实例化的服务/对象的对象引用。

因此,尽管这似乎与 Java 本身的一些主要概念背道而驰,但我只是想弄清楚如何在这里重新发明这个*。我想有时我觉得这些大型应用程序框架在幕后做了太多的“黑盒魔法”,我真的希望能够对其进行微调。

感谢您的帮助和/或建议!


哦,我正在尝试从 JBoss 6 运行这一切

【问题讨论】:

  • Spring 的 IOC 和自动装配以何种方式不是您想要的?它使您可以创建任何其他类都可以访问的单例。
  • 我猜他当前的项目中没有 Spring。恕我直言,只为单身人士添加 Spring 将是一种矫枉过正。

标签: java servlets jakarta-ee


【解决方案1】:

这是一种方法。将 servlet 上下文侦听器添加到您的 web.xml,例如:

<listener>
    <listener-class>com.example.BackgroundServletContextListener</listener-class>
</listener>

然后创建该类来管理您的后台服务。在此示例中,我使用单线程 ScheduledExecutorService 来安排它每 5 分钟运行一次:

public class BackgroundServletContextListener implements ServletContextListener {
    private ScheduledExecutorService executor;
    private BackgroundService service;

    public void contextInitialized(ServletContextEvent sce) {
        service = new BackgroundService();

        // setup single thread to run background service every 5 minutes
        executor = Executors.newSingleThreadScheduledExecutor();
        executor.scheduleAtFixedRate(service, 0, 5, TimeUnit.MINUTES);

        // make the background service available to the servlet context
        sce.getServletContext().setAttribute("service", service);
    }

    public void contextDestroyed(ServletContextEvent sce) {
        executor.shutdown();
    }
}

public class BackgroundService implements Runnable {
    public void run() {
        // do your background processing here
    }
}

如果您需要通过网络请求访问BackgroundService,您可以通过ServletContext 访问它。例如:

ServletContext context = request.getSession().getServletContext();
BackgroundService service = (BackgroundService) context.getAttribute("service");

【讨论】:

  • 这很直观..我曾遇到过实现上下文侦听器的概念,但我只是不知道如何使该服务可用于 Web 应用程序的其他部分。 context.setAttribute() 似乎应该可以解决问题。谢谢!
  • 这很有帮助。我想知道它是否可以在 JBoss AS 5.1.0 上使用?我无法找到此版本中内置的 ServletContextListener ... servlet,但我确信这会导致一些兼容性问题。 5.1 有没有好的替代方案?
【解决方案2】:

您是否考虑过使用 EJB 3.1 会话 bean?这些可以部署在 war 文件中,并且可以使用 @Singleton 和 @Startup 进行注释。

EJB 3.1 提供的许多注释旨在将 Spring 的优点引入 Java EE 框架。这可能是您正在考虑的重新发明已经为您完成了。

【讨论】:

    【解决方案3】:

    如果您必须自己开发,您可以创建一个 servlet 并配置它在应用程序使用 load-on-startup 时启动。几年前我建立了一个这样的系统。然后我们使用新的(ish)java.util.concurrent 东西,比如ExecutorService 让它处理来自其他 servlet 的工作。

    有关您正在尝试做什么以及为什么现有的做事方式不足的更多信息会有所帮助。

    【讨论】:

      【解决方案4】:

      您可以为此使用messaging。只需向queue 发送消息,然后让message listener 处理asynchronously in the background。 您可以将JMS 用于实现,将ActiveMQ 用于消息代理。 Spring 有JMSTemplateJMSGateWaySupport API 让 JMS 实现变得简单

      http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jms.html

      【讨论】: