我需要获取一些配置并连接到某处的外部资源/对象/系统,并将其存储在应用程序范围内。
我可以看到两种设置应用程序的方法:
init()
和所需的代码,并将所有构造的对象保留在同一个servlet中。init()
来完成工作。然后将创建的对象存储在ServletContext
中以与其他servlet共享。以上哪种方法更好?有没有更好的方法在servlet之间共享对象?直接从彼此打电话给他们......?
答案 0 :(得分:72)
两者都不是更好的方法。 Servlet旨在侦听HTTP事件(HTTP请求),而不是侦听部署事件(启动/关闭)。
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。
@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并且无法升级,那么选择另一种方法。
@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}
获得。
@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
默认为读/写锁定,主要用于事务性事务,例如调度后台作业。