避免为不同的 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);
}
...
...
...
它工作正常,我解决了这个问题。
我成功实现了一个 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);
}
...
...
...
它工作正常,我解决了这个问题。