JSF和表达式语言:仅在存在时绑定属性

将数据列绑定到数据源中可能存在或可能不存在的属性的最佳方法是什么?

例如,如果您有一个类层次结构,其中某些子项可能是具有该属性的子类型,则会发生这种情况。 数据源包含各种子类类型。

 

当其中一个子类中不存在该属性时,始终会产生一个PropertyNotFoundException。 我不想在基类中包含该属性,因为根据业务规则它不应该存在。

你怎么解决这个问题?

在不改变课程的情况下,最好的办法就是在EL中做一个instanceof 。 您可以通过检查由Object#getClass()获得的(简单)类名,然后检查EL中的Class#getName()Class#getSimpleName()来实现。

假设具有该属性的类具有完全限定名com.example.SubItem ,这是一个示例:

  

要么

  

作为在EL中提供instanceoffunction的另一种方法,您可以考虑将一个isInstanceOf()方法添加到ApplicationScoped bean。 我使用类似的东西:

 @ManagedBean( name="app" ) @ApplicationScoped public class ApplicationController implements Serializable { public boolean isInstanceOf( Object o, String className ) throws ClassNotFoundException { return Class.forName( className ).isInstance( o ); } } 

然后我从EL称它为:

 <... rendered="#{app.isInstanceOf( someObject, 'java.lang.Object' )}"> 

通过一些调整,这个想法可以推广到便于从EL调用任何静态方法。

我认为在这种情况下最好的方法是为视图层创建一个包含所有必要字段的自定义实体,并将要显示的项目转换为它。

为什么不使用基类的布尔属性来告诉您是否在子类中具有实际属性。 这样你可以在EL表达式中轻松使用三元运算符,如下所示:

  

如果EL懒惰地评估表达式,这可能会有效,但我不确定,现在无法检查它。 但无论如何,这是一个开始的想法。

根据您的模型,我认为您可能希望在辅助bean中执行更多工作,而不是尝试使其在实际的JSF页面上工作。

您可以将表绑定到bean

  //BEAN HtmlDataTable dataTable; public DataTable getDataTable() { dataTable = new HtmlDataTable(); //etc... //add the columns here based on the logic in code } 

然后通过动态添加组件等实际在bean内部进行渲染……如果你想要分离模型,你需要将页面作为一个非常受控制的bean,那么上面的答案就更像是你所追求的了。

或者如建议的那样,只需使用rendered属性并检查类名(谨防空指针)。 我定期做两件事,这实际上取决于我将在实际的JSF中使用多少复杂的布尔逻辑。