在&#34;结果&#34;中使用<h:link>和动态查询字符串

时间:2016-11-01 16:06:54

标签: jsf query-string

在我的JSF应用程序中,我有一个指向页面的链接,该页面是使用动态查询字符串构建的:

<h:link outcome="list?#{controller.queryString}" value="Example" />

我无法使用<f:param>,因为包含的参数计数会针对每个请求进行更改。

问题是查询字符串是 URL编码,因为某些参数值可以包含=。结果是查询字符串在结果HTML中被编码两次。

list?a=b%3Dc的结果变为:

<a href=".../list.xhtml?a=b%253Dc">Example</a>

查看JSF规范(默认NavigationHandler算法),我无法在查询字符串中找到有关编码的任何信息。但我认为com.sun.faces.application.NavigationHandlerImpl.findImplicitMatch是一个相当 hacky 的实现。

我的问题:我是否以错误的方式使用<h:link>按设计工作)或者这是某种错误?

我目前的解决方案是使用<h:outputLink>代替 - 这会阻止使用任何导航规则。

1 个答案:

答案 0 :(得分:3)

如果#{controller.queryString}至少是视图范围或更广,那么您可以使用Map<String, String>代替未编码的值,并使用<c:forEach>动态生成<f:param>条目。

private Map<String, String> params;

<h:link ...>
    <c:forEach items="#{bean.params}" var="entry">
        <f:param name="#{entry.key}" value="#{entry.value}" />
    </c:forEach>
</h:link>

如果它是请求范围(例如,取决于用户输入),那么您需要使用请求范围的bean并在ajax更新链接之前在action方法中显式重建视图,以便在渲染响应期间,JSTL标记再次运行。

String viewId = context.getViewRoot().getViewId();
UIViewRoot view = context.getApplication().getViewHandler().createView(context, viewId);
context.setViewRoot(view);

如果请求作用域的bean不是一个选项,那么最好的办法就是在ViewHandler#getBookmarkableURL()的帮助下手动生成URL,并将视图ID和参数作为Map传递。

url = context.getApplication().getViewHandler().getBookmarkableURL(context, outcomeViewId, params, false);

<a href="#{bean.url}">...</a>

如果您完全依赖隐式导航,结果视图ID很容易。

另见: