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

标签 jsf omnifaces

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

这也是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) or ViewScopeManager#isUnloadRequest(FacesContext), depending on whether the FacesContext 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/

相关文章:

java - Primefaces selectOneListbox 验证错误 : Value is not valid

css - <o :form styleClass> not rendered when using MyFaces instead of Mojarra

jsf - 如何使用 onBlur 比较两个 inputText 包含并显示消息

jsf - 如何创建 OmniFaces GraphicImage 方法的缩略图链接

css - primefaces 切换(命令)按钮

jsf - Primefaces 与 Gallery Film strip 的 UI 问题

jsf-2 - 重定向到已配置的 <error-page> 时出现异常 (HTTP 500)

java - 找不到从中引用的标识符为 ":form:display"的组件

css - 如何使用 primefaces/jsf 部分显示图像