问题是什么:
单击浏览器的后退按钮->打开一个页面,该页面的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>
过滤方式是优选的。