使用特殊的自动启动servlet在启动时初始化并共享应用程序数据

时间:2010-08-12 13:30:24

标签: servlets initialization data-sharing

我需要获取一些配置并连接到某处的外部资源/对象/系统,并将其存储在应用程序范围内。

我可以看到两种设置应用程序的方法:

  • 覆盖现有servlet中的init()和所需的代码,并将所有构造的对象保留在同一个servlet中。
  • 使用某种初始化servlet并使用其init()来完成工作。然后将创建的对象存储在ServletContext中以与其他servlet共享。

以上哪种方法更好?有没有更好的方法在servlet之间共享对象?直接从彼此打电话给他们......?

1 个答案:

答案 0 :(得分:72)

两者都不是更好的方法。 Servlet旨在侦听HTTP事件(HTTP请求),而不是侦听部署事件(启动/关闭)。


CDI / JSF / EJB不可用?使用ServletContextListener

@WebListener
public class Config implements ServletContextListener {

    public void contextInitialized(ServletContextEvent event) {
        // Do stuff during webapp's startup.
    }

    public void contextDestroyed(ServletContextEvent event) {
        // Do stuff during webapp's shutdown.
    }

}

如果您尚未使用Servlet 3.0且无法升级,因此无法使用@WebListener注释,则需要在/WEB-INF/web.xml中手动注册,如下所示:

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

要在应用程序范围内存储和获取对象(以便所有servlet都可以访问它们),请使用ServletContext#setAttribute()#getAttribute()

这是一个让侦听器将自己存储在应用程序范围内的示例:

    public void contextInitialized(ServletContextEvent event) {
        event.getServletContext().setAttribute("config", this);
        // ...
    }

然后在servlet中获取它:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        Config config = (Config) getServletContext().getAttribute("config");
        // ...
    }

它也可以通过${config}在JSP EL中使用。所以你也可以把它变成一个简单的bean。


CDI可用吗?在@Observes

上使用ApplicationScoped.class
import javax.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class Config {

    public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext context) {
        // Do stuff during webapp's startup.
    }

    public void destroy(@Observes @Destroyed(ApplicationScoped.class) ServletContext context) {
        // Do stuff during webapp's shutdown.
    }
}

这可以通过@Inject在servlet中找到。如有必要,也可以@Named使其也可以通过EL中的#{config}获取。

从CDI 1.1开始,这应该是新的。如果你仍然使用CDI 1.0并且无法升级,那么选择另一种方法。


JSF可用吗?使用@ManagedBean(eager=true)

import javax.faces.bean.ManagedBean
import javax.faces.bean.ApplicationScoped;

@ManagedBean(eager=true)
@ApplicationScoped
public class Config {

    @PostConstruct
    public void init() {
        // Do stuff during webapp's startup.
    }

    @PreDestroy
    public void destroy() {
        // Do stuff during webapp's shutdown.
    }
}

这也可以通过EL中的#{config}获得。


EJB可用吗?考虑@Startup @Singleton

@Startup
@Singleton
public class Config {

    @PostConstruct
    public void init() {
        // Do stuff during webapp's startup.
    }

    @PreDestroy
    public void destroy() {
        // Do stuff during webapp's shutdown.
    }
}

这可以通过@EJB在servlet中找到。我说“考虑”,因为你不应该为了启动钩子滥用EJB。此外,@Singleton默认为读/写锁定,主要用于事务性事务,例如调度后台作业。

另见: