避免为不同的 bean 创建相同的转换器

Avoiding to create the same converters for different beans

我成功实现了一个 bean 使用的 h:selectOneMenu 的转换器,但我想使用来自不同 bean 的相同转换器,而不是再次创建相同的转换器。

目前我有:

转换器

@FacesConverter(value = "csiConverter")
public class CsiConverter implements Converter {

@Override
public Object getAsObject(FacesContext ctx, UIComponent uiComponent, String dcId) {
    ValueExpression vex =
            ctx.getApplication().getExpressionFactory()
                    .createValueExpression(ctx.getELContext(),
                            "#{cfgbean}", CfgDbBean.class);

   ...
}

@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object o) {
    return ((Csi) o).getCsi();
}

和 xhtml

     <div class="form-group">
      <label>CSI</label>
     <h:selectOneMenu id="csi" styleClass="form-control" value="#{cfgbean.csi}" converter="csiConverter">
            <f:selectItems var="csival" itemLabel="#{csival.csi} - #{csival.name}" itemValue="${csival}" value="#{cfgbean.csilist}" />
        </h:selectOneMenu>          
      </div>

一切正常。 现在我想在不同的 xhtml 中创建相同的 selectOneMenu 出于相同的目的联系不同的 bean 以显示相同的内容。

问题在于 Converter class 内部连接了 bean 引用和 bean class。(createValueExpression(ctx.getELContext(), "#{cfgbean}", CfgDbBean.class);)

如何避免电缆引用并为所有 Bean 提供一个通用 csiConverter

谢谢

我有一个转换器,其中 getAsObject 方法可选择使用属性来传递 bean 名称。如果未设置该属性,我将使用组件的值属性来检测该值绑定到的对象类型:

ValueExpression valueExpression = uiComponent.getValueExpression("value");
Class<?> type = valueExpression.getType(ctx.getELContext());

从类型我可以确定bean 名称。这可能也是您的一个选择。

就我而言:

String beanName = type.getSimpleName() + "Bean";
beanName = beanName.substring(0, 1).toLowerCase() +
           beanName.substring(1);

如果您在不同的 bean 上使用相同的类型,您应该能够从以下位置获取 bean 名称:

valueExpression.getExpressionString()

它 returns 用于创建表达式的原始字符串,未修改。在你的情况下:

#{cfgbean.csi}

只需从该字符串中删除 .csi 部分即可获取 bean。如果你的 bean 扩展了一个抽象 bean / 实现了一个像 CsiHolder 这样的接口(或者你给它起的任何名字),你可以获得这样的 bean:

ctx.getApplication().evaluateExpressionGet(ctx, "#{cfgbean}", CsiHolder.class)

这是在 Jasper 的帮助下完成的部分。

    ValueExpression valueExpression = uiComponent.getValueExpression("value");
    String beanName = valueExpression.getExpressionString();
    //#{formbean.data}
    if(beanName.contains("#{")){
        String[] output = beanName.split("\{");
        if(output.length!=2){
            throw new IllegalArgumentException(beanName + " - invalid format!");
        }else{
            if(output[1].contains(".")){
                String[] bean = output[1].split("\.");
                beanName = bean[0];
            }else{
                throw new IllegalArgumentException(output[1] + " - invalid format!");
            }
        }
    }else{
        throw new IllegalArgumentException(beanName + " - invalid format!");
    }

    Object p = ctx.getApplication().evaluateExpressionGet(ctx, "#{"+beanName+"}", Object.class);

    if(p instanceof FormBean){
        FormBean p2 = (FormBean) p;
        return p2.getName(dcId); 
    }
    ...
    ...
    ...

它工作正常,我解决了这个问题。