如何在EL中引用常量?

如何在JSP页面上引用EL常量?

我有一个接口Addresses与一个常量命名的URL 。 我知道我可以参考一个scriplet: <%=Addresses.URL%> ,但我怎么做这个使用EL?

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 +可以工作。

这个工具只能在JSP中使用,而不能在Facelets中使用。 在JSF + Facelets的情况下,最好的方法是使用OmniFaces <o:importConstants> ,如下所示:

 <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和更旧版本中这是不可能的。 有几个select:

  1. 把它们放在你放在应用程序范围内的Map<String, Object>中。 在EL中,映射值可以通过${map.key}${map['key.with.dots']}通常的Javabean方式访问。

  2. 使用<un:useConstants> taglib (maven2 repo here )的<un:useConstants>

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

    这样他们就可以通过${constants.FOO}来使用通常的Javabean方法。

  3. 使用Javaranch的CCC <ccc:constantsMap>描述在本文底部的某处。

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

    这样,它们也可以通过${constants.FOO}来使用通常的Javabean方法。

  4. 如果您使用的是JSF2,那么您可以使用<o:importConstants>

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

    这样,他们也可以通过#{YourConstants.FOO}来使用通常的Javabean方法。

  5. 创build一个包装类,通过Javabean风格的getter方法返回它们。

  6. 创build一个自定义的ELparsing器,它首先扫描常量的存在,如果不存在,则委托给默认的parsing器,否则返回常量值。

您通常将这些常量放置在Servlet上下文中的Configuration对象(具有getter和setter)中,并使用${applicationScope.config.url}访问它们

以下内容通常不适用于EL,而仅适用于SpEL(Spring EL)(在Tomcat 7上使用3.2.2.RELEASE进行testing)。 我想在这里值得一提的是,如果有人searchJSP和EL(但使用JSP与Spring)。

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

你不能。 它遵循Java Bean约定。 所以你必须有一个吸气。

EL中无法访问静态属性。 我使用的解决方法是创build一个非静态variables,将其自身分配给静态值。

 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} 

是的你可以。 你需要一个自定义标签(如果你不能find其他地方)。 我已经这样做了:

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

所有公共静态最终variables将被放入一个由他们的Java名称索引的Map中,所以如果

 public static final int MY_FIFTEEN = 15; 

那么这个标签就会把它包装在一个Integer中,你可以在JSP中引用它:

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

而且你不必写getters!

您可以。 试着按照下面的方法

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

testingTomCat 7和java6

我在开始时在我的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> 

现在,我可以稍后使用它。 这里是一个例子,其中的值只是为了debugging而写成HTML注释:

 <!-- ${URI} --> 

用你的常量类,你可以导入你的类,并将常量分配给局部variables。 我知道我的答案是一种快速的黑客攻击,但当JSP想直接定义常量时,这个问题也会出现问题。

即使知道它有点晚,甚至知道这是一个小黑客 – 我使用以下解决scheme,以达到预期的结果。 如果你是Java命名约定的爱好者,我的build议是停止阅读这里…

有这样一个类,定义常量,按空类分组创build一种层次结构:

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

可以从java内部用作PERMISSION.PAGE.SEE来检索值1L

为了在ELexpression式中获得一个类似的访问可能性,我做了这个:(如果有一个编码神 – 他希望可以原谅我: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(); } } 

最后,ELexpression式访问相同的Long变成: #{PERMISSION.PAGE.SEE} – 对Java和EL-Access的平等。 我知道这是出于任何惯例,但它工作得很好。

@Bozho已经提供了一个很好的答案

您通常将这些常量放置在Servlet上下文中的configuration对象(具有getter和setter)中,并使用$ {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); } } 

有一个解决方法,不完全是你想要的,但让你活动几乎相同的触摸scriptlets在一个相当小的方式。 您可以使用scriptlet将值放入JSTLvariables中,稍后在页面中使用干净的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>