问题是什么:
单击浏览器的后退按钮->打开一个页面,该页面的viewscoped-managedbean已被破坏->从带有网格记录选择的页面的commandButton提交请求,该怎么办?

我期望什么:
关联的viewscope-managebean被重新创建,接收到网格记录选择,并像处理浏览器的后退按钮一样处理它们。

我的经验:
关联的viewscope-managebean未重新创建,未收到网格记录选择。单击浏览器后退按钮后,必须重新输入URL或F5才能再次正常工作。

所以这是成功的场景,所有的bean都是viewscoped bean:


在@PostConstruct中获取page1.xhtml-> page1Bean创建,查询数据等
从数据表中检查/选择几条记录,单击处理按钮
page1Bean的处理方法将选定的记录存储在flash对象中,然后重定向到page2.xhtml
page1Bean已销毁,page2Bean已创建,并在preRenderView侦听器方法中,从flash对象获取所选记录,并对其进行处理
单击“转到主页”命令按钮以重定向到page1.xhtml,并销毁page2Bean,再次创建page1Bean
从2到5的循环仍然可行


现在,这是一个错误的场景,涉及浏览器的后退按钮(从#6开始发生了各种各样的事情):


在@PostConstruct中获取page1.xhtml-> page1Bean创建,查询数据等
从数据表中检查/选择几条记录,单击处理按钮
page1Bean的处理方法将选定的记录存储在flash对象中,然后重定向到page2.xhtml
page1Bean已销毁,page2Bean已创建,并在preRenderView侦听器方法中,从flash对象获取所选记录,并对其进行处理
单击浏览器的后退按钮page2Bean未销毁,page1Bean未创建
从数据表中检查/选择几条记录,单击处理按钮
page1Bean方法执行(很奇怪,因为page1Bean应该已经被销毁),但是看不到所做的记录选择,并重定向到page2.xhtml
page1Bean没有被销毁(没有日志输出),page2Bean没有被创建(因为它没有被销毁),像往常一样执行了preRenderView侦听器,但是这次在flash对象中没有选定的记录


使用带浏览器后退按钮的viewscope-beans是否有可能具有正常的体验(就像没有浏览器后退按钮一样)?

这是我的依赖:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.faces</artifactId>
    <version>2.1.3</version>
    <scope>compile</scope>
</dependency>


请分享您的想法!

最佳答案

当您将JSF状态保存方法设置为server(这是默认设置)时,浏览器似乎已经从其缓存中提供了该页面,而不是向服务器发送了完整的HTTP GET请求。

有两种方法可以解决此问题:


告诉浏览器不要缓存动态JSF页面。您可以在filter的帮助下完成此操作。

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
        res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        res.setDateHeader("Expires", 0); // Proxies.
    }

    chain.doFilter(request, response);
}


将过滤器映射到FacesServlet或其相同的URL模式。
将JSF状态保存方法设置为client,以便将整个视图状态存储在表单的隐藏字段中,而不是存储在服务器端的会话中。

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>



过滤方式是优选的。

07-24 21:30