jsp 中的页面范围

Page scope in jsp

我知道页面范围是 jsp 中的默认范围(与 request/session/application 范围相比特权最低)并且对象只能在同一 jsp 页面中访问。

我想知道访问同一个 jsp 页面的两个用户是否有可能共享在页面范围内设置的对象值?我强烈认为答案是否定的,但还是想确认一次。

换句话说,PageContext 是否在两个用户之间共享?如果我使用 pageContext.setAttribute(....) 将一个对象设置为页面范围,这个对象是否会在两个不同的用户之间共享?

通过查看 JSP 页面实现 classes 如何使用表示所述范围的 PageContext 对象,您可以更好地了解页面范围的工作原理。

在包 javax.servlet.jsp 的 javadoc 中有一个如何完成此操作的示例。有趣的部分是:

public void _jspService(HttpServletRequest request,
                        HttpServletResponse response)
                        throws IOException, ServletException {

    JspFactory  factory     = JspFactory.getDefaultFactory();
    PageContext pageContext = factory.getPageContext( ... )

    ...
}

如您所见,当您的 servlet 将其请求和响应对象转发给 JSP 时,将调用其页面实现 class 的 _jspService 方法,将它们作为参数.紧接着,该方法获得一个PageContext对象并将其存储为该方法的局部变量

局部变量是线程内存(非共享),因此,服务于另一个用户(甚至不是同一用户)的请求的任何其他线程都无法访问该变量。一旦 _jspService returns,变量就不再存在了。如果另一个线程并发调用_jspService(),工厂给它一个不同的PageContext实例。

这就引出了一个问题,从工厂获取的PageContext对象到底是一直是新实例还是被复用。这取决于实现,如 this question 的答案中所述。在后一种情况下,容器应确保它永远不会将同一实例同时交给两个不同的线程(否则会出现并发问题)。

请注意,在返回之前,_jspService() 通过调用 releasePageContext() 确保 PageContext 对象处于任何状态的 "cleansed"(请参阅javadoc 示例)。这又会在 PageContext 上调用 release(),产生 "releasing all internal references, and preparing the PageContext for potential reuse" 的效果。因此,当使用池化实例时,每个线程总是得到一个 "clean"。