我的用于记录页面 View 的 servletfilter 正在通过单个页面请求接收 GET 和 POST。我追溯到在页面支持 bean 上使用 Omnifaces ViewScope。
@Named
@org.omnifaces.cdi.ViewScoped
我碰巧注意到日志文件中的双页 View 具有精确的时间戳。使用下面的简化版本进行调试,在单页请求上,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 View 状态和物理 bean。
另请参阅the documentation :
... 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!
这也是documented在“检测卸载请求”部分下。
When the unload request has hit your servlet filter or authentication mechanism or whatever global listener/observer, and you would like to be able to detect them, so that you can exclude them from the logic, then you can use
ViewScopeManager#isUnloadRequest(HttpServletRequest)
orViewScopeManager#isUnloadRequest(FacesContext)
, depending on whether theFacesContext
is available in the current context. You should always ensure that the flow just continues for them, else the unload requests won't be able to do their work of explicitly destroying the bean and state.
关于jsf - 使用 org.omnifaces.cdi.ViewScoped 时,我的 javax.servlet.Filter 在单个页面 View 上同时接收 GET 和 POST,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63603936/