【问题标题】:Is there a good way to make a filter not apply to h:commandLink click?有没有让过滤器不适用于 h:commandLink 点击的好方法?
【发布时间】:2013-03-11 15:05:39
【问题描述】:

我的h:commandLink 中的操作未触发时遇到问题。我查看了 BalusC 非常 useful post 的原因可能是什么,我能够将其追溯到第 11 号:

确保同一请求-响应链中没有过滤器或 Servlet 以某种方式阻止了对 FacesServlet 的请求。

似乎有一个过滤器导致了问题 - 我通过删除过滤器并重试发现了这个问题。不幸的是我没有写过滤器,更不幸的是我对它们知之甚少。所以我想知道是否有一种好方法可以让这个过滤器不适用于h:commandLink 动作触发?我看到doFilter() 方法传递了以下参数:

ServletRequest request
ServletResponse response
FilterChain chain 

所以我的第一直觉是看看是否有我可以在其中一个参数中使用的东西,这些参数会告诉我这是来自我的h:commandLink 的点击。如果是这样,我将绕过doFilter() 方法中的所有代码。不确定这是否可能,或者是一种好的方法,但这是首先想到的。

但我也想在这里问一下是否有一种体面的方法来处理这个问题?或者这是否表明过滤器本身存在某种问题,我可能需要考虑修复?任何类似的信息都会很有用。

顺便说一句,我知道我可能可以使用actionListener 来触发我的 bean 中的方法,但是,据我了解,这是不好的设计,所以我想避免这种情况。

【问题讨论】:

  • 这是一个非常罕见的原因,表明相关过滤器中可能存在严重错误或配置错误。它是哪个过滤器?第三方的还是内部的?你能说出它的全限定类名吗?你能告诉/问它的工作是什么吗?
  • 有问题的过滤器是由同行在内部编写的。他的解释如下:“它将长网址重定向到匹配的短网址并将这些短网址转发到真正的长网址”。当我删除过滤器时,要访问页面,我必须转到更长的 url,例如 /status/app/page.xhtml。有了过滤器,这个 url 就变成了 /status/page/ - 所以听起来我有一些调试要做,我想现在是我学习过滤器的时候了 - 一旦我有更好的信息或解决方案
  • 听起来好像他试图以与 JSF2 完全兼容的方式重新发明 PrettyFaces 已经发明的东西。您可能想考虑使用它来获得更强大的实现,而不是浪费时间重新发明轮子,同时对问题的了解不足。
  • 我的调试似乎表明当单击h:commandLink 时,过滤器将其视为来自“长 URL”的请求。当这种情况发生时,链会被使用生成的“短 URL”的重定向中断:httpResponse.setHeader("Location", shortRedirectUrl); 所以我今天会问他是否考虑过 PrettyFaces,如果我的利益相关者可以接受,我会检查自己实施这个 - 感谢信息!

标签: jsf action servlet-filters


【解决方案1】:

我说过,一旦我的解决方案制定出来,我会更新这个。所以我最初的问题的答案是它是可能的。但是这样做的方法并不是很好的设计。

警告 - 第一个选项非常老套,我不建议您这样做 - 只是为了完整性而添加。一种方法是为您的h:commandLink 提供一个 ID,例如“skipFilter”。然后在过滤器中,检查此 ID。您可以在#HttpServletRequest.getParameterNames() 中检查这一点。如果您看到请求来自此 ID,则添加逻辑以跳过过滤器。

另一种选择是只使用 ajax。然后在过滤器中添加逻辑检查请求是否为ajax,如果是则绕过过滤器:if("partial/ajax".equalsIgnoreCase(#HttpServletRequest.getHeader("Faces-Request")))

稍微不那么老套了。

但这已经在我的项目过滤器中完成了,所以我没有自己添加它。

另一个选项当然是 BalusC 推荐的,纠正或更换过滤器。在我的情况下,这不是一个选项,因此我必须在过滤器的限制范围内工作。所以我只使用ajax。我有我的h:commandLink:

<h:commandLink action="#{orderInvoiceBean.navToPdfAction}" value="-EXTRA INVOICE LINK- #{invoice.customerTrxId}" >   
   <f:setPropertyActionListener target="#{orderInvoiceBean.orderInvoiceNative}" value="#{invoice}"/>
   <f:ajax/>  
</h:commandLink>

这样,首先设置 orderInvoiceNative 属性,然后执行 ajax 操作,并且可以根据需要访问该值。

但是,我还有一个问题。我需要显示二进制响应 - 而不是文本。当然,ajax 并不完全允许这样做。但是我被限制使用ajax。那么该怎么办呢?

好吧,我的 ajax 操作触发了一个导航规则,它只是导航到以下页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
   <h:body binding="#{orderInvoiceBean.orderInvoicePdf}"/>
</html>

通过这个页面操作,创建了一个新请求,所以现在我可以在响应中返回一个二进制文件。所以结果是,您停留在您单击链接的页面上,并且您会看到一个文件下载对话框 - 在发送二进制文件响应之前,它不会导航到空白页面,就像我最初担心的那样 - 您继续原始页面,并且浏览器中的 url 不会改变,即使您调用了导航规则转到新页面。

希望这对某人有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多