使用EL与JSTL访问枚举值
我有一个名为状态的枚举定义如下:
public enum Status { VALID("valid"), OLD("old"); private final String val; Status(String val) { this.val = val; } public String getStatus() { return val; } }
我想从JSTL标签访问VALID
的值。 具体来说就是<c:when>
标签的test
属性。 例如
<c:when test="${dp.status eq Status.VALID">
我不确定这是否可能。
一个简单的对比string的作品:
<c:when test="${someModel.status == 'OLD'}">
如果使用Spring MVC,Springexpression式语言(SpEL)可能会有所帮助:
<spring:eval expression="dp.status == T(com.example.Status).VALID" var="isValid" /> <c:if test="${isValid}"> isValid </c:if>
你在这里有三个select,没有一个是完美的:
-
您可以在
test
属性中使用scriptlet:<c:when test="<%= dp.getStatus() == Status.VALID %>">
这使用枚举,但它也使用了一个scriptlet,这不是JSP 2.0中的“正确方法”。 但最重要的是,当你想
when
使用${}
when
添加另外一个条件的时候,这是行不通的。 这意味着你想testing的所有variables都必须在scriptlet中声明,或者保存在请求中,或者session(pageContext
variables在.tag
文件中不可用)。 -
你可以比较string:
<c:when test="${dp.status == 'VALID'}">
这看起来很干净,但是你引入了一个重复枚举值的string,不能被编译器validation。 因此,如果您从枚举中删除该值或将其重命名,则不会看到这部分代码无法再访问。 你基本上每次都必须通过代码进行search/replace。
-
您可以将每个使用的枚举值添加到页面上下文中:
<c:set var="VALID" value="<%=Status.VALID%>"/>
然后你可以这样做:
<c:when test="${dp.status == VALID}">
我更喜欢最后一个选项(3),即使它也使用scriptlet。 这是因为它只在设置值时使用它。 稍后,您可以将其用于更复杂的ELexpression式,以及其他EL条件。 在选项(1)中,不能在单个标签的test
属性中使用scriptlet和ELexpression式。
所以为了让我的问题完全解决,我需要做到以下几点:
<% pageContext.setAttribute("old", Status.OLD); %>
然后我能够做到:
<c:when test="${someModel.status == old}"/>...</c:when>
按预期工作。
为此,我做了以下几点:
<c:set var="abc"> <%=Status.OLD.getStatus()%> </c:set> <c:if test="${someVariable == abc}"> .... </c:if>
这看起来丑陋,但工作!
我对科尔内尔的问题没有一个答案,但是我对其他脚本例子有所评论。 大部分expression式都隐式地信任toString()
,但是Enum.valueOf()
需要一个来自/匹配Enum.name()
属性的值。 所以应该使用例如:
<% pageContext.setAttribute("Status_OLD", Status.OLD.name()); %> ... <c:when test="${someModel.status == Status_OLD}"/>...</c:when>
这里有两个更多的可能性:
JSP EL 3.0常量
只要你至less使用版本3.0的EL,那么你可以将常量导入到你的页面中,如下所示:
<%@ page import="org.example.Status" %> <c:when test="${dp.status eq Status.VALID}">
但是,有些IDE还不能理解这个(例如IntelliJ ),所以如果你input错误,你将不会得到任何警告,直到运行时。
一旦获得适当的IDE支持,这将是我的首选方法。
帮手方法
你可以添加getters到你的枚举。
public enum Status { VALID("valid"), OLD("old"); private final String val; Status(String val) { this.val = val; } public String getStatus() { return val; } public boolean isValid() { return this == VALID; } public boolean isOld() { return this == OLD; } }
然后在你的JSP中:
<c:when test="${dp.status.valid}">
这在所有的IDE中都是支持的,如果你还不能使用EL 3.0的话,它也可以工作。 这是我现在所做的,因为它保留了所有的逻辑包裹到我的枚举。
如果存储枚举的variables可能为空,也要小心。 如果您的代码不能保证它不为空,您需要首先检查:
<c:when test="${not empty db.status and dp.status.valid}">
我认为这种方法比在JSP中设置中间值的方法更好,因为您必须在需要使用枚举的每个页面上执行此操作。 但是,使用这个解决scheme,你只需要声明一次getter。
向enum添加一个方法,如:
public String getString() { return this.name(); }
例如
public enum MyEnum { VALUE_1, VALUE_2; public String getString() { return this.name(); } }
那么你可以使用:
<c:if test="${myObject.myEnumProperty.string eq 'VALUE_2'}">...</c:if>
当使用MVC框架时,我把以下内容放在我的控制器中。
request.setAttribute(RequestParameterNamesEnum.INBOX_ACTION.name(), RequestParameterNamesEnum.INBOX_ACTION.name());
这使我可以在我的JSP页面中使用以下内容。
<script> var url = 'http://www.nowhere.com/?${INBOX_ACTION}=' + someValue;</script>
它也可以用在你的比较中
<c:when test="${someModel.action == INBOX_ACTION}">
我更喜欢把一个string文字。
我通常认为将java代码混合到jsps / tag文件是一个糟糕的做法。 使用'eq'应该可以做到这一点:
<c:if test="${dp.Status eq 'OLD'}"> ... </c:if>
在Java类中:
public class EnumTest{ //Other property link private String name; .... public enum Status { ACTIVE,NEWLINK, BROADCASTED, PENDING, CLICKED, VERIFIED, AWARDED, INACTIVE, EXPIRED, DELETED_BY_ADMIN; } private Status statusobj ; //Getter and Setters }
所以现在POJO和枚举obj被创build。 现在, EnumTest将在会话对象中使用servlet或控制器类session.setAttribute(“enumTest”,EnumTest);
在JSP页面中
<c:if test="${enumTest.statusobj == 'ACTIVE'}"> //TRUE??? THEN PROCESS SOME LOGIC
- 什么是Class对象(java.lang.Class)?
- 当我将Firebase中的JSON转换为Java对象时,为什么会出现“无法popupinput”?
- 使用AsyncTask传递一个值
- 转换string(如testing123)转换为Java中的二进制文件
- 导入org.junit无法parsing
- 有没有像Java中的Environment.Newline在Java中定义的Newline常量?
- 在Spring Data REST中发布@OneToMany子资源关联
- GsonBuilder setDateFormat for“2011-10-26T20:29:59-07:00”
- Java – Common Gotchas