我们正在使用:
我们有mainForm.jsp,filterForm.jsp和externalForm.jsp意见。
mainForm.jsp
filterForm.jsp
externalForm.jsp
上有一个按钮“过滤器”,mainForm.jsp可转换为filterForm.jsp。它通过导航规则来做到这一点:
<h:commandButton value="Filter" action="#{mainBean.filterData}" />
该mainBean.java代码是:
mainBean.java
public String filterData() { doStuff(); return "filter"; }
最初可以正确转换为filterForm.jsp。我们可以mainForm.jsp使用浏览器后退按钮返回。我们可以重复执行此操作。
上面mainForm.jsp有一个表格(实际上是ILog Gantt图表,但我们认为没有关系),图表栏上带有“弹出”菜单。菜单选项之一是重定向到externalForm.jsp。
选择“重定向”会触发以下方法mainBean.java:
public void redirect(FacesMenuActionEvent event) { if (svr == null) { svr = new SetupURL(); // Simple code to set up the full URL } redirectUrl = svr.redirect(event); // URL of externalForm.jsp svr.redirectData(redirectUrl); }
这可以正常工作。窗口切换到externalForm.jsp。
如果我们按下上的浏览器后退按钮externalForm.jsp,我们将切换回mainForm.jsp,一切看起来都很好。
如果再按“过滤器”按钮,则代码不执行该filterData()方法,而是执行该redirect()方法,然后过渡到externalForm.jsp视图,而不是filterForm.jsp视图。
filterData()
redirect()
为什么这样做,我们如何强制呼叫filterData()呢?
****************************************************************************** BalusC - thank you for your solution. With a few slight tweeks, it worked great. The changes I made to web.xml are: <filter> <filter-name>noCacheFilter</filter-name> <filter-class>{my package name}.CacheControlFilter</filter-class> </filter> <filter-mapping> <filter-name>noCacheFilter</filter-name> <url-pattern>/faces/*</url-pattern> </filter-mapping> Also, I found another solution: faces-config.xml add: <lifecycle> <phase-listener id="nocache">{my package name}. CacheControlPhaseListener</phase-listener> </lifecycle> Create file CacheControlPhaseListener.java: package {my package name}; import javax.faces.context.FacesContext; import javax.faces.event.PhaseEvent; import javax.faces.event.PhaseId; import javax.faces.event.PhaseListener; import javax.servlet.http.HttpServletResponse; public class CacheControlPhaseListener implements PhaseListener { public PhaseId getPhaseId() { return PhaseId.RENDER_RESPONSE; } public void afterPhase(PhaseEvent event) { } public void beforePhase(PhaseEvent event) { FacesContext facesContext = event.getFacesContext(); HttpServletResponse response = (HttpServletResponse) facesContext .getExternalContext().getResponse(); response.addHeader("Pragma", "no-cache"); response.addHeader("Cache-Control", "no-cache"); // Stronger according to blog comment below that references HTTP spec response.addHeader("Cache-Control", "no-store"); response.addHeader("Cache-Control", "must-revalidate"); // some date in the past response.addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT"); } } Both seem to work. Thanks, John
浏览器后退按钮从浏览器缓存中请求结果页面。它不要求服务器重新创建新页面。在您的特定情况下,很可能缓存的页面包含当前无效的JSF视图状态。
最好的解决方法是指示浏览器不要缓存动态JSF页面,而是每次都直接从服务器请求它。您可以在的帮助下执行Filter此操作,该doFilter()方法在方法中包含以下几行:
Filter
doFilter()
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { HttpServletResponse res = (HttpServletResponse) response; 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); }
将此映射<servlet-name>到FacesServlet中的web.xml。例如
<servlet-name>
FacesServlet
web.xml
<filter> <filter-name>noCacheFilter</filter-name> <filter-class>com.example.NoCacheFilter</filter-class> </filter> <filter-mapping> <filter-name>noCacheFilter</filter-name> <servlet-name>facesServlet</servlet-name> </filter-mapping>