使用 org.omnifaces.cdi.ViewScoped 时,我的 javax.servlet.Filter 在单个页面视图上同时接收 GET 和 POST

问题描述 投票:0回答:1

我的用于记录页面视图的 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
    }

还是我使用的全向视镜错误?

jsf omnifaces
1个回答
3
投票

这确实是设计使然。上一页上的 POST 基本上发送了一个信号,表明该页面已卸载,因此

@ViewScoped
背后的逻辑知道它必须立即销毁 JSF 视图状态和物理 bean。

另请参阅文档

...此 CDI 视图范围注释将保证在浏览器卸载时也调用

@PreDestroy
注释方法。这个技巧是由
navigator.sendBeacon
完成的。对于不支持
navigator.sendBeacon
的浏览器,它将回退到同步 XHR 请求。

当您想在过滤器中检测它们时,您可以使用

ViewScopeManager#isUnloadRequest()

if (!ViewScopeManager.isUnloadRequest(request)) {
    // Write to actual log file.
}

chain.doFilter(request, response); // Ensure that this just continues!

这也在“检测卸载请求”部分下记录了

© www.soinside.com 2019 - 2024. All rights reserved.