简体   繁体   English

使用EL和JSTL访问枚举值

[英]Access Enum value using EL with JSTL

I have an Enum called Status defined as such: 我有一个名为Status的枚举定义如下:

public enum Status { 

    VALID("valid"), OLD("old");

    private final String val;

    Status(String val) {
        this.val = val;
    }

    public String getStatus() {
        return val;
    }

}

I would like to access the value of VALID from a JSTL tag. 我想从JSTL标记访问VALID的值。 Specifically the test attribute of the <c:when> tag. 特别是<c:when>标记的test属性。 Eg 例如

<c:when test="${dp.status eq Status.VALID">

I'm not sure if this is possible. 我不确定这是否可行。

对字符串的简单比较:

<c:when test="${someModel.status == 'OLD'}">

If using Spring MVC, the Spring Expression Language (SpEL) can be helpful: 如果使用Spring MVC,Spring Expression Language(SpEL)可能会有所帮助:

<spring:eval expression="dp.status == T(com.example.Status).VALID" var="isValid" />
<c:if test="${isValid}">
   isValid
</c:if>

You have 3 choices here, none of which is perfect: 这里有3个选择,其中没有一个是完美的:

  1. You can use a scriptlet in the test attribute: 您可以在test属性中使用scriptlet:

    <c:when test="<%= dp.getStatus() == Status.VALID %>">

    This uses the enum, but it also uses a scriptlet, which is not the "right way" in JSP 2.0. 这使用了枚举,但它也使用了一个scriptlet,它不是JSP 2.0中的“正确方法”。 But most importantly, this doesn't work when you want to add another condition to the same when using ${} . 但最重要的是,当您when使用${}时想要为其添加另一个条件时,这不起作用。 And this means all the variables you want to test have to be declared in a scriptlet, or kept in request, or session ( pageContext variable is not available in .tag files). 这意味着您要测试的所有变量都必须在scriptlet中声明,或者保存在请求或会话中( pageContext变量在.tag文件中不可用)。

  2. You can compare against string: 你可以比较字符串:

    <c:when test="${dp.status == 'VALID'}">

    This looks clean, but you're introducing a string that duplicates the enum value and cannot be validated by the compiler. 这看起来很干净,但是您引入了一个复制枚举值的字符串,并且无法由编译器验证。 So if you remove that value from the enum or rename it, you will not see that this part of code is not accessible anymore. 因此,如果您从枚举中删除该值或重命名该值,您将不会再看到这部分代码不可访问。 You basically have to do a search/replace through the code each time. 您基本上每次都必须通过代码进行搜索/替换。

  3. You can add each of the enum values you use into the page context: 您可以将您使用的每个枚举值添加到页面上下文中:

    <c:set var="VALID" value="<%=Status.VALID%>"/>

    and then you can do this: 然后你可以这样做:

    <c:when test="${dp.status == VALID}">

I prefer the last option (3), even though it also uses a scriptlet. 我更喜欢最后一个选项(3),即使它也使用了一个scriptlet。 This is because it only uses it when you set the value. 这是因为它仅在您设置值时使用它。 Later on you can use it in more complex EL expressions, together with other EL conditions. 稍后,您可以在更复杂的EL表达式中使用它,以及其他EL条件。 While in option (1) you cannot use a scriptlet and an EL expression in the test attribute of a single when tag. 而在选项(1)你不能在使用一个scriptlet和EL表达test单个的属性when标记。

So to get my problem fully resolved I needed to do the following: 因此,要完全解决我的问题,我需要执行以下操作:

<% pageContext.setAttribute("old", Status.OLD); %>

Then I was able to do: 然后我就能做到:

<c:when test="${someModel.status == old}"/>...</c:when>

which worked as expected. 这按预期工作。

Here are two more possibilities: 这里有两种可能性:

JSP EL 3.0 Constants JSP EL 3.0常量

As long as you are using at least version 3.0 of EL, then you can import constants into your page as follows: 只要您使用至少3.0版本的EL,就可以将常量导入页面,如下所示:

<%@ page import="org.example.Status" %>
<c:when test="${dp.status eq Status.VALID}">

However, some IDEs don't understand this yet (eg IntelliJ ) so you won't get any warnings if you make a typo, until runtime. 但是,有些IDE还没有理解这一点(例如IntelliJ ),所以如果你输入错误,你就不会收到任何警告,直到运行时。

This would be my preferred method once it gets proper IDE support. 一旦获得适当的IDE支持,这将是我的首选方法。

Helper Methods 助手方法

You could just add getters to your enum. 你可以在你的枚举中添加getter。

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

Then in your JSP: 然后在你的JSP中:

<c:when test="${dp.status.valid}">

This is supported in all IDEs and will also work if you can't use EL 3.0 yet. 这在所有IDE中都受支持,如果您还不能使用EL 3.0,也可以使用它。 This is what I do at the moment because it keeps all the logic wrapped up into my enum. 这就是我现在所做的,因为它将所有逻辑都包含在我的枚举中。

Also be careful if it is possible for the variable storing the enum to be null. 如果存储枚举的变量可能为null,也要小心。 You would need to check for that first if your code doesn't guarantee that it is not null: 如果您的代码不保证它不为null,您需要首先检查它:

<c:when test="${not empty db.status and dp.status.valid}">

I think this method is superior to those where you set an intermediary value in the JSP because you have to do that on each page where you need to use the enum. 我认为这种方法优于那些在JSP中设置中间值的方法,因为您必须在需要使用枚举的每个页面上执行此操作。 However, with this solution you only need to declare the getter once. 但是,使用此解决方案,您只需要声明一次getter。

For this purposes I do the following: 为此,我执行以下操作:

<c:set var="abc">
    <%=Status.OLD.getStatus()%>
</c:set>

<c:if test="${someVariable == abc}">
    ....
</c:if>

It's looks ugly, but works! 它看起来很难看,但很有效!

I do not have an answer to the question of Kornel, but I've a remark about the other script examples. 我对Kornel的问题没有答案,但我对其他脚本示例有一个评论。 Most of the expression trust implicitly on the toString() , but the Enum.valueOf() expects a value that comes from/matches the Enum.name() property. 大多数表达式隐式地信任toString() ,但Enum.valueOf()需要一个来自/匹配Enum.name()属性的值。 So one should use eg: 所以应该使用例如:

<% pageContext.setAttribute("Status_OLD", Status.OLD.name()); %>
...
<c:when test="${someModel.status == Status_OLD}"/>...</c:when>

Add a method to the enum like: 在枚举中添加一个方法,如:

public String getString() {
    return this.name();
}

For example 例如

public enum MyEnum {
    VALUE_1,
    VALUE_2;
    public String getString() {
        return this.name();
    }
}

Then you can use: 然后你可以使用:

<c:if test="${myObject.myEnumProperty.string eq 'VALUE_2'}">...</c:if>

When using a MVC framework I put the following in my controller. 使用MVC框架时,我将以下内容放入我的控制器中。

request.setAttribute(RequestParameterNamesEnum.INBOX_ACTION.name(), RequestParameterNamesEnum.INBOX_ACTION.name());

This allows me to use the following in my JSP Page. 这允许我在JSP页面中使用以下内容。

<script> var url = 'http://www.nowhere.com/?${INBOX_ACTION}=' + someValue;</script>

It can also be used in your comparison 它也可以用于比较

<c:when test="${someModel.action == INBOX_ACTION}">

Which I prefer over putting in a string literal. 我更喜欢放入字符串文字。

<%@ page import="com.example.Status" %>

1. ${dp.status eq Title.VALID.getStatus()}
2. ${dp.status eq Title.VALID}
3. ${dp.status eq Title.VALID.toString()}
  • Put the import at the top , in JSP page header 将导入放在JSP页面标题的顶部
  • If you want to work with getStatus method , use #1 如果要使用getStatus方法 ,请使用#1
  • If you want to work with the enum element itself, use either #2 or #3 如果您想使用枚举元素本身,请使用#2或#3
  • You can use == instead of eq 您可以使用==而不是eq

I generally consider it bad practice to mix java code into jsps/tag files. 我通常认为将java代码混合到jsps / tag文件中是不好的做法。 Using 'eq' should do the trick : 使用'eq'可以做到这一点:

<c:if test="${dp.Status eq 'OLD'}">
  ...
</c:if>

I do it this way when there are many points to use... 当有很多要点时,我会这样做...

public enum Status { 

    VALID("valid"), OLD("old");

    private final String val;

    Status(String val) {
        this.val = val;
    }

    public String getStatus() {
        return val;
    }

    public static void setRequestAttributes(HttpServletRequest request) {
        Map<String,String> vals = new HashMap<String,String>();
        for (Status val : Status.values()) {
            vals.put(val.name(), val.value);
        }
        request.setAttribute("Status", vals);
    }

}

JSP JSP

<%@ page import="...Status" %>
<% Status.setRequestAttributes(request) %>

<c:when test="${dp.status eq Status.VALID}">
...

In Java Class: 在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
}

So now POJO and enum obj is created. 所以现在创建了POJO和enum obj。 Now EnumTest you will set in session object using in the servlet or controller class session.setAttribute("enumTest", EnumTest ); 现在,您将在servlet或控制器类session.setAttribute(“enumTest”,EnumTest)中使用EnumTest设置会话对象;

In JSP Page 在JSP页面中

<c:if test="${enumTest.statusobj == 'ACTIVE'}">

//TRUE??? THEN PROCESS SOME LOGIC

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM