【问题标题】:Static Servlet Context variable静态 Servlet 上下文变量
【发布时间】:2012-04-10 09:19:37
【问题描述】:

我从问题How to gain access to a ServletContext instance from any method? 中读到,如果我想从我的Java Web 项目中的任何类访问Servlet 上下文,我可以声明一个静态字段,该字段指向ServletContextListener 中的ServletContext,但是一个静态字段字段在 Java Web 应用程序中是一种不好的做法,因为在关闭 JVM 之前 GC 无法收集它(如果我在这一点上错了,请纠正我)。是否有另一种方法来访问 ServletContext 而不使用侦听器或将其作为参数接收?还有另一种解决方法可以解决这个问题吗?我正在为 Web 应用程序使用 JSF 1.2 和 JBoss 5.1 GA。

注意:我知道我可以使用

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

要访问ServletContext,但是有一个在启动时运行的方法需要访问ServletContext并且FacesContext.getCurrentInstance()还没有被初始化。

更新:

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

【问题讨论】:

  • 您究竟在哪里需要它,为什么?为什么你不只是在ServletContextListener 本身做这项工作?顺便说一下,FacesContext 仅在其 URL 与 FacesServlet 的 URL 模式匹配并因此调用它的每个 HTTP 请求上初始化。
  • @BalusC 有一个常量字符串,它使用 web.xml 中的上下文参数以静态方法加载。为此,它需要ServletContext#getInitParameter。实际的解决方法是创建一个 Singleton 类,该类将这些值加载到实现 ServletContextListener 的类中,但会产生内存问题,因此我们需要创建该类的实例并将其作为属性加载到 ServletContext 中,但随后我无法在静态方法中访问。
  • “创建一个 Singleton 类,将这些值加载到实现 ServletContextListener 的类中” 我无法想象这有什么意义。功能需求是什么?您是否需要它以 public static 变量结尾?为什么?
  • @BalusC 我已将要求添加到问题中
  • @LuiggiMendoza 您的断言but a static field is a bad practice in Java web applications because the GC can't collect it until the JVM is turned off 不正确。 JVM GC 将收集不再有引用或位于孤岛 上的所有对象。有关详细信息,请参阅stackoverflow.com/a/5667747/650425。如果您从静态变量中删除对象引用并且它不再被任何其他变量引用,那么它就有资格进行垃圾回收。我认为您所指的是在JVM终止之前不会收集Class对象本身。

标签: java jsf web-applications jsf-1.2 servlet-listeners


【解决方案1】:

我不知道你为什么需要一个单例。 Just create one 存储在应用程序范围内的 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);
}

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

【讨论】:

  • Singleton 用于缓存实现(是的,我们不知道 ehcache 或其他框架)但这是一个糟糕的解决方案,所以我的老板不想添加这个框架,而是想用我们编写的课程。顺便说一句,您的解决方案看起来很有趣,但我怎样才能在 HTTP 请求中未调用的方法中访问 context
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-25
  • 1970-01-01
  • 2019-03-17
  • 2011-11-30
相关资源
最近更新 更多