在我的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>
代替 - 这会阻止使用任何导航规则。
答案 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很容易。