【问题标题】:How can you access the @Size annotation of a field in JSF?如何访问 JSF 中字段的 @Size 注释?
【发布时间】:2016-03-18 13:19:54
【问题描述】:

我的问题是:

出于兼容性原因,我的一些实体字段需要具有准确的长度。该长度通过@Size(min=10, max=10) 或字段上的类似名称定义。尽管这些字段被键入为字符串,但它们实际上包含数字。大多数字段的值都带有前导零,例如:0000148233

现在我不想强迫用户在输入字段中输入前导零。应该可以只输入148233

我的第一种方法是编写一个复合组件,它使用一个简单的 FacesConverter 根据属性 length 在输入上添加前导零:

<composite:interface>
    <composite:attribute name="value" required="true" />
    <composite:attribute name="length" required="true"
        type="java.lang.Integer" />
</composite:interface>

<composite:implementation>
    <h:inputText value="#{cc.attrs.value}">
        <f:converter converterId="leadingZeroesConverter" />
        <f:attribute name="length" value="#{cc.attrs.length}" />
    </h:inputText>
</composite:implementation>

我在 Converter 中读取了length 属性:

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
    int length = (Integer) component.getAttributes().get("length");
    return Strings.zeroPrefixFillUp(value, length);
}

这确实很好用,但我实际上不想在 JSF 中定义长度。

我想做的是以某种方式访问​​注释,无论是在 JSF 中还是在转换器中。这样我可以避免在两个地方维护该属性。

在转换器中,我有 FacesContext 和 UIComponent(显然是 InputText)。有什么方法可以获取字段的名称(以及它的类),以便我可以访问该注释?

PS:为了让您知道,为了清楚起见,我从 Converter 中删除了所有错误处理。

【问题讨论】:

  • @BalusC:我不认为这是重复的。这里要求的是能够使用转换器中的长度来自动添加前导零......
  • @Kukeltje:谢谢,这个链接让我走上了正轨。查看我的答案以查看可行的解决方案。任何进一步的建议表示赞赏。

标签: jsf reflection annotations


【解决方案1】:

关注@Kukeltje 的链接让我走上了正轨:

我现在有两个复合属性,即beanfield。通过cc.attrs.bean[cc.attrs.field] 我设置了inputText 的值。在我的转换器中,我评估表达式#{cc.attrs.bean}#{cc.attrs.field},它们返回bean 和字段的名称。使用反射,我现在可以访问 @Size 注释。

复合组件

<composite:interface>
    <composite:attribute name="bean" required="true" />
    <composite:attribute name="field" required="true" type="java.lang.String" />
</composite:interface>

<composite:implementation>
    <h:inputText value="#{cc.attrs.bean[cc.attrs.field]}">
        <f:converter converterId="leadingZerosConverter" />
    </h:inputText>
</composite:implementation>

转换器

@FacesConverter(value = "leadingZerosConverter")
public class LeadingZerosConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {

        Object bean = evaluateExpression("#{cc.attrs.bean}", context, Object.class);
        String fieldName = evaluateExpression("#{cc.attrs.field}", context, String.class);
        if (bean == null || fieldName == null) {
            throw new IllegalArgumentException("bean and field must not be null");
        }
        try {
            Size annotation = bean.getClass().getDeclaredField(fieldName).getAnnotation(Size.class);
            return Strings.zeroPrefixFillUp(value, annotation.min());
        } catch (NoSuchFieldException | SecurityException e) {
            throw new IllegalArgumentException(e);
        }   
    }

    private <T> T evaluateExpression(String expression, FacesContext context, Class<T> clazz) {

        ExpressionFactory factory = context.getApplication().getExpressionFactory();
        ValueExpression exp = factory.createValueExpression(context.getELContext(), expression, clazz);

        return clazz.cast(exp.getValue(context.getELContext()));
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return ((String) value).replaceFirst("^0+(?!$)", "");
    }
}

【讨论】:

  • 请添加异常处理
  • 完成。另外,我发现UIComponent.getCurrentCompositeComponent(context).getAttributes().get("bean"); 也将返回复合属性cc.attrs.bean。所以没有必要在evaluateExpression() 中乱用表达式语言。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-21
  • 1970-01-01
  • 2014-01-21
相关资源
最近更新 更多