我理解页面范围是jsp中的默认范围(与请求/会话/应用程序范围相比最低特权),并且只能在同一个jsp页面中访问对象。
我想知道访问同一个jsp页面的两个用户是否有可能共享在页面范围内设置的对象值?我非常认为答案是否定的,但仍想确认一次。
在其他方面,PageContext是否在两个用户之间共享?如果我使用pageContext.setAttribute(....)将对象设置为页面范围,那么这个对象是否会在两个不同的用户之间共享?
答案 0 :(得分:2)
通过查看JSP页面实现类如何使用代表所述范围的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时,将调用其页面实现类的_jspService
方法,将它们作为参数。之后,该方法获取PageContext
对象并将其存储为方法的局部变量。
本地变量是线程内存(不共享),因此,任何其他线程都无法为另一个用户(甚至来自同一用户)的请求提供对该变量的访问权限。一旦_jspService
返回,变量就会停止存在。如果另一个线程同时调用_jspService()
,则工厂会为其提供不同的PageContext
实例。
这导致了一个问题,即从工厂获得的PageContext
对象是始终是新实例还是正在重用的实例。这取决于实现,如this question的答案中所述。在后一种情况下,容器应该确保它永远不会将同一个实例同时移动到两个不同的线程 (否则会出现并发问题)。
请注意,在返回之前,_jspService()
通过调用releasePageContext()来确保PageContext
对象被“清除”任何状态(请参阅javadoc示例中的finally
块)。这反过来调用PageContext
上的release(),其效果是“释放所有内部引用,并为可能的重用准备PageContext”。因此,当使用池化实例时,每个线程总是得到一个“干净”的实例。