JSTL과 함께 EL을 사용하여 Enum 값에 액세스


104

다음과 같이 정의 된 Status라는 Enum이 있습니다.

public enum Status { 

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

    private final String val;

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

    public String getStatus() {
        return val;
    }

}

VALIDJSTL 태그 의 값에 액세스하고 싶습니다 . 특히 태그 의 test속성입니다 <c:when>. 예

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

이것이 가능한지 잘 모르겠습니다.

답변:


112

문자열에 대한 간단한 비교가 작동합니다.

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

11
소스가 필요한 경우 : JSR-245의 일부인 "표현 언어 사양, 버전 2.2"의 섹션 1.17에 지정되어 있습니다 (예 :) .
meriton 2010-08-06

4
JavaServer Pages ™ 사양, 버전 2.0은 JSP.2.3.5.7에서 다음과 같이 말합니다. "• A 또는 B가 문자열 인 경우 A와 B를 모두 문자열로 강제 비교하십시오. 어휘 비교"
Roland Illig 2011

11
그러나 열거 형을 갖는 이점을 잃어 버립니다. 언젠가 열거 형이 변경되면 성가신 오해로 이어질 수 있습니다. 일반적으로 열거 형을 변경하는 것이 안전하다고 느끼면 해당 뷰에서 string-to-enum-reference를 기억하지 못할 것입니다.
reallynice

1
이것은 enum의 toString과 비교됩니까? 따라서 toString을 재정의하는 경우 (예 : 친숙한 표시 이름을 원하는 경우) 일치하는 값도 변경해야합니다.
루퍼트 매든 - 애보트

1
FWIW, 오늘 내 Java 8 (중요한 경우 WebSphere 용 IBM Java)에서는 작동하지 않는 것 같습니다. 소문자 "오래된"것 여기에 문자열 값에 대해 비교하는 경우에만 작동하는 것 같다
dbreaux

54

Spring MVC를 사용하는 경우 Spring Expression Language (SpEL)가 도움이 될 수 있습니다.

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

1
내부 열거 형에 대해 작동하지 않는 것 같습니까? 유형을 찾을 수 없습니다 'my.package.model.EngagementRequest.EngagementStatus'org.springframework.expression.spel.SpelEvaluationException : EL1005E : (POS 0)에 의해 발생
에디

4
'my.package.model.EngagementRequest $ EngagementStatus'사용 시도
James

이 솔루션의 좋은 점은 식에 오류가있는 경우 오류 메시지가 표시된다는 것입니다. 이는 <c:if>and에서 항상 발생하지는 않습니다 <c:when>(조용히 실패 함).
vegemite4me

41

여기에 3 가지 선택 항목이 있으며 그중 어느 것도 완벽하지 않습니다.

  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) test에서는 단일 when태그 의 속성에 스크립틀릿과 EL 표현식을 사용할 수 없습니다 .


1
옵션 2와 관련하여 컴파일러는이를 확인할 수 없지만 런타임시 문자열은 열거 형에 해당 이름의 상수가없는 경우 Enum.valueOf(Class<T> enumType, String name)를 트리거하는 사용하여 열거 형으로 변환됩니다 ELException. 이 표현은 항상 거짓이 아닙니다.
재부팅

23

따라서 내 문제를 완전히 해결하려면 다음을 수행해야했습니다.

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

그런 다음 할 수있었습니다.

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

예상대로 작동했습니다.


12
스크립틀릿을 사용하는 것은 나쁜 스타일입니다.
Eugene Retunsky 2013-08-16

13

두 가지 가능성이 더 있습니다.

JSP EL 3.0 상수

버전 3.0 이상의 EL을 사용하는 한 다음과 같이 페이지로 상수를 가져올 수 있습니다.

<%@ 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을 사용할 수없는 경우에도 작동합니다. 이것은 모든 논리를 내 열거 형으로 묶어두기 때문에 지금 내가하는 일입니다.

또한 열거 형을 저장하는 변수가 null이 될 수있는 경우에도주의하십시오. 코드가 null이 아님을 보장하지 않는 경우 먼저 확인해야합니다.

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

이 방법은 열거 형을 사용해야하는 각 페이지에서 설정해야하기 때문에 JSP에서 중간 값을 설정하는 방법보다 우수하다고 생각합니다. 그러나이 솔루션에서는 getter를 한 번만 선언하면됩니다.


2
"JSP EL 3.0 상수"부분은 기본 제공 기능을 사용하여 필요한 결과를 얻는 표준 방법이므로 허용되는 답변이어야합니다. 참고로 InteliJ IDEA (최소한 Ultimate 버전 2017.2.4)는를 입력 할 때 사용 가능한 상수 목록 을 표시 ${MyEnum.}하고 점 바로 뒤에 캐럿을 놓고을 눌러 Ctrl+Space제안을 표시합니다.
izogfif

[ 업데이트 ] IntelliJ IDEA가 이미이 답변에 언급 된 문제를 해결 한 것 같습니다.
informatik01

10

이를 위해 다음을 수행합니다.

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

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

보기 흉해 보이지만 작동합니다!


3

Kornel의 질문에 대한 답은 없지만 다른 스크립트 예제에 대해서는 언급했습니다. 대부분의 식은를 암시 적으로 신뢰 toString()하지만 Enum.valueOf()Enum.name()속성 에서 가져 오거나 속성 과 일치하는 값을 기대 합니다. 따라서 다음을 사용해야합니다.

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

2

열거 형에 다음과 같은 메서드를 추가합니다.

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>

1

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

문자열 리터럴을 넣는 것보다 선호합니다.


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()}
  • JSP 페이지 헤더 의 맨 위에 가져 오기를 배치하십시오.
  • getStatus 메소드 로 작업 하려면 # 1을 사용하십시오 .
  • enum 요소 자체 로 작업 하려면 # 2 또는 # 3을 사용하십시오.
  • eq 대신 == 를 사용할 수 있습니다.

-1

나는 일반적으로 자바 코드를 jsps / tag 파일에 혼합하는 것이 나쁜 습관이라고 생각합니다. 'eq'를 사용하면 트릭을 수행해야합니다.

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

3
그래서 ==대신 eq? 를 사용하는 것은 나쁜 습관 입니다 . 둘 다 똑같은 일을하므로 "속임수"의 수단이 없습니다.
BalusC

물론 eq vs ==의 사용에 관한 진술을하지 않았습니다. 이 질문에 대한 많은 답변은 자바 코드를 jsp 또는 태그 파일에 삽입하는 것과 관련이 있습니다. JSP의 디스플레이 로직과는 별도로 비즈니스 로직을 자바 코드 (쉽고 철저하게 단위 테스트 할 수있는)로 유지하는 것을 선호합니다.
Eclatante

7
나에게는 열거 형을 리팩토링하고 싶을 때 컴파일러에서 확인할 수없는 매직 문자열을 JSP에 삽입하는 것도 똑같이 나쁜 습관 인 것 같습니다. 양쪽에 이것에 대한 좋은 해결책이없는 것 같습니다.
Lyle

-1

사용할 포인트가 많을 때 이렇게합니다 ...

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 클래스에서 :

    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가 생성됩니다. 이제 EnumTest 는 서블릿 또는 컨트롤러 클래스를 사용하여 세션 객체에 설정합니다. session.setAttribute ( "enumTest", EnumTest);

JSP 페이지에서

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

//TRUE??? THEN PROCESS SOME LOGIC
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.