답변:
이미 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.xml
Servlet 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 이상에서 가능합니다. 몇 가지 대안이 있습니다.
Map<String, Object>
응용 프로그램 범위에 넣으십시오 . EL에서지도 값으로 보통 자바 빈즈의 방법으로 액세스 할 수 있습니다 ${map.key}
또는 ${map['key.with.dots']}
.
사용 <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}
.
이 기사 의 하단에 설명 된 대로 Javaranch의 CCC <ccc:constantsMap>
를 사용 하십시오 .
<%@ taglib uri="http://bibeault.org/tld/ccc" prefix="ccc" %>
<ccc:constantsMap className="com.example.YourConstants" var="constants" />
이렇게하면 일반적인 Javabean 방식으로 ${constants.FOO}
도 액세스 할 수 있습니다.
JSF2를 사용 <o:importConstants>
하는 경우 OmniFaces를 사용할 수 있습니다 .
<html ... xmlns:o="http://omnifaces.org/ui">
<o:importConstants type="com.example.YourConstants" />
이렇게하면 일반적인 Javabean 방식으로 #{YourConstants.FOO}
도 액세스 할 수 있습니다.
Javabean 스타일의 getter 메서드를 통해 반환하는 래퍼 클래스를 만듭니다.
먼저 상수의 존재를 스캔하고없는 경우 기본 해석기에 위임하고 그렇지 않으면 대신 상수 값을 반환하는 사용자 정의 EL 해석기를 만듭니다.
unstandard-taglib
프로젝트가 아직 살아 있습니까? 대안이 있습니까?
다음은 일반적으로 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"/>
일반적으로 이러한 종류의 상수 Configuration
는 서블릿 컨텍스트 의 객체 (게터 및 세터가 있음)에 배치하고 다음을 사용하여 액세스합니다.${applicationScope.config.url}
url
String 속성으로 클래스를 Configuration
만들고 이름을 지정하고 인스턴스화하고 url
원하는대로 설정합니다 . 그 후 해당 Configuration
개체를 ServletContext
. 같은 무언가를 servletContext.setAttribute("config", config)
. 그리고 당신은 간다.
ServletContext
? 상수를 더 깔끔하게 분류 할 수 있다는 것뿐입니까? 예 : applicationScope.config.url
대 applicationScope.url
.
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의 전체 코드
나는 다음과 같이 구현했다.
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}
처음에 내 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에서 상수를 직접 정의하고 싶을 때도 질문이 올라갑니다.
<%=URI%>
: P
<%=URI%>
이 작동하지 않는 곳 이 있었지만이 기술은 작동했습니다.
그래 넌 할수있어. 사용자 정의 태그가 필요합니다 (다른 곳에서 찾을 수없는 경우). 나는 이것을했다 :
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를 작성할 필요가 없습니다!
할 수 있습니다. 방법을 따르십시오
#{T(com.example.Addresses).URL}
TomCat 7 및 java6에서 테스트 됨
조금 늦게 알고 심지어 이것이 약간의 해킹이라는 것을 알고도-원하는 결과를 얻기 위해 다음 솔루션을 사용했습니다. 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의 동등성. 나는 이것이 어떤 관습에서 벗어난 것을 알고 있지만 완벽하게 잘 작동합니다.
@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);
}
}
정확히 원하는 것은 아니지만 아주 최소한의 방법으로 스크립틀릿을 터치하여 거의 동일하게 활성화 할 수있는 해결 방법이 있습니다. 스크립틀릿을 사용하여 값을 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>