2010-03-26 14 views
34

Tengo algunas clases que extienden una superclase, y en el JSP deseo mostrar algunos atributos de estas clases. Solo quiero hacer una JSP, pero no sé de antemano si el objeto tiene un atributo o no. Entonces necesito una expresión JSTL o una etiqueta que compruebe que el objeto que paso tiene este atributo (similar a en el operador en javascript, pero en el servidor).El atributo de comprobación existe en 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> 

¿Cómo puedo obtener esto?

Gracias.

Respuesta

50

Hacer uso de JSTL c:catch.

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

¿Soy solo yo? Creo que esta es una forma fea de ver si una variable existe o no. Es como atrapar NullPointerException en java en lugar de? '(if! = null)' –

+5

@Shervin: de hecho es un mal diseño. Pero esa es hasta ahora la única manera de lograr el requisito impar. – BalusC

+0

@ Shervin Asgari Creo que "si nulo" son feos. A menos que lo hagas de una API de terceros. debe encargarse de todas las excepciones, mucho más limpias. – magulla

1

¿Quieres decir algo como esto:

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

u otra variante del

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

Si se trata de una lista que puede hacer

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

No, si hago myObject.myAttribute y myObject no tiene un getter para myAttribute obtendré una PropertyNotFoundException. No es lo mismo que un objeto tenga una propiedad con valor nulo que no tenga esta propiedad. – Javi

+0

Pero, ¿cómo se supone que debes acceder a la propiedad? Solo puedo acceder a través de getters hasta donde yo sé. Incluso si la variable es pública, creo que necesita un getter. ¿Por qué no puedes crear un getter? –

+3

La propiedad no está presente en todas las subclases, por lo tanto, cuando la propiedad está presente, tengo un getter para ella. El problema es que no sé cuál de las subclases se aprobará. – Javi

13

Puede crear fácilmente una función personalizada para comprobar la propiedad, según vivin's blog post.

En resumen, si usted ya tiene su propia taglib es sólo una cuestión de crear un método estático 'hasProperty' ...

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; 
    } 
} 

... y la adición de cinco líneas a su dominio de nivel superior ...

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

... y decir que es en su uso de JSP

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

Sólo una más detallada (típico?) de BalusC gran respuesta

<%-- 
    [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} 

Como se señaló por Shervin en los comentarios de la respuesta de BalusC, esto probablemente no es la solución más limpia, sino como respuesta por BalusC "que es hasta ahora la única manera de lograr el requisito extraño".

Recursos

1

la respuesta aceptada puede tener algunos efectos secundarios cuando sólo quiero poner a prueba si el objeto tiene campo, pero hacerlo no quiere dar salida al valor del campo. En los casos mencionados, utilizo el fragmento de golpe:

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

Espero que esto ayude.

Cuestiones relacionadas