在JSP EL中,枚举值始终为空。

8
尝试使用EL条件时,我发现枚举值完全被忽略了。这对我来说似乎与规范相反。
<c:out value='${com.foobar.data.BookingStatus.FAILED}' />
<c:out value='${BookingStatus.FAILED}' />
<c:out value='${com.foobar.data.BookingStatus.failed}' />
<c:out value='${BookingStatus.failed}' />
<c:if test="${empty BookingStatus.FAILED }">empty</c:if>

令我惊讶的是,这些都被评估为。为什么Enum类没有被识别? 这在当前稳定的Tomcat实例中发生。
这可能是一个类路径问题吗?该Enum在控制器代码中成功使用,但在JSP中的其他地方没有使用。它在部署的lib目录中提供了一个jar。
更新: 我的意图是将提供的整数与Enum的属性进行比较,如下所示:
<c:when test='${bookingInformation.bookingStatus eq BookingStatus.FAILED.code}'>
    FOOBARFAIL
</c:when>

很遗憾,被检查的值无法更改,将保持为整数。该枚举如下(简化):

public enum BookingStatus {

    COMPLETED(0), FAILED(1);

    private final int code;

    private BookingStatus(int code) {
        this.code = code;
    }

    public int getCode() {
        return code;
    }

}

我希望避免硬编码“FAIL”等整数值,而是使用枚举进行比较。

https://dev59.com/H3VD5IYBdhLWcg3wAGiD - jmj
1
不是这样的。我的问题不在于条件,而是枚举对象本身无法访问,它是空的/ null。就好像Tomcat根本看不到枚举类一样。 - sibidiba
3个回答

17

这是因为当前版本的EL不支持访问枚举或调用枚举常量,此支持仅在EL 3.0中可用。

不清楚您的意图是什么,但需要知道的是,在EL中可以将枚举属性作为String进行比较。它们被解析为String

假设您有一个看起来像这样的bean:

public class Booking {
    public enum Status { NEW, PROGRESS, SUCCESS, FAILED }

    private Status status;

    public Status getStatus() {
        return status;
    }
}

你可以按照以下方式测试Status.FAILED条件:

<c:if test="${booking.status == 'FAILED'}">
    Booking status is FAILED.
</c:if>

另请参阅:


问题在于我正在与一个整数进行比较,这个整数是枚举的序数值,而不是另一个枚举。我能否在EL中将整数转换为枚举? - sibidiba
2
请勿使用序数。使用完整的枚举值。您的 getStatus() 必须返回 Status 而不是 int。这是设计不良模型的迹象。序数不是常量。每当您添加/删除/重新排列枚举值时,它们可能会更改。这听起来很像您正在以(糟糕的)解决方法的方式来保存 Java 枚举在/从数据库中。这是一个不同的主题。 - BalusC
2
不支持EL。它只支持Javabeans,如Javabeans规范所述。您可以添加一个getter来返回状态的所有值,但这很笨拙。您必须在不同的级别上解决此问题:即不使用序数,而是使用枚举。 - BalusC
1
不仅仅是枚举类型。EL不支持通过完全限定类名访问类,也不支持访问公共静态常量等等。但是说EL很糟糕就太过分了。这根本不是EL的设计意图。它是围绕着JavaBeans规范设计的。当您想在EL中使用非JavaBeans时,最好的方法是在模型中添加另一个getter来执行所需的操作。 - BalusC
我认为EL的规范限制过于严格。更糟糕的是,它鼓励新手使用脚本片段,这是可怕的,因为这些片段根本不会对他们进行任何限制,将业务逻辑混杂在JSP中。EE6带来了一些新的功能来解决这个问题,比如函数调用。最终,您将能够访问Java标准库中不符合JavaBean规范的属性! - sibidiba
显示剩余2条评论

7

正如BalusC所指出的,你不能使用EL访问枚举,但是你可以这样做:

<c:set var="enumFailed" value="<%=BookingStatus.FAILED%>"/>

<c:if test="${enumFailed.code == bookingInformation.bookingStatus}">
    ...
</c:if>

如果bookingInformation.bookingStatus是一个枚举而不是int类型,那就太理想了。但是如果由于你的应用程序具有传统性质而无法进行重构,那么上面的例子应该会有所帮助。你需要为枚举的每个值都使用<c:set/>(在你的示例中似乎只有两个值)。

1
您需要在JSP页面中导入枚举类。只要导入了它,就可以引用它。我在下面写了一个例子。
我的枚举是WebSettingType。
public enum WebSettingType {

    SMTP_HOSTNAME("smtp_hostname"),
    SMTP_PORT("smtp_port"),
    SMTP_USERNAME("smtp_username");
    private final String value;

    private WebSettingType(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}

我有一个websettings.jsp页面,它使用了标签页等。
<%@page import="my.package.WebSettingType"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="t" tagdir="/WEB-INF/tags" %>

<t:admin>
    <jsp:attribute name="css">
    </jsp:attribute>
    <jsp:attribute name="content">
        <input type="text" name="${WebSettingType.SMTP_HOSTNAME.getValue()}"/>
    </jsp:attribute>
</t:admin>

1
在问题被提出的日期,这在EL中尚不受支持。请参阅当前接受的答案和相关的“参见”链接:https://dev59.com/qm865IYBdhLWcg3wnPya - BalusC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接