我在本地计算机上运行了一个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");
context1
和context2
之间有什么区别?我认为两者都是指应用程序上下文。但是,如果我在context1
中设置了一些属性并在context2
中进行了访问,则我无法获得context2
中的值。
任何帮助都将不胜感激。
答案 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 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_ENABLED
和SecurityUtil.isPackageProtectionEnabled()
设置配合使用的更多信息,请参阅SO上的Why do Servlets access Tomcat ApplicationContext through a Facade。
答案 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。但是,遗憾的是,这些都不是真的。乙^)