为什么 JSF 会命中 xhtml 页面 3 次
Why does JSF hit xhtml page 3 times
我有一个 JSF 应用程序。击中入口点后。
/MyApp/start.xhtml
该页面包含一个查看操作,它将根据查询字符串参数决定转到哪个页面。
<f:viewAction action="#{startController.newQuote()}" />
.
@ManagedBean
@SessionScoped
public class StartController {
public String newQuote(){
....
FacesContext fc = FacesContext.getCurrentInstance();
ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler)fc.getApplication().getNavigationHandler();
nav.performNavigation("aboutYou.xhtml?faces-redirect=true");
}
据报道,根据我的过滤器,aboutYou.xhtml
被点击了 3 次。
@WebFilter("*.xhtml")
public class TrackingFilter implements Filter {
private static Logger LOG = Logger.getLogger(TrackingFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
LOG.trace("request URI: " + req.getRequestURI());
}
这是为什么?我怀疑这与 ?faces-redirect=true
使用的 PRG 模式有关,但我可能希望看到这 2 次,而不是 3 次。
如何优化我的过滤器,以便我只捕获移动到该页面的单个操作?
根据评论:
The browser shows x2 HTTP200 POSTs
这是完全符合预期的 1 个 GET 请求。如果您在加载请求的页面时触发一些 ajax 请求,则可能会发生这些 POST 请求。例如,假设 PrimeFaces,具有 <p:outputPanel deferred="true">
、<p:remoteCommand autoRun="true">
等。通常都与延迟加载有关。
您可以在过滤器中通过检查 HttpServletRequest#getMethod()
来识别 POST 请求。
if ("POST".equals(request.getMethod())) {
// It's a POST request.
}
或者,特别是 JSF ajax 通过检查 Faces-Request
header.
请求
if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
// It's a JSF ajax request.
}
与具体问题无关,你根本没有在这里执行PRG。默认情况下,<f:viewAction>
仅在 GET 请求上调用,而不是在 POST 请求上调用(它仅在您添加 onPostback="true"
时执行)。而且,<f:viewAction action>
的行为与 <h:commandButton action>
完全相同,包括像往常一样返回导航案例结果(唯一的区别是它是 GET,而不是 POST)。所以所有的导航处理程序和重定向混乱都是不必要的。
public String newQuote() {
// ...
return "aboutYou.xhtml";
}
仅当不支持返回 String
结果(如 <f:event type="preRenderView">
中)时,才需要导航处理程序方法。仅当初始请求是 POST 请求(如 <h:commandButton action>
或 <f:viewAction onPostback="true">
)时才需要重定向。
我有一个 JSF 应用程序。击中入口点后。
/MyApp/start.xhtml
该页面包含一个查看操作,它将根据查询字符串参数决定转到哪个页面。
<f:viewAction action="#{startController.newQuote()}" />
.
@ManagedBean
@SessionScoped
public class StartController {
public String newQuote(){
....
FacesContext fc = FacesContext.getCurrentInstance();
ConfigurableNavigationHandler nav = (ConfigurableNavigationHandler)fc.getApplication().getNavigationHandler();
nav.performNavigation("aboutYou.xhtml?faces-redirect=true");
}
据报道,根据我的过滤器,aboutYou.xhtml
被点击了 3 次。
@WebFilter("*.xhtml")
public class TrackingFilter implements Filter {
private static Logger LOG = Logger.getLogger(TrackingFilter.class);
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
LOG.trace("request URI: " + req.getRequestURI());
}
这是为什么?我怀疑这与 ?faces-redirect=true
使用的 PRG 模式有关,但我可能希望看到这 2 次,而不是 3 次。
如何优化我的过滤器,以便我只捕获移动到该页面的单个操作?
根据评论:
The browser shows x2 HTTP200 POSTs
这是完全符合预期的 1 个 GET 请求。如果您在加载请求的页面时触发一些 ajax 请求,则可能会发生这些 POST 请求。例如,假设 PrimeFaces,具有 <p:outputPanel deferred="true">
、<p:remoteCommand autoRun="true">
等。通常都与延迟加载有关。
您可以在过滤器中通过检查 HttpServletRequest#getMethod()
来识别 POST 请求。
if ("POST".equals(request.getMethod())) {
// It's a POST request.
}
或者,特别是 JSF ajax 通过检查 Faces-Request
header.
if ("partial/ajax".equals(request.getHeader("Faces-Request"))) {
// It's a JSF ajax request.
}
与具体问题无关,你根本没有在这里执行PRG。默认情况下,<f:viewAction>
仅在 GET 请求上调用,而不是在 POST 请求上调用(它仅在您添加 onPostback="true"
时执行)。而且,<f:viewAction action>
的行为与 <h:commandButton action>
完全相同,包括像往常一样返回导航案例结果(唯一的区别是它是 GET,而不是 POST)。所以所有的导航处理程序和重定向混乱都是不必要的。
public String newQuote() {
// ...
return "aboutYou.xhtml";
}
仅当不支持返回 String
结果(如 <f:event type="preRenderView">
中)时,才需要导航处理程序方法。仅当初始请求是 POST 请求(如 <h:commandButton action>
或 <f:viewAction onPostback="true">
)时才需要重定向。