我想使用值表达式的动态参数实现此目的:
<h:dataTable value="#{someBean.someValue}" var="field">
<h:column>#{anotherBean[field]}</h:column>
</h:dataTable>
其中field
为'user.name'
或'location.address.zip'
或......
有可能吗?
请注意,这是一个简单的示例,我对ValueExpression
感兴趣而不是dataTable
组件。
更新 现在的问题是:如何替换标准的BeanELResolver?
查看ELUtils:
...
composite.addRootELResolver(IMPLICIT_RESOLVER);
composite.add(FLASH_RESOLVER);
composite.addPropertyELResolver(COMPOSITE_COMPONENT_ATTRIBUTES_EL_RESOLVER);
addELResolvers(composite, associate.getELResolversFromFacesConfig());
addVariableResolvers(composite, FacesCompositeELResolver.ELResolverChainType.Faces,
associate);
addPropertyResolvers(composite, associate);
composite.add(associate.getApplicationELResolvers());
composite.addRootELResolver(MANAGED_BEAN_RESOLVER);
composite.addPropertyELResolver(RESOURCE_RESOLVER);
composite.addPropertyELResolver(BUNDLE_RESOLVER);
...
但我还没有完全理解旋转变压器链......所以我会继续学习:)
更新2
此代码有效;)
public class ExtendedBeanELResolver extends BeanELResolver
{
@Override
public Object getValue(ELContext context, Object base, Object property) throws NullPointerException, PropertyNotFoundException, ELException
{
try
{
return super.getValue(context, base, property);
}
catch(PropertyNotFoundException e)
{
try
{
Object value = base;
for(String part : property.toString().split("\\."))
{
value = super.getValue(context, value, part);
}
return value;
}
catch(PropertyNotFoundException e1)
{
context.setPropertyResolved(false);
}
}
return null;
}
}
答案 0 :(得分:9)
默认情况下不支持此操作。您需要在此处设置自定义ELResolver
。最简单的是扩展现有的BeanELResolver
。
这是一个启动示例:
public class ExtendedBeanELResolver extends BeanELResolver {
@Override
public Object getValue(ELContext context, Object base, Object property)
throws NullPointerException, PropertyNotFoundException, ELException
{
if (property == null || base == null || base instanceof ResourceBundle || base instanceof Map || base instanceof Collection) {
return null;
}
String propertyString = property.toString();
if (propertyString.contains(".")) {
Object value = base;
for (String propertyPart : propertyString.split("\\.")) {
value = super.getValue(context, value, propertyPart);
}
return value;
}
else {
return super.getValue(context, base, property);
}
}
}
要使其运行,请在faces-config.xml
:
<application>
<el-resolver>com.example.ExtendedBeanELResolver</el-resolver>
</application>
答案 1 :(得分:3)
关于这个主题的工作非常有趣,但并不完整。
如果您在此组件中设置的复合组件中传递值,则它不起作用。
示例:
<composite:interface>
<composite:attribute name="value" type="java.lang.Boolean" required="true" />
</composite:interface>
<composite:implementation>
<h:inputText id="inputValue" value="#{cc.attrs.value}"
</h:inputText>
</composite:implementation>
使用ExtendedBeanElResolver时,在设置值时会抛出PropertyNotFoundException。
因此,我花了几个小时来找到解决方案,这是工作解决方案,能够使用ExtendedBeanElResolver并能够在复合组件中设置值:
public class ExtendedBeanELResolver extends BeanELResolver {
private static final String PRIMEFACES_RESOURCE_PREFIX = "primefaces:";
private static final String RESOURCES_HANDLER = "class org.omnifaces.resourcehandler.GraphicResourceHandler";
private static final String PRIMEFACES_EXT_RESOURCES_HANDLER = "class org.primefaces.extensions.application.PrimeFacesExtensionsResourceHandler";
@Override
public Object getValue(ELContext context, Object base, Object property) {
if (property == null || base == null || base instanceof ResourceBundle || base instanceof Map || base instanceof Collection
|| property.toString().startsWith(PRIMEFACES_RESOURCE_PREFIX) || base.getClass().toString().equals(RESOURCES_HANDLER)
|| base.getClass().toString().equals(PRIMEFACES_EXT_RESOURCES_HANDLER)) {
return null;
}
String propertyString = property.toString();
if (propertyString.contains(".")) {
Object value = base;
for (String propertyPart : propertyString.split("\\.")) {
value = super.getValue(context, value, propertyPart);
}
return value;
} else {
Object v = super.getValue(context, base, property);
return v;
}
}
@Override
public void setValue(ELContext context, Object base, Object property, Object val) {
if (base != null && !(base instanceof ResourceBundle) && !(base instanceof Map) && !(base instanceof Collection))
super.setValue(context, base, property, val);
}
}
(我添加了“setValue”部分)。
现在它有效。不要犹豫,给我你的反馈,因为这是我在本网站的第一篇文章!