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
声明符合服务器支持的最新 servlet 版本。因此,如果使用声明为符合 Servlet 2.5 或更早版本的 web.xml
,则 Servlet 3.0+ 的任何功能都将不起作用。
另请注意,此功能仅在 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 和更早版本中是不可能的。有几种选择:
将它们放入您放入应用程序范围的 Map
以下内容通常不适用于 EL,而仅适用于 SpEL(Spring EL)(在 Tomcat 7 上使用 3.2.2.RELEASE 测试)。我认为这里值得一提,以防有人搜索 JSP 和 EL(但将 JSP 与 Spring 结合使用)。
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<spring:eval var="constant" expression="T(com.example.Constants).CONSTANT"/>
您通常将这些类型的常量放在 servlet 上下文中的 Configuration
对象(具有 getter 和 setter)中,并使用 ${applicationScope.config.url}
访问它们
url
作为字符串属性创建一个类,将其命名为 Configuration
,实例化它并将 url
设置为您喜欢的任何值。然后在 ServletContext
中设置该 Configuration
对象。执行类似 servletContext.setAttribute("config", config)
的操作。你去吧。
ServletContext
的属性之间有什么区别?只是你可以更整齐地对常量进行分类吗?例如:applicationScope.config.url
与 applicationScope.url
。
你不能。它遵循 Java Bean 约定。所以你必须有一个吸气剂。
我在一开始就在我的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%>
不起作用的地方,但这种技术可以。
我实施如下:
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}
在 EL 中无法访问静态属性。我使用的解决方法是创建一个将自身分配给静态值的非静态变量。
public final static String MANAGER_ROLE = 'manager';
public String manager_role = MANAGER_ROLE;
我使用 lombok 来生成 getter 和 setter,这样就很好了。你的 EL 看起来像这样:
${bean.manager_role}
https://rogerkeays.com/access-java-static-methods-and-constants-from-el 处的完整代码
是的你可以。您需要一个自定义标签(如果您在其他地方找不到它)。我已经这样做了:
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 名称索引的 Map 中,所以如果
public static final int MY_FIFTEEN = 15;
然后标签将把它包装在一个整数中,你可以在 JSP 中引用它:
<c:if test="${consts['MY_FIFTEEN'] eq 15}">
而且您不必编写吸气剂!
你可以。按照以下方式尝试
#{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;
...
}
}
可以在 java 中用作 PERMISSION.PAGE.SEE
来检索值 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();
}
}
最后,访问相同 Long
的 EL-Expression 变为: #{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);
}
}
有一个不完全是您想要的解决方法,但可以让您以非常简单的方式通过触摸 scriptlet 进行几乎相同的活动。您可以使用 scriptlet 将值放入 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>
不定期副业成功案例分享
unstandard-taglib
项目还活着吗?有其他选择吗?