浏览器返回+观察范围豆
问题是什么: 单击浏览器后退按钮时会发生什么 -->打开一个 viewscoped-managementbean 已被销毁的页面 -->使用 grid-record-selections 从该页面的 commandButton 提交请求?
我的期望: 关联的 viewscope-managebean 被重新创建,接收 grid-record-selections,并处理它们,就像从不涉及浏览器后退按钮一样。
我的经历: 关联的 viewscope-managebean 不会重新创建,也不会接收网格记录选择。必须重新输入 URL,或者单击浏览器后退按钮后按 F5,才能再次正常工作。
所以这是成功场景,所有bean都是viewscoped beans:
- GET page1.xhtml -->在@PostConstruct中创建page1Bean,查询数据等,
- 从数据表中检查/选择几条记录,单击处理按钮
- page1Bean的处理方法将所选记录存储在flash对象中,并重定向到page2.xhtml
- page1Bean被销毁,page2Bean被创建,并在preRenderView监听方法,从flash对象中获取选中的记录,并处理它们
- 点击“转到主页面”命令按钮重定向到page1.xhtml,并销毁page2Bean,创建page1Bean 从 2 到 5 的再次
- 循环仍然可行
现在,这是涉及浏览器后退按钮的错误场景(从 #6 开始发生不同的事情):
- GET page1.xhtml -->在@PostConstruct中创建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>
请分享您的想法!
What the problem is :
What happens when clicking on the browser back button --> opens up a page whose viewscoped-managedbean is already destroyed --> submit a request from a commandButton from that page with grid-record-selections ?
What i expect :
The associated viewscope-managebean is re-created, receives the grid-record-selections, and deal with them as if the browser back button is never involved.
What i experience :
The associated viewscope-managebean is NOT re-created, doesnt receive the grid-record-selections. Have to reenter the URL, or F5 after clicking on the browser-back button for it to work properly again.
So here's the success scenario, all beans are viewscoped beans :
- GET page1.xhtml --> page1Bean created, querying data, etc in @PostConstruct
- check/select several records from a datatable, click on process button
- page1Bean's process method stores the selected records in the flash object, and redirect to the page2.xhtml
- page1Bean destroyed, page2Bean created, and in preRenderView listener method, fetches the selected records from the flash object, and deal with them
- click the "go to main page" commandButton to redirect to page1.xhtml, and page2Bean destroyed, page1Bean created again
- loop from no 2 - 5 is still doable
Now, this is the errornous scenario involving the browser back button (different stuffs happening starting from #6) :
- GET page1.xhtml --> page1Bean created, querying data, etc in @PostConstruct
- check/select several records from a datatable, click on process button
- page1Bean's process method stores the selected records in the flash object, and redirect to the page2.xhtml
- page1Bean destroyed, page2Bean created, and in preRenderView listener method, fetches the selected records from the flash object, and deal with them
- click the browser back button page2Bean is not destroyed, page1Bean is not created
- check/select several records from a datatable, click on process button
- the page1Bean method executes (strange, because the page1Bean should've been destroyed), but cannot see the record-selections made, and redirect to page2.xhtml
- page1Bean is not destroyed (no logging output), page2Bean is not created (since it's not been destroyed), executes the preRenderView listener as usual, but this time, no selected records in the flash object
Is it possible to have the normal experience (as if without the browser back button) with viewscope-beans with the browser back button ?
Here's my dependency :
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.faces</artifactId>
<version>2.1.3</version>
<scope>compile</scope>
</dependency>
Please share your ideas !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当您将 JSF 状态保存方法设置为
server
(这是默认值)时,浏览器似乎从其缓存中提供页面服务,而不是向服务器发送完整的 HTTP GET 请求。有两种方法可以解决此问题:
告诉浏览器不要缓存动态 JSF 页面。您可以在过滤器的帮助下完成此操作。
<前><代码>@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) 请求;
HttpServletResponse res = (HttpServletResponse) 响应;
if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // 跳过 JSF 资源(CSS/JS/Images/etc)
res.setHeader("Cache-Control", "无缓存,无存储,必须重新验证"); // HTTP 1.1。
res.setHeader("Pragma", "无缓存"); // HTTP 1.0。
res.setDateHeader("过期", 0); // 代理。
}
chain.doFilter(请求,响应);
}
将过滤器映射到
FacesServlet
或其相同的URL 模式上。将JSF状态保存方式设置为客户端,使整个视图状态存储在表单的隐藏字段中,而不是存储在服务器端的会话中。
优选过滤方式。
The browser seems to have served the page from its cache instead of sending a fullworthy HTTP GET request to the server, while you have JSF state saving method set to
server
(which is the default).There are 2 ways to solve this problem:
Tell the browser to not cache the dynamic JSF pages. You can do this with help of a filter.
Map the filter on the
FacesServlet
or its same URL-pattern.Set the JSF state saving method to client, so that the entire view state is stored in a hidden field of the form instead of in the session in the server side.
The filter way is preferable.
禁用页面的浏览器缓存的缺点是,如果用户使用浏览器后退导航到上一页,他将看到浏览器错误页面。
因此,另一个解决方案是使用 javascript 来识别页面是来自服务器还是来自浏览器缓存:
首先创建一个简单的支持 bean,它提供唯一的 id(在我的例子中是当前系统时间):
所以现在您可以测试页面是否是从服务器或浏览器提供服务,如果当前页面来自浏览器缓存,则重定向用户。请参阅以下放置在不应被浏览器缓存的 jsf 页面中的 javascript 代码:
该脚本也可以放置在 Facelet 中以使 jsf 代码更加简洁。
The disadvantage of disabling the browser cache of a page is that the user will see an browsers error page if he use browser back to navigate to previous page.
So another solutions is to identify if the page comes from the server or from the browser cache using javascript:
First create a simple backing bean which serves a unique id (in my case current system time):
So now you can test if a page is served from the server or browser and redirecting the user if the current page comes from browser cache. See the following javascript code placed into a jsf page which should not be cached by browser:
The script can also be placed into facelet to make the jsf code more clean.