我对面部导航有疑问。
所以我有一个页面,它接受一个请求参数来加载特定用户。此页面显示commandLink列表,单击该列表时,使用隐式导航重定向到另一个页面。通过调用“preRenderView”中的方法来加载用户。
我们重定向到的页面还会获取一个请求参数来确定要加载的大小写。该页面还使用了preRenderView。
两个页面都有视图作用域的bean。
对于按下的FIRST链接,这一切都很棒。第一页重定向到新URL,案例按预期加载。
但是,如果我单击浏览器的后退按钮,然后单击另一个链接,则页面不会重定向。它刷新(相反),显然不会购买案例。
刷新后,我可以点击链接,它会正确重定向。
现在,当第一页的bean保留在会话中时,所有这一切都完全正常但我不想滥用会话状态,我认为不应该将这些数据保留在会话。
我知道我可以通过在单击后退按钮时自动重新加载页面来修复此问题(因为视图将被重新创建),但我不确定这是否也是正确的解决方案。 (我也不确定如何强制这样做)
有没有人有任何建议?这似乎是一个相当常见的用例,但我真的找不到任何例子。
谢谢!
答案 0 :(得分:12)
基本上,您需要告诉浏览器在将视图状态保存方法设置为(默认)server
时不缓存动态生成的JSF页面。视图状态由生成的JSF页面形式的<input type="hidden" name="javax.faces.ViewState">
字段跟踪,视图状态标识符作为输入值。当您提交页面并导航到其他页面时,视图状态将在服务器端被删除,并且不再存在。从浏览器缓存中恢复页面仍然会将旧视图状态标识符作为隐藏输入的值。提交该表单根本不起作用,因为找不到服务器端的视图状态。
您希望直接从服务器而不是浏览器缓存中获取新的新页面。为了告诉浏览器这样做,请创建一个Filter
,如下所示:
@WebFilter(servletNames={"Faces Servlet"})
public class NoCacheFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpRes = (HttpServletResponse) response;
if (!httpReq.getRequestURI().startsWith(httpReq.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
httpRes.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
httpRes.setHeader("Pragma", "no-cache"); // HTTP 1.0.
httpRes.setDateHeader("Expires", 0); // Proxies.
}
chain.doFilter(request, response);
}
// ...
}
这样,后退按钮将发送一个完整的HTTP请求,该请求应该重新创建视图状态并导致页面的表单具有正确的视图状态隐藏字段值。