EL kullanarak JSTL ile Enum değerine erişin


104

Şu şekilde tanımlanan Durum adlı bir Enum var:

public enum Status { 

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

    private final String val;

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

    public String getStatus() {
        return val;
    }

}

VALIDBir JSTL etiketinden değerine erişmek istiyorum . Özellikle etiketin testniteliği <c:when>. Örneğin

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

Bunun mümkün olup olmadığından emin değilim.

Yanıtlar:


112

Dizge çalışmalarıyla basit bir karşılaştırma:

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

11
Bir kaynağa ihtiyaç duyanlar için: Bu, JSR-245'in bir parçası olan "İfade Dili Spesifikasyonu, sürüm 2.2" bölüm 1.17'de belirtilmiştir (örneğin) .
meriton

4
JavaServer Pages ™ Spesifikasyonu, Sürüm 2.0, JSP.2.3.5.7'de şöyle diyor: "• A veya B Dize ise, hem A hem de B'yi Dize'ye zorlayın"
Roland Illig

11
Ancak bir numaralandırmanın avantajını kaybedersiniz: Bu, bir gün sıralama değiştirilirse, hantal yanlış anlamalara yol açabilir. Genellikle, kendimi bir sıralamayı değiştirirken bulursam, kendimi oldukça güvende hissederim ve muhtemelen bu görünümdeki
dizeden numaraya

1
Bu, numaralandırmanın toString'iyle mi karşılaştırılıyor? Dolayısıyla, toString'i geçersiz kılarsanız (örneğin, uygun bir görünen ad istiyorsanız), eşleştirilen değeri de değiştirdiğinizden emin olmanız gerekir.
Rupert Madden-Abbott

1
FWIW, bugün Java 8'imde (önemli olması durumunda WebSphere için IBM Java), bu işe yaramıyor gibi görünüyor. Yalnızca burada küçük harf olan "eski" olan dize değeriyle karşılaştırılırsa işe yarıyor gibi görünüyor
dbreaux

54

Spring MVC kullanılıyorsa, Spring Expression Language (SpEL) yardımcı olabilir:

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

1
Bu iç numaralandırmalar için işe yaramıyor mu? Nedeni: org.springframework.expression.spel.SpelEvaluationException: EL1005E: (pos 0): Tür bulunamıyor 'my.package.model.EngagementRequest.EngagementStatus'
Eddie

4
'My.package.model.EngagementRequest $ EngagementStatus' kullanmayı deneyin
James

Bu çözümle ilgili iyi bir şey, ifadenizde her zaman meydana gelmeyen <c:if>ve <c:when>(sessizce başarısız olan) bir hata varsa bir hata mesajı almanızdır.
vegemite4me

41

Burada hiçbiri mükemmel olmayan 3 seçeneğiniz var:

  1. testÖznitelikte bir betik kullanabilirsiniz :

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

    Bu, numaralandırmayı kullanır, ancak aynı zamanda JSP 2.0'da "doğru yol" olmayan bir betik kullanır. Aynı için başka bir koşul eklemek istediğinizde Ama en önemlisi, bu işe yaramazsa whenkullanarak ${}. Ve bu, test etmek istediğiniz tüm değişkenlerin bir betikte bildirilmesi veya istekte veya oturumda tutulması gerektiği anlamına gelir ( pageContextdeğişken .tagdosyalarda mevcut değildir ).

  2. Dizeyle karşılaştırabilirsiniz:

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

    Bu temiz görünüyor, ancak enum değerini kopyalayan ve derleyici tarafından doğrulanamayan bir dizge tanıtıyorsunuz. Dolayısıyla, bu değeri numaralandırmadan kaldırırsanız veya yeniden adlandırırsanız, kodun bu kısmına artık erişilemediğini görmezsiniz. Temelde her seferinde kod üzerinden bir arama / değiştirme yapmanız gerekir.

  3. Kullandığınız enum değerlerinin her birini sayfa bağlamına ekleyebilirsiniz:

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

    ve sonra bunu yapabilirsiniz:

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

Bir scriptlet kullanmasına rağmen son seçeneği (3) tercih ediyorum. Bunun nedeni, yalnızca değeri ayarladığınızda onu kullanmasıdır. Daha sonra diğer EL koşullarıyla birlikte daha karmaşık EL ifadelerinde kullanabilirsiniz. (1) seçeneğindeyken test, tek bir whenetiketin özniteliğinde bir betik ve bir EL ifadesi kullanamazsınız .


1
Seçenek 2 ile ilgili olarak, derleyici bunu doğrulayamaz, ancak çalışma zamanında dize , numaralandırmanın bu ada sahip bir sabiti yoksa Enum.valueOf(Class<T> enumType, String name)tetikleyecek olan bir numaralandırmaya dönüştürülür ELException. İfade her zaman yanlış olmayacaktır.
yeniden başlatın

23

Bu yüzden sorunumu tam olarak çözmek için aşağıdakileri yapmam gerekiyordu:

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

Sonra yapabildim:

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

beklendiği gibi çalıştı.


12
betik kullanmak kötü bir stildir.
Eugene Retunsky

13

İşte iki olasılık daha:

JSP EL 3.0 Sabitleri

EL'nin en az 3.0 sürümünü kullandığınız sürece, sabitleri sayfanıza aşağıdaki şekilde aktarabilirsiniz:

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

Ancak, bazı IDE'ler bunu henüz anlamadıklarından (örneğin IntelliJ ) çalışma zamanına kadar bir yazım hatası yaparsanız herhangi bir uyarı almayacaksınız.

Uygun IDE desteği aldıktan sonra bu benim tercih ettiğim yöntem olacaktır.

Yardımcı Yöntemler

Numaranıza alıcılar ekleyebilirsiniz.

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

Ardından JSP'nizde:

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

Bu, tüm IDE'lerde desteklenir ve henüz EL 3.0'ı kullanamıyorsanız da çalışacaktır. Şu anda yaptığım şey bu çünkü tüm mantığı numaramda saklı tutuyor.

Ayrıca, numaralandırmayı depolayan değişkenin boş olması mümkünse dikkatli olun. Kodunuz boş olmadığını garanti etmiyorsa, önce bunu kontrol etmeniz gerekir:

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

Bu yöntemin JSP'de bir ara değer belirlediğiniz yöntemlerden daha üstün olduğunu düşünüyorum çünkü numaralandırmayı kullanmanız gereken her sayfada bunu yapmanız gerekiyor. Bununla birlikte, bu çözümle alıcıyı yalnızca bir kez bildirmeniz gerekir.


2
Yerleşik işlevselliği kullanarak gerekli sonucu elde etmenin standart yolu olduğundan, "JSP EL 3.0 Sabitleri" bölümü kabul edilen yanıt olmalıdır. Bir yan not olarak, InteliJ IDEA (en azından Ultimate sürüm 2017.2.4) onu kutunun dışında destekler ve yazarken kullanılabilir sabitlerin listesini gösterir ${MyEnum.}, noktanın hemen arkasına düzeltme işareti koyun ve Ctrl+Spaceönerileri göstermek için tuşuna basın .
izogfif

[ GÜNCELLEME ] IntelliJ IDEA bu ​​yanıtta bahsedilen sorunu zaten çözmüş gibi görünüyor.
informatik01

10

Bu amaçla aşağıdakileri yapıyorum:

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

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

Çirkin görünüyor ama işe yarıyor!


3

Kornel sorusuna bir cevabım yok ama diğer senaryo örnekleri hakkında bir fikrim var. İfadenin çoğu dolaylı olarak öğesine güvenir toString(), ancak özellikten Enum.valueOf()gelen / Enum.name()özellik ile eşleşen bir değer bekler . Öyleyse, örneğin kullanılmalı:

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

2

Numaralandırmaya aşağıdaki gibi bir yöntem ekleyin:

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

Örneğin

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

O zaman şunları kullanabilirsiniz:

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

1

Bir MVC çerçevesi kullanırken aşağıdakileri denetleyicime koyarım.

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

Bu, JSP Sayfamda aşağıdakileri kullanmama izin veriyor.

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

Karşılaştırmanızda da kullanılabilir

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

Bir dize değişmezi koymayı tercih ederim.


1
<%@ page import="com.example.Status" %>

1. ${dp.status eq Title.VALID.getStatus()}
2. ${dp.status eq Title.VALID}
3. ${dp.status eq Title.VALID.toString()}
  • İçe aktarımı JSP sayfa başlığında en üste yerleştirin
  • GetStatus yöntemi ile çalışmak istiyorsanız , # 1'i kullanın
  • Enum öğesinin kendisiyle çalışmak istiyorsanız , # 2 veya # 3 kullanın
  • Eq yerine == kullanabilirsiniz

-1

Genelde java kodunu jsps / tag dosyalarına karıştırmanın kötü bir uygulama olduğunu düşünüyorum. 'Eq' kullanmak hile yapmalı:

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

3
Yani ==yerine kullanmak kötü bir uygulama eqmı? İkisini de tamamen aynı şekilde yapıyorlar, bu yüzden bir "numara" yok.
BalusC

Tabii ki, eq vs == kullanımıyla ilgili bir açıklama yapmıyordum. Bu sorunun pek çok yanıtı, jsp veya etiket dosyalarına java kodunu eklemeyi içeriyordu. İş mantığını java kodunda (ünitenin kolayca ve kapsamlı bir şekilde test edilebildiği) JSP'deki ekran mantığından ayrı tutmayı tercih ediyorum.
Eclatante

7
Bana göre, numaralandırmalarınızı yeniden düzenlemek istediğinizde derleyici tarafından kontrol edilemeyen sihirli dizeleri JSP'nize eklemek eşit derecede kötü bir uygulama gibi görünüyor. Görünüşe göre her iki tarafta da iyi bir çözüm yok.
Lyle

-1

Kullanılacak çok nokta varken bunu bu şekilde yapıyorum ...

public enum Status { 

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

    private final String val;

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

    public String getStatus() {
        return val;
    }

    public static void setRequestAttributes(HttpServletRequest request) {
        Map<String,String> vals = new HashMap<String,String>();
        for (Status val : Status.values()) {
            vals.put(val.name(), val.value);
        }
        request.setAttribute("Status", vals);
    }

}

JSP

<%@ page import="...Status" %>
<% Status.setRequestAttributes(request) %>

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

-2

Java Sınıfında:

    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
}

Artık POJO ve enum obj oluşturuldu. Şimdi EnumTest , sunucu uygulaması veya denetleyici sınıfını kullanarak oturum nesnesini ayarlayacaksınız. Session.setAttribute ("enumTest", EnumTest);

JSP Sayfasında

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

//TRUE??? THEN PROCESS SOME LOGIC
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.