valore Accesso Enum utilizzando EL con JSTL


95

Ho una chiamata Stato Enum definiti come tali:

public enum Status { 

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

    private final String val; 

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

    public String getStatus() { 
     return val; 
    } 

} 

Vorrei accedere al valore di VALID da un tag JSTL. In particolare l'attributo test del tag <c:when>. Per esempio.

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

Non sono sicuro che sia possibile.

102

Un semplice confronto contro la stringa funziona:

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

Per quelli che richiedono una fonte: Questo è specificato (ad esempio) nella sezione 1.17 della "Expression Language Specification, versione 2.2", che fa parte di [JSR-245] (http://www.jcp.org/en/ JSR/dettaglio? id = 245). 06 ago. 102010-08-06 16:57:43

+4

La specifica JavaServer Pages ™, versione 2.0, dice in JSP.2.3.5.7: "• Se A o B è stringa coercitiva sia A che B a stringa, confrontare lessicalmente" 13 apr. 112011-04-13 08:29:31

+8

Ma si perde il vantaggio di avere un enum: questo potrebbe portare a incomprensioni ingombranti se l'enum viene cambiato un giorno. Di solito, se mi trovo a cambiare un enum, mi sento abbastanza sicuro, e probabilmente non mi ricorderei quel riferimento string-enum in quella vista ... 19 set. 142014-09-19 14:31:51

  0

Esatto, è meglio mettere il codice decisionale fuori la vista. Eppure a volte uno deve. 22 set. 142014-09-22 06:57:39

  0

Questo è confrontato con il toString dell'enum? Pertanto, se si esegue l'override di toString (ad esempio, si desidera un nome di visualizzazione descrittivo), è necessario accertarsi di modificare anche il valore con cui viene confrontato. 07 lug. 172017-07-07 08:26:01


21

Quindi, per ottenere il mio problema completamente risolto avevo bisogno di fare quanto segue:

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

Poi sono stato in grado di fare:

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

che ha funzionato come previsto.

+10

l'utilizzo di scriptlet è in cattivo stile. 16 ago. 132013-08-16 15:54:24


9

Per questo scopo ho effettuare le seguenti operazioni:

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

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

E 'sembra brutto, ma funziona!

  0

Tuttavia non funzionerà quando si usano i tagdir. 12 lug. 132013-07-12 08:42:37


-1

Generalmente considero una pratica errata mescolare il codice java in file jsps/tag. Usando 'eq' dovrebbe fare il trucco:

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

Quindi è una cattiva pratica usare '==' invece di 'eq'? Fanno esattamente la stessa cosa, quindi non c'è alcun mezzo per "trucchetti". 24 nov. 092009-11-24 11:08:50

  0

Naturalmente, non stavo facendo una dichiarazione riguardo l'uso di eq vs ==. Molte risposte a questa domanda riguardavano l'inserimento di codice java in jsp o tag file che possono essere una stampella. Io preferisco mantenere la logica di business nel codice java (dove può essere testato facilmente e in modo completo) separatamente dalla logica del display nel JSP. 25 nov. 092009-11-25 08:25:40

+7

Anche a me sembra una pratica altrettanto scorretta inserire stringhe magiche nel tuo JSP che non possono essere verificate dal compilatore quando vuoi rifattorizzare le tue enumerazioni. Sembra che non ci sia una buona soluzione su entrambi i lati. 19 gen. 112011-01-19 22:48:37


2

aggiungere un metodo per l'enumerazione come:

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

Per esempio

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

Quindi è possibile utilizzare:

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

3

Non ho una risposta alla domanda di Kornel, ma I'v e un'osservazione sugli altri esempi di script. La maggior parte dell'espressione si basa implicitamente sullo toString(), ma lo Enum.valueOf() prevede un valore che deriva dalla/corrisponde alla proprietà Enum.name(). Quindi, si dovrebbe usare, ad esempio:

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

52

Se si utilizza Spring MVC, la lingua Primavera Expression (SPEL) può essere utile:

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

Sembra che questo non funzioni per le enumerazioni interiori? Causato da: org.springframework.expression.spel.SpelEvaluationException: EL1005E: (pos 0): Impossibile trovare il tipo 'my.package.model.EngagementRequest.EngagementStatus' 02 set. 112011-09-02 16:37:04

+4

Prova a utilizzare 'my.package.model.EngagementRequest $ EngagementStatus ' 08 set. 112011-09-08 13:53:10

  0

Una cosa buona di questa soluzione è che ricevi un messaggio di errore se c'è un errore nell'espressione, che non sempre avviene con '<c:if>' e '<c:when>' (falliscono in silenzio). 14 ott. 152015-10-14 08:19:56


33

Hai 3 scelte qui, nessuno dei quali è perfetto:

  1. si può usare uno scriptlet nell'attributo test:

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

    Questo utilizza l'enumerazione, ma utilizza anche uno scriptlet, che non è il "modo giusto" in JSP 2.0.Ma soprattutto, questo non funziona quando si desidera aggiungere un'altra condizione allo stesso when utilizzando ${}. E questo significa che tutte le variabili che vuoi testare devono essere dichiarate in uno scriptlet, o mantenute in una richiesta o sessione (la variabile pageContext non è disponibile nei file .tag).

  2. È possibile confrontare contro la stringa:

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

    Questo sembra pulito, ma si sta introducendo una stringa che duplica il valore enum e non può essere convalidato dal compilatore. Quindi se rimuovi quel valore dall'enumerazione o lo rinomina, non vedrai che questa parte di codice non è più accessibile. Fondamentalmente devi fare una ricerca/sostituzione attraverso il codice ogni volta.

  3. È possibile aggiungere ognuno dei valori enum si usa nel contesto di pagina:

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

    e quindi si può fare questo:

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

preferisco l'ultima opzione (3), anche se utilizza anche uno scriptlet. Questo perché lo utilizza solo quando si imposta il valore. In seguito puoi usarlo in espressioni EL più complesse, insieme ad altre condizioni EL. Mentre nell'opzione (1) non è possibile utilizzare uno scriptlet e un'espressione EL nell'attributo test di un singolo tag when.

+1

Per quanto riguarda l'opzione 2, il compilatore non può verificarlo, ma in fase di esecuzione la stringa verrà convertita in enum usando 'Enum.valueOf (Classe <T> enumType, String name)' che attiverà un 'ELException' se l'enum non ha costante con quel nome. L'espressione non sarà sempre solo falsa. 13 giu. 142014-06-13 13:55:34


-2

in classe Java:

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 
} 

Così ora POJO e enum obj viene creato. Ora EnumTest verrà impostato nell'oggetto di sessione utilizzando nella classe servlet o controller session.setAttribute ("enumTest", EnumTest);

In JSP Pagina

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

//TRUE??? THEN PROCESS SOME LOGIC 

5

Qui ci sono altre due possibilità:

JSP EL 3.0 Costanti

Finché si utilizza almeno la versione 3.0 di EL, allora si può importare le costanti nella tua pagina come segue:

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

Tuttavia, alcuni IDE non lo comprendono ancora (ad es. IntelliJ) in modo da non ricevere alcun avviso se si commette un errore di battitura, fino al runtime.

Questo sarebbe il mio metodo preferito una volta ottenuto il corretto supporto IDE.

Metodi ausiliari

Si può solo aggiungere getter al vostro enum.

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

Poi, nel tuo JSP:

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

Questo è supportato in tutti i IDE e funziona anche se non è possibile utilizzare EL 3.0 ancora. Questo è quello che faccio in questo momento perché mantiene tutta la logica avvolta nel mio enum.

Inoltre, fare attenzione se è possibile che la variabile che memorizza l'enum sia nullo. Si avrebbe bisogno di verificare la presenza di quel primo se il codice non garantisce che non è nullo:

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

Penso che questo metodo è superiore a quelle in cui si imposta un valore intermedio nel JSP perché si deve fare in ogni pagina in cui è necessario utilizzare l'enumerazione. Tuttavia, con questa soluzione è sufficiente dichiarare il getter una sola volta.

+1

La parte "Costanti JSP EL 3.0" deve essere la risposta accettata poiché è il modo standard per ottenere il risultato richiesto utilizzando la funzionalità integrata. Una nota a margine, InteliJ IDEA (almeno Ultimate versione 2017.2.4) lo supporta immediatamente e mostra l'elenco delle costanti disponibili quando si digita '$ {MyEnum.}', Metti il ​​punto dopo il punto e premi 'Ctrl + Spazio' per mostrare suggerimenti. 13 set. 172017-09-13 22:59:22


1

Quando si utilizza un framework MVC, inserisco quanto segue nel mio controller.

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

Questo mi consente di utilizzare quanto segue nella mia pagina JSP.

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

Può essere utilizzato anche nel confronto

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

che preferisco più di mettere in una stringa letterale.