【问题标题】:How to get the context without any request, session, etc?如何在没有任何请求、会话等的情况下获取上下文?
【发布时间】:2014-10-31 08:54:48
【问题描述】:

我在一个类中有一个方法,它没有得到任何可用于获取实际 servlet 上下文的东西。实际上,它就像

public String getSomething() { ... }

但要计算结果,我需要实际的、特定于线程的 servlet 结构。

我认为,在应用程序上下文的深处,应该存在一些像线程特定的存储,可以通过调用某些系统类的静态方法来实现。

我在一个 tomcat6 servlet 容器中,但如果需要,也可以使用 Spring。

【问题讨论】:

    标签: java spring tomcat servlets


    【解决方案1】:

    ServletContextListener 添加到您的web.xml。这将在您的 web 应用程序加载时调用。在contextInitialized() 方法中,您可以将ServletContext 存储在静态变量中,以供以后使用。然后您将能够以静态方式访问ServletContext

    class MyListener implements ServletContextListener {
    
        public static ServletContext context;
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            context = sce.getServletContext();
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            context = null;
        }
    
    }
    

    像这样将它添加到web-xml

    <web-app>
        <listener>
            <listener-class>
                com.something.MyListener
            </listener-class>
        </listener>
    </web-app>
    

    你可以像这样从任何地方访问它:

    public String getSomething() {
        // Here you have the context:
        ServletContext c = MyListener.context;
    }
    

    注意:

    您可能希望将其存储为private 并提供getter 方法,并在使用前检查null 值。

    【讨论】:

      【解决方案2】:

      如果你没有指向有用的东西的指针,我知道的唯一方法是在包含当前 ServletContext 的类中拥有一个静态属性。 ServletContextListener 是微不足道的:

      @WebListener
      public class ServletContextHolder implements ServletContextListener {
          private static ServletContext servletContext;
      
          public static ServletContext getServletContext() {
              return servletContext;
          }
      
          @Override
          public void contextInitialized(ServletContextEvent sce) {
              servletContext = sce.getServletContext();
          }
      
          @Override
          public void contextDestroyed(ServletContextEvent sce) {
              servletContext = null;
          }    
      }
      

      然后从您使用的任何地方

      ServletContextHolder.getServletContext();
      

      如果您使用 Spring,您还可以使用 RequestContextHolder 来获取当前请求的访问权限(从那里访问您需要的任何内容)

      HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                                       .getRequestAttributes()).getRequest();
      

      当然,如果在 servlet 应用程序中而不是在 portlet 应用程序中以这种方式工作 - 你将不得不使用 PortletRequestAttributes 并最终获得一个 PortletRequest

      【讨论】:

        【解决方案3】:

        一个明显的解决方案是将上下文作为参数传递,因为您显然是在上下文通常可用的地方运行代码。

        如果出于某种原因您觉得这不是您可以做的事情(我想听听原因),另一种方法是创建一个 servlet 过滤器,然后创建一个 ThreadLocal&lt;ServletContext&gt;

        【讨论】:

        • 真的需要ThreadLocal 吗? AFAIK,ServletContext 每个虚拟机只定义一次
        • @epoch 也许不同的web应用有不同的ServletContext?
        • 非常感谢 - 最后我做了你的第一个想法:我在一个新的 setter 中将 servletContext 提供给了 bean。也许这不是最完美的解决方案,但肯定是最简单且最独立于平台的解决方案。
        • @Kayaman:当您在不同的 API/库项目中有一些公共代码,并且您在该库中有多态构造函数时,这是必需的。
        【解决方案4】:

        您可以自动装配 servlet 上下文,如下所示

        @Autowired
        ServletContext servletContext;
        

        【讨论】:

          猜你喜欢
          • 2017-04-05
          • 1970-01-01
          • 2011-05-15
          • 2014-08-06
          • 2013-05-19
          • 2015-11-08
          • 2018-09-04
          • 1970-01-01
          • 2011-02-15
          相关资源
          最近更新 更多