我需要进行一些配置并在某处连接到外部资源/对象/系统并将其存储在应用程序范围内。
我可以看到两种设置应用程序的方法:
- 覆盖
init()
现有 servlet 和所需的代码,并将所有构造的对象保留在同一个 servlet 中。 - 拥有某种初始化 servlet 并使用它
init()
来完成工作。然后存储创建的对象ServletContext
以与我的其他 servlet 共享。
以上哪种方法更好?有没有更好的方法在 servlet 之间共享对象?直接从彼此之间打电话给他们……?
我需要进行一些配置并在某处连接到外部资源/对象/系统并将其存储在应用程序范围内。
我可以看到两种设置应用程序的方法:
init()
现有 servlet 和所需的代码,并将所有构造的对象保留在同一个 servlet 中。init()
来完成工作。然后存储创建的对象ServletContext
以与我的其他 servlet 共享。以上哪种方法更好?有没有更好的方法在 servlet 之间共享对象?直接从彼此之间打电话给他们……?
两者都不是更好的方法。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 并且无法升级(因为 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");
// ...
}
它在 JSP EL 中也可用${config}
。所以你也可以把它变成一个简单的bean。
@Observes
在ApplicationScoped.class
import jakarta.enterprise.context.ApplicationScoped; // And thus NOT e.g. jakarta.faces.bean.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.
}
}
这在 servlet 中通过@Inject
. 如有必要,也可以制作它,@Named
以便它也可以通过#{config}
EL 获得。
应该注意的是,这是自 CDI 1.1 以来的新功能。如果您仍在使用 CDI 1.0 并且无法升级,请选择另一种方法。
如果您对如何在 Tomcat 等非 JEE 服务器上安装 CDI 感到好奇,请前往:如何在 Tomcat 上安装和使用 CDI?
@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.
}
}
这在 servlet 中通过@EJB
. 与其他方法的不同之处在于它默认是事务性的,并且在@Singleton
读/写锁定的情况下也是如此。因此,如果您需要将随机 EJB(例如@Stateless
)注入到 a@WebListener
或 an中,@ApplicationScoped
那么您基本上可以将两者合并到一个@Startup @Singleton
.