valor Acceso Enum usando EL con JSTL


95

Tengo una llamada de estado de enumeración se define como tal:

public enum Status { 

    VALID("valid"), OLD("old"); 

    private final String val; 

    Status(String val) { 
     this.val = val; 
    } 

    public String getStatus() { 
     return val; 
    } 

} 

quisiera acceder al valor de VALID de una etiqueta JSTL. Específicamente, el atributo test de la etiqueta <c:when>. P.ej.

<c:when test="${dp.status eq Status.VALID"> 

No estoy seguro de si esto es posible.

102

Una comparación simple en contra de cadena funciona:

<c:when test="${someModel.status == 'OLD'}"> 
+11

Para aquellos que requieren una fuente: Esto se especifica (por ejemplo) en la sección 1.17 de la "Especificación del lenguaje de expresión, versión 2.2", que es parte de [JSR-245] (http://www.jcp.org/en/ jsr/detail? id = 245). 06 ago. 102010-08-06 16:57:43

+4

La especificación JavaServer Pages ™, versión 2.0 dice en JSP.2.3.5.7: "• Si A o B es Coerción de cadena tanto A como B a cadena, compare léxicamente" 13 abr. 112011-04-13 08:29:31

+8

Pero pierde la ventaja de tener una enumeración: esto podría conducir a engorrosos malentendidos si la enumeración cambia un día. Por lo general, si me encuentro cambiando una enumeración, me siento bastante seguro, y probablemente no recordaría esa referencia de cadena a referencia en esa vista ... 19 sep. 142014-09-19 14:31:51

  0

Correcto, es mejor colocar el código de toma de decisiones fuera de la vista. Sin embargo, a veces uno tiene que hacerlo. 22 sep. 142014-09-22 06:57:39

  0

¿Esto se compara con el toString de la enumeración? Por lo tanto, si anula el toString (por ejemplo, desea un nombre descriptivo amistoso), entonces debe asegurarse de cambiar también el valor con el que se compara. 07 jul. 172017-07-07 08:26:01


21

Así que para conseguir mi problema resuelto por completo que tenía que hacer lo siguiente:

<% pageContext.setAttribute("old", Status.OLD); %> 

entonces yo era capaz de hacer:

<c:when test="${someModel.status == old}"/>...</c:when> 

que trabajó como se esperaba.

+10

usando scriptlets es un mal estilo. 16 ago. 132013-08-16 15:54:24


9

A estos efectos hago lo siguiente:

<c:set var="abc"> 
    <%=Status.OLD.getStatus()%> 
</c:set> 

<c:if test="${someVariable == abc}"> 
    .... 
</c:if> 

Es ve feo, pero funciona!

  0

Sin embargo, no funcionará cuando se usen tagdirs. 12 jul. 132013-07-12 08:42:37


-1

Por lo general, considero una mala práctica mezclar código java en archivos jsps/tag. El uso de 'eq' debe hacer el truco:

<c:if test="${dp.Status eq 'OLD'}"> 
    ... 
</c:if> 
+3

Entonces, ¿es una mala práctica usar '==' en lugar de 'eq'? Ambos hacen exactamente lo mismo, por lo que no hay forma de "truco". 24 nov. 092009-11-24 11:08:50

  0

Por supuesto, no estaba haciendo una declaración sobre el uso de eq vs ==. Muchas respuestas a esta pregunta involucraron la inserción de código java en jsp o archivos de etiquetas que pueden ser una muleta. Estoy a favor de mantener la lógica de negocios en el código Java (donde se puede probar la unidad de forma fácil y exhaustiva) por separado de la lógica de visualización en el JSP. 25 nov. 092009-11-25 08:25:40

+7

Para mí, parece una mala práctica insertar cadenas mágicas en su JSP que el compilador no puede verificar cuando desea refactorizar sus enumeraciones. Parece que no hay una buena solución para esto en ningún lado. 19 ene. 112011-01-19 22:48:37


2

añadir un método para la enumeración como:

public String getString() { 
    return this.name(); 
} 

Por ejemplo

public enum MyEnum { 
    VALUE_1, 
    VALUE_2; 
    public String getString() { 
     return this.name(); 
    } 
} 

continuación, puede utilizar:

<c:if test="${myObject.myEnumProperty.string eq 'VALUE_2'}">...</c:if> 

3

No tengo una respuesta a la pregunta de Kornel, pero I'v e un comentario sobre los otros ejemplos de guiones. La mayor parte de la expresión confía implícitamente en el toString(), pero el Enum.valueOf() espera un valor que proviene de/coincide con la propiedad Enum.name(). Así que uno debe utilizar por ejemplo:

<% pageContext.setAttribute("Status_OLD", Status.OLD.name()); %> 
... 
<c:when test="${someModel.status == Status_OLD}"/>...</c:when> 

52

Si utilizando Spring MVC, el Lenguaje Expresión primavera (SpEL) puede ser útil:

<spring:eval expression="dp.status == T(com.example.Status).VALID" var="isValid" /> 
<c:if test="${isValid}"> 
    isValid 
</c:if> 
+1

Parece que esto no funciona para las enumeraciones internas? Causado por: org.springframework.expression.spel.SpelEvaluationException: EL1005E: (pos 0): No se puede encontrar el tipo 'my.package.model.EngagementRequest.EngagementStatus' 02 sep. 112011-09-02 16:37:04

+4

Intente usar 'my.package.model.EngagementRequest $ EngagementStatus ' 08 sep. 112011-09-08 13:53:10

  0

Lo bueno de esta solución es que aparece un mensaje de error si hay un error en su expresión, que no siempre ocurre con '<c:if>' y '<c:when>' (fallan silenciosamente). 14 oct. 152015-10-14 08:19:56


33

Usted tiene 3 opciones aquí, ninguno de los cuales es perfecta:

  1. Se puede utilizar un scriptlet en el atributo test:

    <c:when test="<%= dp.getStatus() == Status.VALID %>">

    Esto utiliza la enumeración, pero también utiliza un scriptlet, que no es el "camino correcto" en JSP 2.0.Pero lo más importante, esto no funciona cuando desea agregar otra condición al mismo when usando ${}. Y esto significa que todas las variables que desea probar deben declararse en un scriptlet, o mantenerse en la solicitud, o la sesión (la variable pageContext no está disponible en los archivos .tag).

  2. Puede comparar contra la cadena:

    <c:when test="${dp.status == 'VALID'}">

    Esto se ve limpio, pero usted está introduciendo una cadena que duplica el valor de enumeración y no puede ser validada por el compilador. Entonces, si elimina ese valor de la enumeración o lo renombra, no verá que esta parte del código ya no está accesible. Básicamente tienes que buscar/reemplazar a través del código cada vez.

  3. Puede agregar cada uno de los valores de enumeración se utiliza en el contexto de la página:

    <c:set var="VALID" value="<%=Status.VALID%>"/>

    y entonces usted puede hacer esto:

    <c:when test="${dp.status == VALID}">

prefiero la última opción (3), aunque también usa un scriptlet. Esto se debe a que solo lo usa cuando establece el valor. Más adelante, puede usarlo en expresiones EL más complejas, junto con otras condiciones EL. Mientras que en la opción (1) no puede usar un scriptlet y una expresión EL en el atributo test de una sola etiqueta when.

+1

Con respecto a la opción 2, el compilador no puede verificarlo, pero en tiempo de ejecución, la cadena se convertirá en una enumeración usando 'Enum.valueOf (Clase <T> enumType, String name) 'que activará una' ELException' si la enumeración no tiene constante con ese nombre. La expresión no siempre será siempre falsa. 13 jun. 142014-06-13 13:55:34


-2

En Java Class:

public class EnumTest{ 
    //Other property link 
    private String name; 
    .... 

     public enum Status { 
       ACTIVE,NEWLINK, BROADCASTED, PENDING, CLICKED, VERIFIED, AWARDED, INACTIVE, EXPIRED, DELETED_BY_ADMIN; 
      } 

     private Status statusobj ; 

    //Getter and Setters 
} 

Así que ahora se crea POJO y obj enumeración. Ahora EnumTest se configurará en el objeto de sesión utilizando en el servlet o clase de controlador session.setAttribute ("enumTest", EnumTest);

En la página JSP de

<c:if test="${enumTest.statusobj == 'ACTIVE'}"> 

//TRUE??? THEN PROCESS SOME LOGIC 

5

Aquí hay dos posibilidades más:

JSP EL 3.0 Constantes

Mientras usted está utilizando al menos la versión 3.0 de EL, entonces se puede importe las constantes en su página de la siguiente manera:

<%@ page import="org.example.Status" %> 
<c:when test="${dp.status eq Status.VALID}"> 

Sin embargo, algunos IDEs aún no lo entienden (p. IntelliJ) por lo que no recibirá ninguna advertencia si comete un error tipográfico, hasta el tiempo de ejecución.

Este sería mi método preferido una vez que reciba la compatibilidad adecuada con IDE.

Métodos útiles para

Se podía añadir captadores a su enumeración.

public enum Status { 
    VALID("valid"), OLD("old"); 

    private final String val; 

    Status(String val) { 
    this.val = val; 
    } 

    public String getStatus() { 
    return val; 
    } 

    public boolean isValid() { 
    return this == VALID; 
    } 

    public boolean isOld() { 
    return this == OLD; 
    } 
} 

Luego, en su JSP:

<c:when test="${dp.status.valid}"> 

Esto es compatible con todos los entornos de desarrollo y también funcionará si no se puede utilizar EL 3.0 todavía. Esto es lo que hago en este momento porque mantiene toda la lógica envuelta en mi enumeración.

También tenga cuidado si es posible que la variable que almacena la enumeración sea nula. Usted tendría que comprobar que en primer lugar si el código no garantiza que no es nulo:

<c:when test="${not empty db.status and dp.status.valid}"> 

Creo que este método es superior a aquellos en los que se establece un valor de intermediaria en la JSP, ya que tiene que hacer eso en cada página donde necesitas usar la enumeración. Sin embargo, con esta solución solo necesita declarar el getter una vez.

+1

La parte "Constantes JSP EL 3.0" debe ser la respuesta aceptada, ya que es la forma estándar de lograr el resultado requerido utilizando la funcionalidad incorporada. En una nota lateral, InteliJ IDEA (al menos Ultimate versión 2017.2.4) lo admite de fábrica y muestra la lista de constantes disponibles cuando escribe '$ {MyEnum.}', Coloca el cursor justo después del punto y presiona 'Ctrl + Espacio' para mostrar sugerencias. 13 sep. 172017-09-13 22:59:22


1

Cuando uso un marco MVC pongo lo siguiente en mi controlador.

request.setAttribute(RequestParameterNamesEnum.INBOX_ACTION.name(), RequestParameterNamesEnum.INBOX_ACTION.name()); 

Esto me permite utilizar lo siguiente en mi página JSP.

<script> var url = 'http://www.nowhere.com/?${INBOX_ACTION}=' + someValue;</script> 

También se puede utilizar en su comparación

<c:when test="${someModel.action == INBOX_ACTION}"> 

que yo prefiero más de poner en una cadena literal.