Доступ к значению Enum с использованием EL с JSTL

StackOverflow https://stackoverflow.com/questions/123598

  •  02-07-2019
  •  | 
  •  

Вопрос

У меня есть Enum под названием Status, определенный как таковой:

public enum Status { 

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

    private final String val;

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

    public String getStatus() {
        return val;
    }

}

Я хотел бы получить доступ к значению VALID из тега JSTL.В частности test атрибут <c:when> ярлык.Например.

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

Я не уверен, возможно ли это.

Это было полезно?

Решение

Простое сравнение со строкой работает:

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

Другие советы

При использовании Spring MVC может оказаться полезным язык выражений Spring (SpEL):

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

У вас есть три варианта, ни один из которых не идеален:

  1. Вы можете использовать скриптлет в test атрибут:

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

    Здесь используется перечисление, но также используется скриптлет, что не является «правильным» в JSP 2.0.Но самое главное, это не работает, когда вы хотите добавить к тому же самому еще одно условие. when с использованием ${}.А это означает, что все переменные, которые вы хотите протестировать, должны быть объявлены в скриптлете, сохранены в запросе или сеансе (pageContext переменная недоступна в .tag файлы).

  2. Вы можете сравнить со строкой:

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

    Это выглядит чисто, но вы вводите строку, которая дублирует значение перечисления и не может быть проверена компилятором.Поэтому, если вы удалите это значение из перечисления или переименуете его, вы не увидите, что эта часть кода больше не доступна.По сути, вам каждый раз приходится выполнять поиск/замену в коде.

  3. Вы можете добавить каждое из используемых вами значений перечисления в контекст страницы:

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

    и тогда вы можете сделать это:

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

Я предпочитаю последний вариант (3), хотя он также использует скриптлет.Это потому, что он использует его только тогда, когда вы устанавливаете значение.Позже вы сможете использовать его в более сложных выражениях EL вместе с другими условиями EL.В варианте (1) вы не можете использовать скриптлет и выражение EL в test атрибут одного when ярлык.

Итак, чтобы полностью решить мою проблему, мне нужно было сделать следующее:

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

Тогда я смог сделать:

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

который сработал, как и ожидалось.

Вот еще две возможности:

Константы JSP EL 3.0

Если вы используете EL как минимум версии 3.0, вы можете импортировать константы на свою страницу следующим образом:

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

Однако некоторые IDE еще этого не понимают (например. IntelliJ), поэтому вы не получите никаких предупреждений, если допустите опечатку, до момента выполнения.

Это будет мой предпочтительный метод, как только он получит надлежащую поддержку IDE.

Вспомогательные методы

Вы можете просто добавить геттеры в свое перечисление.

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

Затем в вашем JSP:

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

Это поддерживается во всех IDE и также будет работать, если вы еще не можете использовать EL 3.0.Это то, что я делаю в данный момент, потому что вся логика сохраняется в моем перечислении.

Также будьте осторожны, если переменная, хранящая перечисление, может быть нулевой.Вам нужно будет сначала проверить это, если ваш код не гарантирует, что он не равен нулю:

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

Я думаю, что этот метод превосходит те, в которых вы устанавливаете промежуточное значение в JSP, потому что вам придется делать это на каждой странице, где вам нужно использовать перечисление.Однако в этом решении вам нужно объявить геттер только один раз.

Для этих целей я делаю следующее:

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

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

Выглядит некрасиво, но работает!

На вопрос о Корнеле у меня нет ответа, но есть замечание по поводу остальных примеров скриптов.Большая часть выражений безоговорочно доверяет toString(), но Enum.valueOf() ожидает значение, которое исходит из/соответствует Enum.name() свойство.Поэтому следует использовать, например:

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

Добавьте метод в перечисление, например:

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

Например

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

Затем вы можете использовать:

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

При использовании структуры MVC я помещаю в свой контроллер следующее.

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

Это позволяет мне использовать следующее на моей странице JSP.

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

Его также можно использовать в сравнении

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

Что я предпочитаю вводить строковый литерал.

<%@ 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()}
  • Поместите импорт в вершина, в заголовке страницы JSP
  • Если вы хотите работать с метод getStatus, использовать #1
  • Если вы хотите работать с элемент перечисления сам, используйте либо №2 или №3
  • Вы можете использовать == вместо экв.

Обычно я считаю плохой практикой смешивать Java-код с файлами jsps/tag.Использование «eq» должно помочь:

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

Я делаю это таким образом, когда есть много точек, которые можно использовать...

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

}

ДСП

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

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

В классе 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
}

Итак, теперь созданы POJO и enum obj.Сейчас ЭнумТест Вы установите в объекте сеанса, используя в сеансе сервлета или класса контроллера. SetAttribute ("EnumTest", EnumTest);

На странице JSP

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

//TRUE??? THEN PROCESS SOME LOGIC
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top