session.getServletContext()和session.getServletContext()之间的区别.getContext(“/ SampleProject”)

时间:2013-03-26 14:32:40

标签: java tomcat servlets

我在本地计算机上运行了一个Tomcat 6实例。

我在配置中做了以下更改:

  • 在/ conf / context.xml中 - 更改了标记如下

    <Context crossContext="true">
    
  • 在/ conf / server.xml中 - 更改了标记如下

    <Connector port="8080" protocol="HTTP/1.1" emptySessionPath="true"
           connectionTimeout="20000" 
           redirectPort="8443" />
    

假设我在此部署了一个名为SampleProject.war的WAR文件,该文件将解压缩到文件夹SampleProject

在这个WAR中的一些servlet中,比如SampleServlet,我写了两段代码,如下所示:

ServletContext context1 = session.getServletContext();

ServletContext context2 = session.getServletContext().getContext("/SampleProject");

context1context2之间有什么区别?我认为两者都是指应用程序上下文。但是,如果我在context1中设置了一些属性并在context2中进行了访问,则我无法获得context2中的值。

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:5)

我觉得您的问题有点被误解,并且您已经对API有了基本的了解,即一旦网络应用设置了crossContext="true",它就可以使用getContext()来访问对应的上下文到服务器上部署的其他网络应用程序。

getServletContext().getContext() equals NULL unless <Context crossContext="true">

根据我的理解,您的问题实际上是/SameWebApp为什么

ServletContext context1 = session.getServletContext();
context1.setAttribute("contextAttribute", new Object());
ServletContext context2 = session.getServletContext().getContext("/SameWebApp");

System.out.println(context1.equals(context2)); // prints false, or 
System.out.println(context2.getAttribute("contextAttribute")); // prints null (at least they could have been clones)

简而言之,答案是&#34;安全&#34;。想象一下,如果你不能保证&#34; adminEmail&#34;上下文属性未被具有crossContext=true evil 网络应用程序篡改。你的应用程序可能会帮助自己妥协,并且#34;忘记密码&#34;请求来了! :)

潜入Tomcat内部

Tomcat 7提供class ApplicationContext implements ServletContext,从getContext("/context-root")返回

    if (context.getCrossContext()) {
        // If crossContext is enabled, can always return the context
        return child.getServletContext();
    } else if (child == context) {
        // Can still return the current context
        return context.getServletContext();
    } else {
        // Nothing to return
        return (null);
    }

此处context属于当前的网络应用,child代表其他网络应用。但是,坚持一下,是什么让Tomcat称之为小孩?

这两个实际上并不是ApplicationContext但是StandardContext的实例implements Context但是而不是servlet特定的东西为像crosscontext这样的web应用程序保存了Tomcat特定的配置设置,hostname,mimeMappings等StandardContext.getParent()为您提供Container,因此它被称为上面的孩子。

无论如何,我们对child == context为真的情况感兴趣,即在{34> / SameWebApp 上调用getContext() &#34 ;.该致电被委托给StandardContext.getServletContext(),该ApplicationContext已被实施以返回context1不同实例

这就是context2中找不到您在StandardContext.getServletContext()中设置的属性的原因。

但是等等,还有更多的东西。为什么return (context.getFacade()); 会像

一样返回
ApplicationContextFacade

Tomcat实例基本上是执行两种类型的Java代码:

    提供
  • 容器,
  • 用户已部署

容器代码是&#34;信任&#34;并且有时可能需要以提升的权限运行。另一方面,用户代码不受信任,需要限制其破坏Tomcat内部。

Tomcat实现此目的的一个方面是始终在ApplicationContext周围包裹StandardContext(因此也ServletContext)。所以回顾一下,看似简单的StandardContext实现实际上是映射到ApplicationContext的{​​{1}},然后将其包含在ApplicationContextFacade内。

有关ApplicationContextFacade如何使用反射与Globals.IS_SECURITY_ENABLEDSecurityUtil.isPackageProtectionEnabled()设置配合使用的更多信息,请参阅SO上的Why do Servlets access Tomcat ApplicationContext through a Facade

参考文献:
Tomcat 7 Source Code (Download Link)

答案 1 :(得分:3)

这两个上下文对象绝对不同于另一个。 Context1对象提供当前Web应用程序servlet上下文obj。 (ServletContext context1 = session.getServletContext();)

context2对象给出了指定Web应用程序的servletcontext obj (ServletContext context2 = session.getServletContext()。getContext(“/ SampleProject”);)

您在一个上下文中设置对象并尝试使用另一个上下文进行检索,因此无法通过将其置于当前应用程序上下文中来从另一个Web应用程序上下文中获取属性。但是您可以使用第二种方法将属性驻留在另一个Web应用程序上下文中。

答案 2 :(得分:3)

想想OO&amp; java EE平台标准+安全性。

第一个调用返回当前应用程序的权威 servlet上下文,并支持所有操作。

第二个调用返回可能适用于任何应用程序的servlet上下文的副本。正如在javadoc中所说的那样(相当含糊!),它的目的是让你获得RequestDispatcher,这样你就可以发送到其他应用程序的页面。这是另一个主要但隐含的要求是安全地执行此操作并遵守Java EE规范,这些规范不允许在应用程序之间共享会话状态或servlet上下文。想象一下,如果可以通过蛮力改变(或读取)Servlet上下文数据,那么“流氓App B”可能对“好应用程序A”造成的可怕损害。这就是为什么它是副本。

因此,在副本上设置属性不会导致对原始文件的更改。你可能会争辩说副本应该抛出一些“操作不支持异常”。或者,您可以认为getRequestDispatcher应该重构为另一个类,或者允许传入App Context URL。但是,遗憾的是,这些都不是真的。乙^)