静态Servlet上下文变量

3
我看到一个问题,链接如下:如何从任何方法中访问ServletContext实例?。该问题解释了如果我想在Java Web项目中的任何类中访问ServletContext,我可以声明一个指向ServletContextListener中ServletContext的静态字段,但是在Java Web应用程序中使用静态字段是一种不好的实践,因为GC只有在JVM关闭时才会收集它(如果我在这一点上错了,请纠正我)。是否有另一种方法来访问ServletContext而不使用监听器或将其作为参数接收?还有其他解决此问题的方法吗? 我正在使用JSF 1.2和JBoss 5.1 GA进行Web应用程序开发。

注意:我知道可以使用

(ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext();

访问ServletContext需要一个在启动时运行的方法来访问ServletContext,但是FacesContext.getCurrentInstance()尚未初始化。

更新:

我们需要在Web应用程序启动时从web.xml中加载一些IP到String常量中。为此,我们创建了一个Singleton类,将context-params加载到变量中,然后使用Singleton类的某些值填充String常量。这个Singleton类管理大量数据,并出现了内存不足异常错误。为了解决这个问题,我们正在修改Singleton类,将其作为ServerContext属性加载为简单类,但由于这个(不再是)Singleton的实例的缺失,无法加载String常量。


你需要它的确切位置和原因是什么?为什么不直接在 ServletContextListener 中完成任务呢?顺便说一下,FacesContext 仅在每个 URL 与 FacesServlet 的 URL 模式匹配并因此调用它的每个单独 HTTP 请求上初始化。 - BalusC
@BalusC 在web.xml中使用context-param加载的静态方法中有一个常量字符串。为了实现这一点,需要使用ServletContext#getInitParameter。目前的解决方法是创建一个单例类,在实现ServletContextListener接口的类中加载这些值,但是这会导致内存问题,所以我们需要在ServletContext中创建该类的实例并将其作为属性加载,但是在静态方法中无法访问它。 - Luiggi Mendoza
“创建一个Singleton类,该类在实现ServletContextListener的类中加载这些值”,我无法想象它是如何有意义的。功能需求是什么?您需要将其最终放入public static变量中吗?为什么? - BalusC
@BalusC 我已经在问题中添加了这个要求。 - Luiggi Mendoza
@downvoter 至少解释一下你的理由... - Luiggi Mendoza
显示剩余3条评论
1个回答

2

我不确定你为什么需要一个单例模式。只需创建一个 bean 并将其存储在应用程序范围内即可。

@Override
public void contextInitialized(ServletContextEvent event) {
    ServletContext context = event.getServletContext();
    Set<String> ips = parseContextParamSomehow(context.getInitParam("ips"));
    Manager manager = new Manager();
    manager.setIps(ips);
    context.setAttribute("manager", manager);
}

它将在EL上下文中由#{manager}提供。也可以作为任意JSF托管bean的托管属性。另一种选择是创建一个应用程序范围的JSF托管bean,并在其构造函数中完成工作,但这会将其构造延迟到涉及该bean的第一个HTTP请求。


单例模式用于缓存实现(是的,我们不知道ehcache或其他框架),但那是一个糟糕的解决方案,所以,与其添加这个框架,我的老板想用我们已经编写的类来解决这个问题。顺便说一下,你的解决方案看起来很有趣,但是在没有HTTP请求调用的方法中如何访问上下文? - Luiggi Mendoza

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接