使用 org.omnifaces.cdi.ViewScoped 时,我的 javax.servlet.Filter 在单个页面视图中同时收到 GET 和 POST
When using org.omnifaces.cdi.ViewScoped my javax.servlet.Filter receives both a GET and a POST on a single page view
我用于记录页面浏览量的 servletfilter 正在接收一个 GET 和一个带有单个页面请求的 POST。我追溯到在页面支持 bean 上使用 Omnifaces ViewScope。
@Named
@org.omnifaces.cdi.ViewScoped
我碰巧注意到我的日志文件中的双页浏览量具有准确的时间戳。使用以下简化版本进行调试,在单个页面请求中,doFilter 执行两次,第一次是 GET,URL 是我正在浏览的 URL。然后再次执行doFilter,它是一个POST,URL是我来自的页面。如果我刷新页面,我会看到一个 GET 然后一个 POST 到同一页面。如果我使用 javax.faces.view.ViewScoped
,只有 GET 请求进来。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
System.out.println(new java.util.Date() + " " + ((HttpServletRequest) request).getMethod() + " " + httpRequest.getServletPath());
chain.doFilter(request, response);
}
例如,如果我正在查看 http://localhost:8080/myApp/page1.xhtml 并将 url 更改为 page2.xhtml
过滤器将写出
Wed Aug 26 12:17:04 EDT 2020 GET /page2.xhtml
Wed Aug 26 12:17:04 EDT 2020 POST /page1.xhtml
也许是设计使然?。但我只想记录用户正在浏览的页面,而不是他们来自的页面。是不是很简单?:
if(((HttpServletRequest) request).getMethod().equalsIgnoreCase("GET")){
//Write to actual log file
}
还是我使用 omnifaces viewscope 有误?
这确实是设计使然。上一页的 POST 基本上发送了一个信号,表明该页面已被卸载,因此 @ViewScoped
背后的逻辑知道它必须立即销毁 JSF 视图状态和物理 bean。
... this CDI view scope annotation will guarantee that the @PreDestroy
annotated method is also invoked on browser unload. This trick is done by navigator.sendBeacon
. For browsers not supporting navigator.sendBeacon
, it will fallback to a synchronous XHR request.
如果您想在过滤器中检测它们,则可以使用 ViewScopeManager#isUnloadRequest()
。
if (!ViewScopeManager.isUnloadRequest(request)) {
// Write to actual log file.
}
chain.doFilter(request, response); // Ensure that this just continues!
诚然,这确实记录得不够清楚,我会在下一个版本中记住这一点。
我用于记录页面浏览量的 servletfilter 正在接收一个 GET 和一个带有单个页面请求的 POST。我追溯到在页面支持 bean 上使用 Omnifaces ViewScope。
@Named
@org.omnifaces.cdi.ViewScoped
我碰巧注意到我的日志文件中的双页浏览量具有准确的时间戳。使用以下简化版本进行调试,在单个页面请求中,doFilter 执行两次,第一次是 GET,URL 是我正在浏览的 URL。然后再次执行doFilter,它是一个POST,URL是我来自的页面。如果我刷新页面,我会看到一个 GET 然后一个 POST 到同一页面。如果我使用 javax.faces.view.ViewScoped
,只有 GET 请求进来。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
System.out.println(new java.util.Date() + " " + ((HttpServletRequest) request).getMethod() + " " + httpRequest.getServletPath());
chain.doFilter(request, response);
}
例如,如果我正在查看 http://localhost:8080/myApp/page1.xhtml 并将 url 更改为 page2.xhtml
过滤器将写出
Wed Aug 26 12:17:04 EDT 2020 GET /page2.xhtml
Wed Aug 26 12:17:04 EDT 2020 POST /page1.xhtml
也许是设计使然?。但我只想记录用户正在浏览的页面,而不是他们来自的页面。是不是很简单?:
if(((HttpServletRequest) request).getMethod().equalsIgnoreCase("GET")){
//Write to actual log file
}
还是我使用 omnifaces viewscope 有误?
这确实是设计使然。上一页的 POST 基本上发送了一个信号,表明该页面已被卸载,因此 @ViewScoped
背后的逻辑知道它必须立即销毁 JSF 视图状态和物理 bean。
... this CDI view scope annotation will guarantee that the
@PreDestroy
annotated method is also invoked on browser unload. This trick is done bynavigator.sendBeacon
. For browsers not supportingnavigator.sendBeacon
, it will fallback to a synchronous XHR request.
如果您想在过滤器中检测它们,则可以使用 ViewScopeManager#isUnloadRequest()
。
if (!ViewScopeManager.isUnloadRequest(request)) {
// Write to actual log file.
}
chain.doFilter(request, response); // Ensure that this just continues!
诚然,这确实记录得不够清楚,我会在下一个版本中记住这一点。