【问题标题】:JSF and expression language: Bind property only when it existsJSF 和表达式语言:仅在属性存在时绑定属性
【发布时间】:2011-08-02 21:57:21
【问题描述】:

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

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

<DataColumn outputText="#{item.property}" />

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

你会如何解决这个问题?

【问题讨论】:

    标签: java jsf el


    【解决方案1】:

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

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

    <h:outputText value="#{item.property}" rendered="#{item.class.name == 'com.example.SubItem'}" />
    

    <h:outputText value="#{item.property}" rendered="#{item.class.simpleName == 'SubItem'}" />
    

    【讨论】:

    • 我在尝试使用 #{item.class} 时遇到问题,但可以很好地使用 #{item.getClass()}
    • 如果你事先不知道这门课,你知道怎么做吗?
    【解决方案2】:

    作为在 EL 中提供instanceof 功能的另一种方法,您可以考虑将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 调用任何静态方法。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        <DataColumn outputText="#{item.hasProperty ? item.property : 'I don't have this property.'}" />
        

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

        【讨论】:

          【解决方案5】:

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

          您可以将表绑定到 bean

          <h:dataTable binding="#{myBean.dataTable}" />
          
          //BEAN
          HtmlDataTable dataTable;
          
          public DataTable getDataTable()
          {
            dataTable = new HtmlDataTable(); //etc...
            //add the columns here based on the logic in code
          }
          

          然后通过动态添加组件等实际在 bean 内部进行渲染...如果您希望分离模型并且您需要页面是一个非常受控的 bean,那么上面的答案真的更适合您'在之后。

          或者按照建议,只需使用呈现的属性并检查类名(注意空指针)。我会定期执行这两项操作,这实际上取决于我将在实际 JSF 中拥有多少复杂的布尔逻辑。

          【讨论】:

            猜你喜欢
            • 2011-03-15
            • 1970-01-01
            • 2013-08-18
            • 1970-01-01
            • 2012-08-05
            • 2014-04-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多