如何在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:
-
把它们放在你放在应用程序范围内的
Map<String, Object>
中。 在EL中,映射值可以通过${map.key}
或${map['key.with.dots']}
通常的Javabean方式访问。 -
使用
<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方法。 -
使用Javaranch的CCC
<ccc:constantsMap>
描述在本文底部的某处。<%@ taglib uri="http://bibeault.org/tld/ccc" prefix="ccc" %> <ccc:constantsMap className="com.example.YourConstants" var="constants" />
这样,它们也可以通过
${constants.FOO}
来使用通常的Javabean方法。 -
如果您使用的是JSF2,那么您可以使用
<o:importConstants>
。<html ... xmlns:o="http://omnifaces.org/ui"> <o:importConstants type="com.example.YourConstants" />
这样,他们也可以通过
#{YourConstants.FOO}
来使用通常的Javabean方法。 -
创build一个包装类,通过Javabean风格的getter方法返回它们。
-
创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>