【问题标题】:No access to nested property in managed bean within p:columns无法访问 p:columns 中托管 bean 中的嵌套属性
【发布时间】:2026-02-14 07:55:01
【问题描述】:

我有以下两个简单的 POJO:

class Person {
   String name
   Address address;
   //and of course the getter/setter for the attributes
}

class Address {
   String city;
   //also getter/setter for this attribute
}

还有一个支持 bean:

@ManagedBean
@RequestScoped
class PersonController {

    private List persons;
    private List<String> columns = Arrays.toList("name", "address.city");
   //of course getter/setter
}

现在我想创建一个数据表。

<p:dataTable var="person" value="#{personController.persons}" columnIndexVar="index">
    <p:columns var="column" value="#{personController.columns}">
        <h:outputText value="#{person[column]}"/>
    <p:columms>
</p:dataTable>

当我执行这个时,我得到一个 ServletException:

Person 类没有“address.city”属性。

但是如果尝试在 p:columns 中访问这样的属性城市:

<h:outputText value="#{person.address.city}"/>

一切都很好。

为什么我不能访问像#{person['address.city']} 这样的嵌套属性?以及如何在p:columns 中访问它?

【问题讨论】:

  • &lt;h:columns&gt; 标签不存在。你是不是过度概括了 PrimeFaces &lt;p:columns&gt; 标签?

标签: jsf primefaces el


【解决方案1】:

默认情况下,不支持像 #{person['address.city']} 这样的大括号字符串表达式中的嵌套 bean 属性。你基本上需要一个#{person['address']['city']}

您需要在此处自定义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>

【讨论】:

  • 感谢您的及时答复。我会试试的!
  • 大家注意!我对这个解决方案和 FontAwesome 图标有疑问。在我实施解析器后,它们不再呈现。 @Schakko 的解决方案对我有用。
【解决方案2】:

除了@BalusC 答案之外,我还必须添加对 PrimeResourceHandler 的检查。否则,所有 #{resource...} 解析(如 primefaces.css 中的 #{resource['primefaces:spacer/dot_clear.gif']} )都会失败,解析后的 CSS 文件的输出流会损坏。

public class ExtendedBeanELResolver extends BeanELResolver {

    private static final String PRIMEFACES_RESOURCE_PREFIX = "primefaces:";

    @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 || base instanceof PrimeResourceHandler) {
            return null;
        }

        String propertyString = property.toString();

        if (!propertyString.startsWith(PRIMEFACES_RESOURCE_PREFIX) && 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);
        }
    }
}

【讨论】: