【问题标题】:Using <h:link> with a dynamic query string in "outcome"在“结果”中将 <h:link> 与动态查询字符串一起使用
【发布时间】:2016-11-01 16:06:54
【问题描述】:

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

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

我不能使用&lt;f:param&gt;,因为每个请求包含的参数数量都会发生变化。

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

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

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

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

我的问题:我是否以错误的方式使用了&lt;h:link&gt;按设计工作)还是这是一个错误?

我目前的解决方案是改用&lt;h:outputLink&gt; - 这会阻止使用任何导航规则。

【问题讨论】:

    标签: jsf query-string


    【解决方案1】:

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

    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 更新链接之前在操作方法中显式重建视图,如下所示,以便 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 很容易。

    另见:

    【讨论】:

    • 不幸的是,我的参数取决于一些输入值 - 它们是请求范围的,在 查看构建时间期间不可用。您如何看待“错误与否”?如果我应该报告这件事,我无所谓。
    • &lt;a&gt; 解决方案不只是替代我的&lt;h:outputLink&gt; 解决方案吗?重建视图看起来就像用大锤敲碎坚果。在这种情况下,我宁愿编写一个自定义渲染器来解决我的应用程序中所有&lt;h:link&gt; 的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2010-10-28
    • 2013-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多