1

我有一个问题,我的动作h:commandLink没有触发。我查看了 BalusC 关于原因可能是什么的非常有用的帖子,我能够将其追溯到第 11 号:

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

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

ServletRequest request
ServletResponse response
FilterChain chain 

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

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

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

4

1 回答 1

0

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

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

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

稍微不那么hacky。

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

另一种选择当然是 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 不会改变,即使您调用了导航规则转到新页面。

希望这对某人有用。

于 2013-03-29T14:00:46.190 回答