> JSF 1.2-1.2_07-b03-FCS
> JSTL 1_1-mr2(特别版)
> Java 1.6.0_22-b04
> Eclipse 3.6.0(Helios)
> Tomcat 6.0.28(需要在Weblogic上运行)
> IE 7.0.5730.13
> Firefox:6.0
我们有mainForm.jsp,filterForm.jsp和externalForm.jsp视图.
mainForm.jsp上有一个“过滤器”按钮,可以转换为filterForm.jsp.它通过导航规则执行此操作:
<h:commandButton value="Filter" action="#{mainBean.filterData}" /> 
 mainBean.java代码是:
public String filterData() {
    doStuff();
    return "filter";
} 
 这最初正确地过渡到filterForm.jsp.我们可以使用浏览器后退按钮返回mainForm.jsp.我们可以反复这样做.
在mainForm.jsp上,我们有一个表(实际上是一个ILog甘特图,但我们认为不重要),在图表栏上有一个“弹出”菜单.其中一个菜单选项是重定向到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()呢?
******************************************************************************
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页面,而是每次都直接从服务器请求它.您可以在doFilter()方法中包含以下行的Filter的帮助下执行此操作:
@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> web.xml中的FacesServlet.例如.
<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>
