我需要获取一些配置并连接到外部资源/对象/系统的某个位置,并将其存储在应用程序范围内。
我可以看到两种设置应用程序的方法:
- 覆盖现有servlet中的
init()
,并在其中添加所需的代码,将所有构建的对象保留在同一个servlet中。 - 拥有某种初始化servlet,并使用其
init()
来完成工作。然后将创建的对象存储在ServletContext
中,以与其他servlet共享它。
上述哪种方法更好?是否有更好的方法来在servlet之间共享对象?直接相互调用还是如此...
我需要获取一些配置并连接到外部资源/对象/系统的某个位置,并将其存储在应用程序范围内。
我可以看到两种设置应用程序的方法:
init()
,并在其中添加所需的代码,将所有构建的对象保留在同一个servlet中。init()
来完成工作。然后将创建的对象存储在ServletContext
中,以与其他servlet共享它。上述哪种方法更好?是否有更好的方法来在servlet之间共享对象?直接相互调用还是如此...
两者都没有更好的方法。Servlets旨在侦听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.
}
}
<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。
ApplicationScoped.class
上使用@Observes
。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
,以便在EL中通过#{config}
使用。
需要注意的是,这是CDI 1.1之后的新功能。如果您仍在使用CDI 1.0并且无法升级,则选择其他方法。
如果您想知道如何在非JEE服务器(如Tomcat)上安装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.
}
}
通过@EJB
,可以在Servlet中使用此功能。与其他方法的区别在于默认情况下是事务性的,并且在@Singleton
的情况下也是读/写锁定的。因此,如果您需要将随机EJB(例如@Stateless
)注入到@WebListener
或@ApplicationScoped
中,则可以将两者合并为单个@Startup @Singleton
。
/WEB-INF/web.xml
中注册<listener>
。我不知道这一点。此外,GWT可能会出现注释方法的问题,因此最好手动注册<listener>
而不是依赖注释,即使IDE没有给出错误。 - xji