EL에서 상수를 참조하는 방법은 무엇입니까?


106

JSP 페이지에서 EL로 상수를 어떻게 참조합니까?

Addresses이름이 상수 인 인터페이스 가 있습니다.URL 있습니다. 다음으로 이동하여 스크립트로 참조 할 수 있다는 것을 알고 <%=Addresses.URL%>있지만 EL을 사용하여 어떻게 수행합니까?

답변:


156

EL 3.0 이상

이미 Java EE 7 / EL 3.0 @page import을 사용중인 경우은 EL 범위의 클래스 상수도 가져옵니다.

<%@ page import="com.example.YourConstants" %>

이것은을 통해 가져 와서 ImportHandler#importClass()사용할 수 있습니다 ${YourConstants.FOO}.

모든 것을 참고 java.lang.*클래스가 이미 암시 적 수입과 같이 사용할 수 있습니다 ${Boolean.TRUE}${Integer.MAX_VALUE}. 초기 버전에 버그가 있었으므로 최신 Java EE 7 컨테이너 서버 만 필요합니다. 예 : GlassFish 4.0 및 Tomcat 8.0.0-1x는 실패하지만 GlassFish 4.1+ 및 Tomcat 8.0.2x +는 작동합니다. 그리고 web.xml서버에서 지원하는 최신 서블릿 버전을 준수하도록 선언 되었는지 확인해야 합니다. 따라서 web.xmlServlet 2.5 또는 이전 버전에 적합하다고 선언 된에서는 Servlet 3.0+ 기능이 작동하지 않습니다.

또한이 기능은 Facelet이 아닌 JSP에서만 사용할 수 있습니다. JSF + Facelets의 경우 가장 좋은 방법은 아래와<o:importConstants> 같이 OmniFaces 를 사용 하는 것입니다.

<o:importConstants type="com.example.YourConstants" />

또는 ImportHandler#importClass()아래와 같이 호출하는 EL 컨텍스트 리스너를 추가 합니다.

@ManagedBean(eager=true)
@ApplicationScoped
public class Config {

    @PostConstruct
    public void init() {
        FacesContext.getCurrentInstance().getApplication().addELContextListener(new ELContextListener() {
            @Override
            public void contextCreated(ELContextEvent event) {
                event.getELContext().getImportHandler().importClass("com.example.YourConstants");
            }
        });
    }

}

EL 2.2 이상

입니다 하지 EL 2.2 이상에서 가능합니다. 몇 가지 대안이 있습니다.

  1. Map<String, Object>응용 프로그램 범위에 넣으십시오 . EL에서지도 값으로 보통 자바 빈즈의 방법으로 액세스 할 수 있습니다 ${map.key}또는 ${map['key.with.dots']}.

  2. 사용 <un:useConstants>이 Unstandard 태그 라이브러리 (maven2는 REPO 여기 )

    <%@ taglib uri="http://jakarta.apache.org/taglibs/unstandard-1.0" prefix="un" %>
    <un:useConstants className="com.example.YourConstants" var="constants" />

    이렇게하면 .NET에서 일반적인 Javabean 방식으로 액세스 할 수 있습니다 ${constants.FOO}.

  3. 이 기사 의 하단에 설명 된 대로 Javaranch의 CCC <ccc:constantsMap> 를 사용 하십시오 .

    <%@ taglib uri="http://bibeault.org/tld/ccc" prefix="ccc" %>
    <ccc:constantsMap className="com.example.YourConstants" var="constants" />

    이렇게하면 일반적인 Javabean 방식으로 ${constants.FOO}도 액세스 할 수 있습니다.

  4. JSF2를 사용 <o:importConstants>하는 경우 OmniFaces를 사용할 수 있습니다 .

    <html ... xmlns:o="http://omnifaces.org/ui">
    <o:importConstants type="com.example.YourConstants" />

    이렇게하면 일반적인 Javabean 방식으로 #{YourConstants.FOO}도 액세스 할 수 있습니다.

  5. Javabean 스타일의 getter 메서드를 통해 반환하는 래퍼 클래스를 만듭니다.

  6. 먼저 상수의 존재를 스캔하고없는 경우 기본 해석기에 위임하고 그렇지 않으면 대신 상수 값을 반환하는 사용자 정의 EL 해석기를 만듭니다.


4
form : options 태그와 함께 정적 목록 필드를 사용하려고 할 때 동일한 문제가 발생했기 때문에이 질문을 찾았습니다. 정적 목록을 반환하는 비 정적 게터를 추가하여 작동시킬 수있었습니다. 약간 엉성하지만 JSP 개발입니다!
spaaarky21

1
빈이 봄에 의해 관리되는 경우 JSF에 대해 이것을 구성하는 방법에 대한 예가 있습니까? 미리 Thx.
Lodger

2
@Lodger : 나는 Spring을하지 않는다.
BalusC 2013

2
자카르타 unstandard-taglib프로젝트가 아직 살아 있습니까? 대안이 있습니까?
davioooh

1
열거 형에이 기술을 활용할 수있는 방법이 있습니까?
Niklas Peter

11

다음은 일반적으로 EL에 적용되지 않지만 대신 SpEL (Spring EL)에만 적용됩니다 (Tomcat 7에서 3.2.2.RELEASE로 테스트 됨). 누군가가 JSP와 EL을 검색하는 경우 (그러나 Spring과 함께 JSP를 사용하는 경우) 여기에서 언급 할 가치가 있다고 생각합니다.

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<spring:eval var="constant" expression="T(com.example.Constants).CONSTANT"/>

9

일반적으로 이러한 종류의 상수 Configuration는 서블릿 컨텍스트 의 객체 (게터 및 세터가 있음)에 배치하고 다음을 사용하여 액세스합니다.${applicationScope.config.url}


JSP에 관해서는 초보자입니다. 더 자세히 설명해 주시겠습니까?
tau-neutrino

1
@ tau-neutrino : 사실 간단합니다. urlString 속성으로 클래스를 Configuration만들고 이름을 지정하고 인스턴스화하고 url원하는대로 설정합니다 . 그 후 해당 Configuration개체를 ServletContext. 같은 무언가를 servletContext.setAttribute("config", config). 그리고 당신은 간다.
Adeel Ansari

제안 된 솔루션과 단순히 상수를 속성으로 추가하는 것의 차이점은 무엇입니까 ServletContext? 상수를 더 깔끔하게 분류 할 수 있다는 것뿐입니까? 예 : applicationScope.config.urlapplicationScope.url.
theyuv

7

당신은 할 수 없습니다. Java Bean 규칙을 따릅니다. 그래서 당신은 그것을위한 게터가 있어야합니다.


5

EL에서는 정적 속성에 액세스 할 수 없습니다. 내가 사용하는 해결 방법은 정적 값에 자신을 할당하는 비 정적 변수를 만드는 것입니다.

public final static String MANAGER_ROLE = 'manager';
public String manager_role = MANAGER_ROLE;

나는 lombok을 사용하여 getter와 setter를 생성하므로 꽤 좋습니다. EL은 다음과 같습니다.

${bean.manager_role}

http://www.ninthavenue.com.au/java-static-constants-in-jsp-and-jsf-el의 전체 코드


5

나는 다음과 같이 구현했다.

public interface Constants{
    Integer PAGE_SIZE = 20;
}

-

public class JspConstants extends HashMap<String, String> {

        public JspConstants() {
            Class c = Constants.class;
            Field[] fields = c.getDeclaredFields();
            for(Field field : fields) {
                int modifier = field.getModifiers();
                if(Modifier.isPublic(modifier) && Modifier.isStatic(modifier) && Modifier.isFinal(modifier)) {
                    try {
                        Object o = field.get(null);
                        put(field.getName(), o != null ? o.toString() : null);
                    } catch(IllegalAccessException ignored) {
                    }
                }
            }
        }

        @Override
        public String get(Object key) {
            String result = super.get(key);
            if(StringUtils.isEmpty(result)) {
                throw new IllegalArgumentException("Check key! The key is wrong, no such constant!");
            }
            return result;
        }
    }

다음 단계는이 클래스의 인스턴스를 servlerContext에 넣습니다.

public class ApplicationInitializer implements ServletContextListener {


    @Override
    public void contextInitialized(ServletContextEvent sce) {
        sce.getServletContext().setAttribute("Constants", new JspConstants());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }
}

web.xml에 리스너 추가

<listener>
    <listener-class>com.example.ApplicationInitializer</listener-class>
</listener>

jsp에서 액세스

${Constants.PAGE_SIZE}

4

처음에 내 jsp에서 상수를 정의하고 있습니다.

<%final String URI = "http://www.example.com/";%>

내 JSP에 핵심 taglib를 포함합니다.

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

그런 다음 다음 명령문으로 EL에서 상수를 사용할 수 있도록합니다.

<c:set var="URI" value="<%=URI%>"></c:set>

이제 나중에 사용할 수 있습니다. 다음은 디버깅 목적으로 값이 HTML 주석으로 작성된 예입니다.

<!-- ${URI} -->

상수 클래스를 사용하면 클래스를 가져오고 상수를 로컬 변수에 할당 할 수 있습니다. 내 대답이 일종의 빠른 해킹이라는 것을 알고 있지만 JSP에서 상수를 직접 정의하고 싶을 때도 질문이 올라갑니다.


1
lol 그것이 EL 변수를 초기화하는 방법이라면 Scriptlet을 직접 사용하지 않는 이유는 무엇입니까?
Navin

맨 위에 세 줄이 엉망이되고 나머지 JSP 전체에서 EL을 청소합니다 ^^.
koppor

1
@koppoor 그렇게 생각합니다. 나는 그냥 사용할 것입니다 <%=URI%>: P
Navin 2015 년

1
나는 직접 <%=URI%>이 작동하지 않는 곳 이 있었지만이 기술은 작동했습니다.
englebart

3

그래 넌 할수있어. 사용자 정의 태그가 필요합니다 (다른 곳에서 찾을 수없는 경우). 나는 이것을했다 :

package something;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.taglibs.standard.tag.el.core.ExpressionUtil;

/**
 * Get all class constants (statics) and place into Map so they can be accessed
 * from EL.
 * @author Tim.sabin
 */
public class ConstMapTag extends TagSupport {
    public static final long serialVersionUID = 0x2ed23c0f306L;

    private String path = "";
    private String var = "";

    public void setPath (String path) throws JspException {
        this.path = (String)ExpressionUtil.evalNotNull ("constMap", "path",
          path, String.class, this, pageContext);
    }

    public void setVar (String var) throws JspException {
        this.var = (String)ExpressionUtil.evalNotNull ("constMap", "var",
          var, String.class, this, pageContext);
    }

    public int doStartTag () throws JspException {
        // Use Reflection to look up the desired field.
        try {
            Class<?> clazz = null;
            try {
                clazz = Class.forName (path);
            } catch (ClassNotFoundException ex) {
                throw new JspException ("Class " + path + " not found.");
            }
            Field [] flds = clazz.getDeclaredFields ();
            // Go through all the fields, and put static ones in a Map.
            Map<String, Object> constMap = new TreeMap<String, Object> ();
            for (int i = 0; i < flds.length; i++) {
                // Check to see if this is public static final. If not, it's not a constant.
                int mods = flds [i].getModifiers ();
                if (!Modifier.isFinal (mods) || !Modifier.isStatic (mods) ||
                  !Modifier.isPublic (mods)) {
                    continue;
                }
                Object val = null;
                try {
                    val = flds [i].get (null);    // null for static fields.
                } catch (Exception ex) {
                    System.out.println ("Problem getting value of " + flds [i].getName ());
                    continue;
                }
                // flds [i].get () automatically wraps primitives.
                // Place the constant into the Map.
                constMap.put (flds [i].getName (), val);
            }
            // Export the Map as a Page variable.
            pageContext.setAttribute (var, constMap);
        } catch (Exception ex) {
            if (!(ex instanceof JspException)) {
                throw new JspException ("Could not process constants from class " + path);
            } else {
                throw (JspException)ex;
            }
        }
        return SKIP_BODY;
    }
}

태그는 다음과 같이 호출됩니다.

<yourLib:constMap path="path.to.your.constantClass" var="consts" />

모든 공개 정적 최종 변수는 해당 Java 이름으로 색인이 생성 된 맵에 배치됩니다.

public static final int MY_FIFTEEN = 15;

그런 다음 태그는 이것을 Integer로 래핑하고 JSP에서 참조 할 수 있습니다.

<c:if test="${consts['MY_FIFTEEN'] eq 15}">

getter를 작성할 필요가 없습니다!


3

할 수 있습니다. 방법을 따르십시오

 #{T(com.example.Addresses).URL}

TomCat 7 및 java6에서 테스트 됨


3
EL이 아닌 SpEL처럼 보입니다. 내가 착각 했나? 또한 이전 Tomcat5.5에서 작동합니까?
Pytry

2

조금 늦게 알고 심지어 이것이 약간의 해킹이라는 것을 알고도-원하는 결과를 얻기 위해 다음 솔루션을 사용했습니다. Java-Naming-Conventions 애호가라면 여기에서 읽는 것을 중단하는 것이 좋습니다.

이와 같은 클래스를 가지고 상수를 정의하고 빈 클래스로 그룹화하여 일종의 계층 구조를 만듭니다.

public class PERMISSION{
    public static class PAGE{
       public static final Long SEE = 1L; 
       public static final Long EDIT = 2L; 
       public static final Long DELETE = 4L; 
       ...
    }
}

PERMISSION.PAGE.SEE값을 검색하기 위해 Java 내에서 사용할 수 있습니다.1L

EL-Expressions 내에서 유사한 액세스 가능성을 달성하기 위해 다음과 같이했습니다. (코딩 신이있는 경우-그는 저를 용서할 수 있습니다. : D)

@Named(value="PERMISSION")
public class PERMISSION{
    public static class PAGE{
       public static final Long SEE = 1L; 
       public static final Long EDIT = 2L; 
       public static final Long DELETE = 4L; 
       ...

       //EL Wrapper
       public Long getSEE(){
           return PAGE.SEE;
       }

       public Long getEDIT(){
           return PAGE.EDIT;
       }

       public Long getDELETE(){
           return PAGE.DELETE;
       }
    }

    //EL-Wrapper
    public PAGE getPAGE() {
        return new PAGE();
    }
}

마지막으로 EL-Expression Long은 다음 #{PERMISSION.PAGE.SEE}과 같이 액세스합니다.-Java 및 EL-Access의 동등성. 나는 이것이 어떤 관습에서 벗어난 것을 알고 있지만 완벽하게 잘 작동합니다.


2

@Bozho는 이미 훌륭한 답변을 제공했습니다.

일반적으로 이러한 종류의 상수는 서블릿 컨텍스트의 Configuration 개체 (게터 및 설정자 포함)에 배치하고 $ {applicationScope.config.url}을 사용하여 액세스합니다.

하지만 좀 더 명확하고 누군가의 시간을 절약 할 수 있도록 예제가 필요하다고 생각합니다.

@Component
public Configuration implements ServletContextAware {
    private String addressURL = Addresses.URL;

    // Declare other properties if you need as also add corresponding
    // getters and setters

    public String getAddressURL() {
        return addressURL;
    }

    public void setServletContext(ServletContext servletContext) {
        servletContext.setAttribute("config", this);
    }
}

0

정확히 원하는 것은 아니지만 아주 최소한의 방법으로 스크립틀릿을 터치하여 거의 동일하게 활성화 할 수있는 해결 방법이 있습니다. 스크립틀릿을 사용하여 값을 JSTL 변수에 넣고 나중에 페이지에서 깨끗한 JSTL 코드를 사용할 수 있습니다.

<%@ taglib prefix="c"       uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page import="com.whichever.namespace.Addresses" %>
<c:set var="ourUrl" value="<%=Addresses.URL%>"/>
<c:if test='${"http://www.google.com" eq ourUrl}'>
   Google is our URL!
</c:if>

1
왜 이것이 반대표를 받았는지 모르겠습니다. 이것은 다음의 옵션 # 3과 동일한 패턴입니다. stackoverflow.com/a/16692821/274677
Marcus Junius Brutus 2016
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.