2013-05-26 17 views
1

我的大部分页面导航都使用get请求,现在我有一个窗体,其中参数应该作为查询字符串参数使用f:paramh:commandButton之内或检查includeViewParams的属性以使用UIViewParameterJSF - 从f:param和includeViewParams创建url查询字符串的内置方法

我不想使用includeViewParams,因为这将包括所有视图定义的参数,我只想使用作为命令组件的子项提供的参数。

<h:form> 
    <p:inputText value="#{bean.value1}"/> 
    <p:selectOneMenu value="#{bean.value2}"/> 
    <p:commandButton action="#{utilBean.performActionParams(outcome)}"> 
     <f:param name="key1" value="#{bean.value1}"/> 
     <o:param name="key1" value="#{bean.value2}" converter="#{bean.converter}/> 
    </p:commandButton> 
</h:form> 

public String performActionParams(final String outcome) 
{ 
    final UriBuilder uriBuilder = UriBuilder.fromPath(outcome); 

    final FacesContext context = FacesContext.getCurrentInstance(); 
    final UIComponent component = UIComponent.getCurrentComponent(context); 

    for (final UIComponent child : component.getChildren()) 
     if (child instanceof UIParameter) 
     { 
      final UIParameter param = (UIParameter) child; 

      if (!param.isDisable() && !StringUtils.isBlank(param.getName())) 
      { 
       final Object value = param.getValue(); 

       if (value != null) 
        uriBuilder.queryParam(param.getName(), value); 
      } 
     } 

    return uriBuilder.build().toString(); 
} 

这种逻辑是不是真的很复杂,但我觉得自己多余的,因为它似乎是同样的逻辑h:linkh:button

那么有人知道这个逻辑在哪里实现?

+0

真的不明白你的问题。这个检查在'RESTORE_VIEW'阶段完成,调用'ViewDeclarationLanguage.getViewMetadata()',在你的情况下将返回一个'ViewMetadata' **的实例,因为**你正在使用GET导航*和*你的目的地页面有''。你的问题是什么?你想重写元数据处理? – kolossus

+0

jsf中的某处必须有从'h:link'内读取'f:param'的代码并创建一个目标uri。我编辑回答并发布了我的代码,它基本上是一种解决方法,并且与'h:link'一样,只是用于使用commandbutton。我只是觉得我的代码是多余的,因为jsf中的某个地方已经被编码了。 – djmj

回答

0

在莫哈拉,这种逻辑也埋在OutcomeTargetRenderer#getEncodedTargetURL()(和HtmlBasicRenderer#getParamList())。由API提供的唯一公共部分是ViewHandler#getBookmarkableURL(),但它需要Map作为参数映射,而不是UIParameter组件的列表。

我不确定具体的功能需求是什么,但到目前为止,似乎你真的想要发起一个简单的GET请求而不是POST请求。在这种情况下,您应该使用<h:link><h:button>(或<p:button>)。他们的渲染器从OutcomeTargetRenderer延伸,并在内部实现了该逻辑。您可以在outcome属性中使用EL(可能的假设是这不可能是您尝试使用命令按钮的原因)。

<p:button outcome="#{outcome}"> 
    <f:param name="key1" value="#{value1}" /> 
    <o:param name="key1" value="#{value2}" converter="#{bean.converter}" /> 
</p:button> 

更新:按照评价,具体功能需求基本上是把一个JSF POST形式与所提交的数据一起到的GET请求。在这种情况下,如果将输入绑定到Map(可在getBookmarkableURL()中使用),则会更容易。

<h:inputText value="#{bean.params.key1}" /> 
<h:inputText value="#{bean.params.key2}" /> 
<p:commandButton value="#{bean.submit(outcome)}" /> 

private Map<String, String> params; 

@PostConstruct 
public void init() { 
    params = new HashMap<>(); 
} 

public String submit(outcome) { 
    // ... 

    return context.getApplication().getViewHandler() 
     .getBookmarkableURL(context, outcome, params, false); 

    // TODO: Is faces-redirect=true also considered? 
} 
+0

但是例如表单输入参数“#{bean.query}”不会被评估,因为在这种情况下我们没有回传(这些值也可以通过viewParam来设置)。我编辑我的示例以使用带有输入参数的表单,很抱歉忘记了这一点。将看看你的方法引用。 – djmj

+0

哦,这样。这完全有道理。那么,有一种方法,我会更新答案。 – BalusC

+1

不需要你的地图类型:'Map >'?.对于某些使用情况来说,这看起来很有希望,但是如果不是仅仅使用'inputText'的String应该被处理(因此在我的示例中使用'o:param'的Converter)。此外,如果bean值也可以通过'f:viewParam'来设置,这会迫使我总是使用一个映射(就像String的?),或者至少创建它。也许使用'HtmlBasicRenderer.getParamList()'和'getBookmarkableURL()'的组合。但是这会强制绑定到莫哈拉,这也不是一个好主意。 – djmj