java session.getServletContext() 和 session.getServletContext().getContext("/SampleProject") 的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15639673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between session.getServletContext() and session.getServletContext().getContext("/SampleProject")
提问by TechSpellBound
I have a Tomcat 6 instance running on my local machine.
我有一个 Tomcat 6 实例在我的本地机器上运行。
I have made the following changes in its configuration:
我对其配置进行了以下更改:
In /conf/
context.xml
– changed the tag as follows<Context crossContext="true">
In /conf/
server.xml
– changed the tag as follows<Connector port="8080" protocol="HTTP/1.1" emptySessionPath="true" connectionTimeout="20000" redirectPort="8443" />
在 /conf/
context.xml
– 更改标签如下<Context crossContext="true">
在 /conf/
server.xml
– 更改标签如下<Connector port="8080" protocol="HTTP/1.1" emptySessionPath="true" connectionTimeout="20000" redirectPort="8443" />
Suppose I have a WAR file named SampleProject.war
deployed here which extract to folder SampleProject
.
假设我有一个名为SampleProject.war
deploy here的 WAR 文件,它提取到文件夹SampleProject
.
In some servlet in this WAR, say SampleServlet
, I write two blocks of code as follows :
在此 WAR 中的某个 servlet 中,例如SampleServlet
,我编写了如下两个代码块:
ServletContext context1 = session.getServletContext();
and
和
ServletContext context2 = session.getServletContext().getContext("/SampleProject");
What is the difference between context1
and context2
? I thought that both refer to the application context. But if I set some attribute in context1
and access in context2
, I don't get the value in context2
.
context1
和 和有什么不一样context2
?我认为两者都指的是应用程序上下文。但如果我设置一些属性context1
和访问中context2
,我没有得到的值context2
。
Any help would be appreciated.
任何帮助,将不胜感激。
采纳答案by Ravi Thapliyal
I feel your question was slightly misunderstood and that you already had the basic understanding of the API i.e. once a web-app sets its crossContext="true"
it could use getContext()
to get access to a context that corresponds to some other web-app deployed on the server.
我觉得您的问题有点被误解了,并且您已经对 API 有了基本的了解,即一旦 Web 应用程序设置了crossContext="true"
它,它就可以getContext()
用来访问与部署在服务器上的其他 Web 应用程序相对应的上下文。
getServletContext().getContext() equals NULL unless <Context crossContext="true">
From what I've understood, your question actually is that in /SameWebApp
why
据我所知,你的问题实际上是/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)
In just one word, the answer is "Security". Imagine if you couldn't guarantee that an "adminEmail" context attribute has not been tampered with by an evilweb-app having its crossContext=true
. Your app could potentially help compromise itself as soon as that "Forgot Password" request comes! :)
一句话,答案就是“安全”。试想一下,如果你不能保证一个“ADMINEMAIL”上下文属性还没有被篡改由邪恶的web应用程序有它crossContext=true
。一旦“忘记密码”请求出现,您的应用程序可能会帮助自我妥协!:)
A Dive into Tomcat internals
深入了解 Tomcat 内部结构
Tomcat 7 provides a class ApplicationContext implements ServletContext
that returns from getContext("/context-root")
as
Tomcat 7 提供了一个class ApplicationContext implements ServletContext
从getContext("/context-root")
as返回的
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);
}
Here context
belongs to current web-app and child
represents the other web-app. But, hold on, what makes Tomcat call it a child?
这里context
属于当前的网络应用程序,child
代表另一个网络应用程序。但是,等等,是什么让 Tomcat 称它为孩子?
These two actually aren't ApplicationContext
but instances of StandardContext
a class that implements Context
but instead of servlet specific things holds Tomcat specific config settings for a web-app like crossContext, hostname, mimeMappings etc. StandardContext.getParent()
gives you the Container
and hence it has been referred to as a child above.
这两个其实都没有ApplicationContext
,但实例StandardContext
一类implements Context
的,而是servlet的具体的事情持有特定于Tomcat的配置设置像crossContext,主机名,mimeMappings等一个web应用程序StandardContext.getParent()
给你Container
,因此它被称为以上孩子.
Anyways, we're interested in the case when child == context
is true i.e. getContext()
was called on the "/SameWebApp". The call is being delegated to StandardContext.getServletContext()
which has been implemented to return a different instanceof ApplicationContext
.
无论如何,我们对在“/ SameWebApp”上调用child == context
ie 为 true的情况感兴趣。该呼叫被委托给已实施,以返回不同的实例中。getContext()
StandardContext.getServletContext()
ApplicationContext
This is why the attributes you set in context1
are not found in context2
.
这就是为什么在context1
中找不到您设置的属性的原因context2
。
But wait, there's some more to it. Why does StandardContext.getServletContext()
return like
但是等等,还有更多。为什么StandardContext.getServletContext()
返回像
return (context.getFacade());
A Tomcat instance is basically executing two types of Java code:
Tomcat 实例基本上执行两种类型的 Java 代码:
- container provided, and
- user deployed
- 提供的容器,以及
- 用户部署
The container code is "Trusted" and may need to run with elevated privileges sometimes. The user code, on the other hand, is not trusted and needs to be restricted from compromising Tomcat internals.
容器代码是“受信任的”,有时可能需要以提升的权限运行。另一方面,用户代码不受信任,需要限制其破坏 Tomcat 内部结构。
One of the things that Tomcat does to achieve this is always wrap an ApplicationContextFacade
around the ApplicationContext
(and hence the StandardContext
as well). So just to recap, what appears to be a simple ServletContext
implementation is actually a StandardContext
mapped to an ApplicationContext
which is then wrapped within an ApplicationContextFacade
.
Tomcat 为实现这一目标所做的一件事是始终ApplicationContextFacade
围绕ApplicationContext
(因此StandardContext
也是)。所以简单回顾一下,看似简单的ServletContext
实现实际上是StandardContext
映射到 anApplicationContext
然后包装在ApplicationContextFacade
.
For further information on how the ApplicationContextFacade
works using Reflection in tandem with Globals.IS_SECURITY_ENABLED
and SecurityUtil.isPackageProtectionEnabled()
settings please take a look at Why do Servlets access Tomcat ApplicationContext through a Facadeon SO.
有关如何结合ApplicationContextFacade
使用反射Globals.IS_SECURITY_ENABLED
和SecurityUtil.isPackageProtectionEnabled()
设置的更多信息,请查看为什么 Servlet 通过 Facadeon SO访问 Tomcat ApplicationContext。
References:
Tomcat 7 Source Code (Download Link)
参考资料:
Tomcat 7 源代码(下载链接)
回答by Eswar
Absolutely those two context objects are different from another.. Context1 object gives current web application servlet context obj. ( ServletContext context1 = session.getServletContext();)
这两个上下文对象绝对是不同的。Context1 对象给出了当前的 web 应用程序 servlet 上下文对象。( ServletContext context1 = session.getServletContext();)
and
和
context2 object gives the servletcontext obj of specified web application (ServletContext context2 = session.getServletContext().getContext("/SampleProject");)
context2 对象给出指定 Web 应用程序的 servletcontext 对象 (ServletContext context2 = session.getServletContext().getContext("/SampleProject");)
you are setting object in one context and trying to retrieve using another context, so it is not possible to get attribute from another web application context by putting it in current application context. But you can get attribute resides in another web application context by using second method.
您正在一个上下文中设置对象并尝试使用另一个上下文进行检索,因此无法通过将其放入当前应用程序上下文来从另一个 Web 应用程序上下文中获取属性。但是您可以使用第二种方法获取驻留在另一个 Web 应用程序上下文中的属性。
回答by Glen Best
Think OO & java EE platform standards + security.
考虑 OO 和 Java EE 平台标准 + 安全性。
The first call returns the definitiveservlet context for the current app, with all operations supported.
第一次调用返回当前应用程序的最终servlet 上下文,支持所有操作。
The second call returns a copyof the servlet context that could be for any app. As stated (rather vaguely!) in the javadoc, it's purpose is to allow you to obtain a RequestDispatcher
, so you can dispatch to pages of other apps. It's other major but implicit requirement is to do this securely and to respect the Java EE specs, which do not allow sharing of session state or servlet context between apps. Imagine the terrible damage "rogue App B" could do to "good App A" if it could just change (or read) Servlet Context data by brute force. That's why it's a copy.
第二个调用返回可以用于任何应用程序的 servlet 上下文的副本。正如 javadoc 中所述(相当含糊!),它的目的是让您获得RequestDispatcher
,以便您可以分派到其他应用程序的页面。另一个主要但隐含的要求是安全地执行此操作并遵守 Java EE 规范,该规范不允许在应用程序之间共享会话状态或 servlet 上下文。想象一下,如果“流氓应用程序 B”可以通过蛮力更改(或读取)Servlet 上下文数据,它会对“好的应用程序 A”造成可怕的损害。这就是为什么它是一个副本。
Hence, setting attributes on the copy, does not result in changes to the original. You could argue that the copy should throw some "Operation Not Supported Exception". Alternatively, you could argue that getRequestDispatcher should be refactored either to another class, or to allow an App Context URL to be passed in. ... But, unfortunately, neither of these things are true. B^)
因此,在副本上设置属性不会导致对原件的更改。您可能会争辩说该副本应该抛出一些“不支持的操作异常”。或者,您可能会争辩说,应该将 getRequestDispatcher 重构为另一个类,或者允许传入 App Context URL。...但是,不幸的是,这些都不是真的。乙^)