【问题标题】:Page scope in jspjsp中的页面范围
【发布时间】:2018-03-17 07:05:17
【问题描述】:

我了解页面范围是 jsp 中的默认范围(与请求/会话/应用程序范围相比特权最低),并且只能在同一个 jsp 页面中访问对象。

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

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

【问题讨论】:

    标签: jsp pagecontext


    【解决方案1】:

    通过查看 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 以供潜在的重用”。因此,当使用池化实例时,每个线程总是会得到一个“干净”的实例。

    【讨论】:

      猜你喜欢
      • 2014-05-11
      • 1970-01-01
      • 2010-10-18
      • 2018-03-13
      • 1970-01-01
      • 1970-01-01
      • 2013-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多