我需要进行一些配置并在某处连接到外部资源/对象/系统并将其存储在应用程序范围内。
我可以看到两种设置应用程序的方法:
init()
在现有的 servlet 和所需的代码中,并将所有构造的对象保存在同一个 servlet 中。 init()
做这项工作。然后将创建的对象存储在 ServletContext
与我的其他 servlet 共享它。 以上哪种方法更好?有没有更好的方法在 servlet 之间共享对象?直接从彼此之间调用他们……?
请您参考如下方法:
两者都不是更好的方法。 Servlet 旨在监听 HTTP 事件(HTTP 请求),而不是部署事件(启动/关闭)。
CDI/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 并且无法升级(因为 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 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.
}
}
这可以通过
@Inject
在 servlet 中使用。 .如有必要,也可以
@Named
所以它可以通过
#{config}
获得在 EL 中也是如此。
应该注意的是,这是自 CDI 1.1 以来的新功能。如果您仍在使用 CDI 1.0 并且无法升级,请选择另一种方法。
如果您对如何在 Tomcat 等非 JEE 服务器上安装 CDI 感到好奇,请访问: How to install and use CDI on Tomcat?
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 中使用。 .与其他方法的不同之处在于它默认是事务性的,如果是
@Singleton
也读/写锁定。因此,如果您需要将随机 EJB(例如
@Stateless
)注入(inject)
@WebListener
或
@ApplicationScoped
那么您基本上可以将两者合并为一个
@Startup @Singleton
.
也可以看看: