我的用于记录页面视图的 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
}
还是我使用的全向视镜错误?
这确实是设计使然。上一页上的 POST 基本上发送了一个信号,表明该页面已卸载,因此
@ViewScoped
背后的逻辑知道它必须立即销毁 JSF 视图状态和物理 bean。
另请参阅文档:
...此 CDI 视图范围注释将保证在浏览器卸载时也调用
注释方法。这个技巧是由@PreDestroy
完成的。对于不支持navigator.sendBeacon
的浏览器,它将回退到同步 XHR 请求。navigator.sendBeacon
ViewScopeManager#isUnloadRequest()
。
if (!ViewScopeManager.isUnloadRequest(request)) {
// Write to actual log file.
}
chain.doFilter(request, response); // Ensure that this just continues!
这也在“检测卸载请求”部分下记录了。