【问题标题】:In JSP EL enum value always empty [duplicate]在 JSP EL 枚举值中始终为空 [重复]
【发布时间】:2023-03-23 10:50:01
【问题描述】:

当试图让 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>

令我惊讶的是,这些都评估为 empty。为什么无法识别 Enum 类? 这发生在当前稳定的 Tomcat 实例中。

这可能是类路径问题吗? Enum 在控制器代码中成功使用,但在 JSP 中没有其他地方。它在部署的 lib 目录中的 jar 中提供。

更新:

我的目的是将提供的 Integer 与 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 等的整数值进行硬编码,而是使用枚举来进行比较。

【问题讨论】:

标签: java jsp enums jstl el


【解决方案1】:

这是因为当前版本的 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 中将整数转换为枚举吗?
  • 不要使用序数。使用完全值得的枚举值。您的 getStatus() 必须返回 Status 而不是 int。这是设计不良模型的标志。序数不是常数。每当您添加/删除/重新排列枚举值时,它们可能会发生变化。这听起来很像您这样做是一种(不好的)解决方法,以便能够将 Java 枚举保存到数据库中/从数据库中保存。那就另当别论了。
  • 再看你的回答,是不是说我在EL里基本不能使用公共枚举类了?
  • 没有。 EL 不支持。它只支持Javabeans spec 中描述的Javabeans。您可以添加一个返回所有状态值的 getter,但这很笨拙。你必须在不同的层次上解决这个问题:即不要使用序数,而是使用枚举。
  • 不仅仅是枚举。 EL 不支持通过完全限定的类名访问类,也不支持访问公共静态最终常量等。但说 EL 很烂也太过分了。这根本就不是 EL 的意图。它是围绕 Javabeans 规范设计的。当你想在 EL 中使用非 Javabeans 时,嗯......最好的办法是添加另一个 getter,它在模型中完成所需的工作。
【解决方案2】:

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

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

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

如果 bookingInformation.bookingStatus 是一个枚举而不是一个 int,那将是理想的,但如果由于其遗留性质而重构您的应用程序是不可能的,那么我上面的示例应该会有所帮助。对于枚举的每个值,您都需要一个 &lt;c:set/&gt;(在您的示例中似乎只有两个)。

【讨论】:

    【解决方案3】:

    你必须在你的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>
    

    【讨论】:

    • 在提出问题之日,EL 不支持此功能。另请参阅当前接受的答案及其“另请参阅”链接:stackoverflow.com/q/3732608
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    • 2011-01-15
    相关资源
    最近更新 更多