JSF表达式评估属性标签

时间:2012-03-02 10:47:18

标签: jsf el

我在评估包含由其他标签创建的var的EL表达式时遇到问题。

我有一个项目,我正在使用自定义验证器。

public class MyValidator implements Validator, StateHolder

我有一个与之关联的标记类:

public class MyValidatorTag extends ValidatorTag

此类允许属性fieldName,并为标记添加适当的tld文件:

<tag>
    <name>my-validator</name>
    <tag-class>my.packaga.MyValidatorTag</tag-class>
    <body-content>JSP</body-content>
    <description>This is my validator</description>
    <attribute>
        <name>fieldName</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
        <type>java.lang.String</type>
        <description>This is some field I need</description>
    </attribute>
</tag>

到目前为止一切顺利。但是这种设置不允许人们使用JSF EL表达式来表示属性值。 所以验证器类(不是标签类)我使用此代码来评估属性值:

public static String evaluateEl(String expression) {
    String value = null;
    if (expression == null) {
        return "";
    }
    if ((expression.indexOf("#{") != -1)
        && (expression.indexOf("#{") < expression.indexOf('}'))) {
        Object evaledValue =
            FacesContext.getCurrentInstance().getApplication().createValueBinding(
                expression).getValue(FacesContext.getCurrentInstance());
        if (evaledValue != null) {
            value = evaledValue.toString();
        } else {
            value = null;
        }
    } else {
        value = expression;
    }
    return value;
}

它仅限于字符串,适用于大多数EL表达式。表达式Hello #{1 eq 2}将使该属性具有值Hello false。 但是有一种情况不适用。包含由另一个标记创建的var的任何表达式都不起作用。数据表,数据系统,尤其是<f:loadBundle>,例如

<f:loadBundle basename="mypackage.message.ui-strings" var="msgs" />

后跟包含验证器的输入组件:

<cust:my-validator fieldName="#{msgs['myfield1.name']}"></cust:my-validator>

Fieldname使用上面的表达式评估代码计算为空字符串。将其更改为#{requestScope.msgs....并不能解决问题。查看loadBundle实现,它将var msgs添加到请求范围,因此我不明白为什么vars对我不起作用。拜托,有人帮我理解。

1 个答案:

答案 0 :(得分:4)

  

任何包含由另一个标记创建的var的表达式都不起作用。数据表,数据系统,最值得注意的是,例如

标记处理程序,例如<f:xxx><c:xxx>和一些<ui:xxx>(那些具有rendered属性)在JSF视图构建时执行,何时生成JSF UI组件树。它们不是UI组件树的一部分。他们已经完成了生成必要的JSF UI组件的工作。

<h:xxx>和一些<ui:xxx>(具有rendered属性的那些)的UI组件在JSF视图渲染时执行,此时要生成要发送的大型HTML字符串到当前HTTP请求的HTTP响应。

因此他们不会同步运行。

验证者的最终用户有几种方法可以解决这个问题,所有这些都列在这个答案中:How to set converter properties for each row of a datatable?

对于开发人员,还有另一种解决方案,让验证程序扩展UIComponentBase,然后在processValidators()中执行作业。父组件仅由UIComponent#getParent()提供,其提交的值可由UIInput#getSubmittedValue()提供。