是否应该用单个javabean getter代替复杂的EL表达式?


10

在JSF中,如果我有一个根据多个变量有条件地进行渲染的组件,那么处理render语句的最佳方式是什么...该逻辑应存在于组件声明中还是以某种形式的帮助器类存在?

仅当动物是大象或狗并且动物没有静音时才显示文本woof。

选项1:

在视图中的实现:

<h:outputText id="text" value="woof" 
  rendered="#{animal.type == 'elephant' 
                  or animal.type == 'dog' and not(animal.mute)}"/>

或选项2:

封装形式:

<h:outputText id="text" value="woof" rendered="#{animal.barkingAnimal}"/>

与实施:

public class Animal {
     public boolean isBarkingAnimal() {
         return ("dog".equals(getType()) || "elephant".equals(getType())) && !isMute();
     }
...

因此,两者都可以工作...但是哪种是正确的方案?


对于该特定示例,我将使用el。看来只是与视图相关的数据。如果您的Java代码中有一些逻辑,barking animals我会调用该方法,因为它已经存在。如果您在多个站点上使用其视图逻辑,则可以从中构建el函数。

表达式语言最初叫尽可能简单的表达语言,这样可以在其预期的使用提示。我自己的观点:如果是观点逻辑,EL可能合适;如果是业务逻辑,则不是。
McDowell

Answers:


5

在大多数情况下,这只是品味问题。如果您只是担心重用该条件,则可以执行以下操作:

<ui:param name="animalCanBark" value="#{animal.type == 'elephant' 
              or animal.type == 'dog' and not(animal.mute)}" />
...
<h:outputText id="text" value="woof" rendered="#{animalCanBark}"/>

当您需要编写的表达式涉及多个对象时,这通常很有用,例如:

<ui:param name="showBarking" value="#{animal.type == 'elephant'
              and not facesContext.validationFailed" />

我认为许多人更喜欢用Java而不是EL编写这种类型的逻辑,因为Java编译器可以在Java代码中进行类型检查(而且,大多数IDE的Java自动补全功能优于.XHTML文件)。对于一些。

话虽如此,如果有关某天该模型的信息可能会在其他地方(不仅仅是另一个Facelets / JSF页面)使用,那将是在您的Java代码中完成它的一个很好的理由。在您给出的示例中,该方法isBarkingAnimal()提供了有关模型(Animal)的一些信息,当另一个对象(不仅仅是另一个Facelets页面)需要知道给定的动物是否吠叫时,有一天该信息最终可能会有用。所以,我可能会同意。


3

根据经验,请尽量使.xhtml文件保持无逻辑,因此它们仅处理表示形式。因此,显然要选择选项2。


2
模型需要关注的逻辑吗?如果它使用超过一次,使用为什么会走样它<c:set>还是<ui:param>不是一种选择?

该示例背后没有模型逻辑。您需要将视图逻辑转换为模型逻辑,从而生成Java代码,而Java代码在Java中甚至没有调用。如果类Animal在其他环境(远程)中,或者程序员将其与之无关。

1

就个人而言,我将使用选项2。虽然我知道使用EL来解决问题并使用功能或ui:params在xhtml文档中获得一些重用是很有可能的,但它实际上似乎缺乏Java bean实现的可移植性,可维护性和可测试性。

如果开发人员精通EL和Java,并且同时拥有xhtml和Java Bean,那么使用EL进行大小大于1的任何条件评估似乎没有多大意义。

在Java端实现似乎似乎有太多好处:

  • 能够依靠IDE +编译器
  • 使用常量或枚举(用于“ dog”和“ bark”),它们也可能在代码中的其他地方使用以进行比较...如果String值发生更改,必须手动替换每个值在字符串中的出现是很有趣的代码库
  • 不必使用适当的数据导航到有问题的页面,我可以使用单元测试来练习逻辑

我听到的(在Stack之外)支持选项1的主要论据之一是:

“如果在视图中保留此逻辑,则更容易查看组件何时渲染。”

我发现对于处于生命初期的应用程序来说可能就是这种情况,因为它的重量更轻且更简单。但是,在较大规模上应用此实践,并且随着较小应用的成熟,它可能导致大鼠出现条件性巢,并成为维持噩梦。以下是一些与我在野外看到的类似的示例:

<h:outputText value="grrr" 
    render="#{animal.type == 'dog' or animal.type == 'cat' or animal.type == 'horse' 
        or animal.type == 'pony' or animal.type == 'mule' or animal.type == 'lion'
        or animal.type == 'tiger' or (animal.type == 'bird' 
        and animal.subType == 'macaw') or .... continue this for another line or two}"
/>

或我最喜欢的,使用多个渲染条件互斥的组件来表示可能显示的不同值:

<h:outputText value="grr" render="#{theMonstrosityFromPreviousExample} />
<h:outputText value="cry" 
    render="#{animal.type == 'human' and animal.subType == 'baby'}" />
<h:outputText value="yo" 
    render="#{animal.type == 'human' and animal.subType == 'teenager'}" />
<h:outputText value="hello" 
    render="#{animal.type == 'human' and animal.subType == 'adult'}"/>

一次最多可以显示4个文本吗?乍一看您看不出来,需要对每个条件进行检查。附带说明一下,我意识到这个示例的设计也不佳,因为可以将它们放在ac:choose ...中,但是我之前已经看到过。

归根结底,这仍然是理论上的“查看”逻辑,因为它确定了实际显示的内容,因此在xhtml中应该有一个概念上的论点。我发现的问题是,从长远来看,在视图模板中包含这样的逻辑会使布局更难以理解,而且我还没有看到解决问题的方法比使用Java具有任何真正的好处。 bean实现。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.