2010-03-26 5 views
34

Ich habe einige Klassen, die eine Oberklasse erweitert, und in der JSP möchte ich einige Attribute dieser Klassen zeigen. Ich möchte nur eine JSP machen, aber ich weiß nicht im Voraus, ob das Objekt ein Attribut hat oder nicht. Also brauche ich einen JSTL-Ausdruck oder ein Tag, das überprüft, ob das übergebene Objekt dieses Attribut hat (ähnlich wie im Operator in Javascript, aber auf dem Server).Überprüfen Attribut existiert in JSP

<c:if test="${an expression which checks if myAttribute exists in myObject}"> 
    <!-- Display this only when myObject has the atttribute "myAttribute" --> 
    <!-- Now I can access safely to "myAttribute" --> 
    ${myObject.myAttribute} 
</C:if> 

Wie kann ich das bekommen?

Danke.

Antwort

50

Nutzen Sie JSTL c:catch tun können.

<c:catch var="exception">${myObject.myAttribute}</c:catch> 
<c:if test="${not empty exception}">Attribute not available.</c:if> 
+27

Ist es nur ich? Ich denke, das ist eine hässliche Art zu sehen, ob eine Variable existiert oder nicht. Es ist wie fangen NullPointerException in Java statt? '(if! = null)' –

+5

@Shervin: Es ist in der Tat ein schlechtes Design. Aber das ist bisher die einzige Möglichkeit, die eine oder andere Anforderung zu erfüllen. – BalusC

+0

@Shervin Asgari Ich denke, "wenn Null" sind hässlich. Es sei denn, Sie tun es Drittpartei API. sollten Sie auf alle Ausnahmen achten - Weg sauberer. – magulla

1

Meinen Sie so etwas wie dieses:

<c:if test="${not null myObject.myAttribute}"> 
    <!-- Now I can access safely to "myAttribute" --> 
</C:if> 

oder andere Variante

<c:if test="${myObject.myAttribute != null}"> 
    <!-- Now I can access safely to "myAttribute" --> 
</C:if> 

Wenn es sich um eine Liste, die Sie

<c:if test="#{not empty myObject.myAttribute}"> 
+3

Nein, wenn ich myObject.myAttribute und myObject hat keinen Getter für myAttribute Ich bekomme eine PropertyNotFoundException. Es ist nicht dasselbe, dass ein Objekt eine Eigenschaft mit einem Nullwert hat, dass es diese Eigenschaft nicht hat. – Javi

+0

Aber wie sonst sollen Sie auf die Immobilie zugreifen? Soweit ich weiß, kann es nur durch Getter erreicht werden. Auch wenn die Variable öffentlich ist, brauche ich einen Getter. Warum können Sie nicht einfach einen Getter erstellen? –

+3

Die Eigenschaft ist nicht in jeder Unterklasse vorhanden, also wenn die Eigenschaft vorhanden ist, habe ich einen Getter dafür. Das Problem ist, dass ich nicht weiß, welche der Unterklassen übergeben wird. – Javi

13

Sie können leicht eine benutzerdefinierte Funktion zu überprüfen, für die Eigenschaft, wie pro vivin's blog post erstellen.

Kurz gesagt, wenn Sie bereits Ihre eigenen taglib seine nur eine Frage des eine statische ‚hasProperty‘ Methode ... und

import java.beans.PropertyDescriptor; 
import org.apache.commons.beanutils.PropertyUtils; 

... 

public static boolean hasProperty(Object o, String propertyName) { 
    if (o == null || propertyName == null) { 
     return false; 
    } 
    try 
    { 
     return PropertyUtils.getPropertyDescriptor(o, propertyName) != null; 
    } 
    catch (Exception e) 
    { 
     return false; 
    } 
} 

... und das Hinzufügen von fünf Zeilen zu Ihren TLD ...

<function> 
    <name>hasProperty</name> 
    <function-class>my.package.MyUtilClass</function-class> 
    <function-signature>boolean hasProperty(java.lang.Object, 
     java.lang.String) 
    </function-signature> 
</function> 

... und es in Ihrer JSP

<c:if test="${myTld:hasProperty(myObject, 'myAttribute')}"> 
    <c:set var="foo" value="${myObject.myAttribute}" /> 
</c:if> 
2

Nur eine detailliertere (typisch?) Nutzung von BalusC großer Antwort Aufruf

<%-- 
    [1] sets a default value for variable "currentAttribute" 
    [2] check if myObject is not null 
    [3] sets variable "currentAttribute" to the value of what it contains 
    [4] catches "property not found exception" if any 
     - if exception thrown, it does not output anything 
     - if not exception thrown, it outputs the value of myObject.myAttribute 

--%> 
<c:set var="currentAttribute" value="" /> <%-- [1] --%> 
<c:if test="${not empty myObject}"> <%-- [2] --%> 
    <c:set var="currentAttribute"> <%-- [3] --%> 
     <c:catch var="exception">${myObject.myAttribute}</c:catch> <%-- [4] --%> 
    </c:set> 
</c:if> 

<%-- use the "currentAttribute" variable without worry in the rest of the code --%> 
currentAttribute is now equal to: ${currentAttribute} 

Wie Shervin in den Kommentaren der BalusC Antwort darauf hingewiesen, ist dies wahrscheinlich nicht die sauberste Lösung, aber wie durch BalusC antwortete „dass der einzige Weg, so weit ist die ungeradee Anforderung zu erreichen“.

Ressourcen

1

die akzeptierte Antwort kann einige Nebenwirkungen haben, wenn ich nur testen wollen, ob das Objektfeld, aber tun nicht den Wert des Feldes ausgeben wollen. In den genannten Fällen benutze ich das Schnipsel blasen:

<c:catch var="exception"> 
     <c:if test="${object.class.getDeclaredField(field) ne null}">    
     </c:if> 
</c:catch> 

hoffe das hilft.