JSP 当end大于项大小时,JSTL c:forEach不引发IndexOutOfBoundException

kqhtkvqz  于 2023-02-17  发布在  其他
关注(0)|答案(1)|浏览(140)

我的工作是编辑用户和他们的通知邮件的简单形式。
用户可以有3封电子邮件(0至3)。虽然我创建3输入如下:

<%
    List<String> notifEmails = // some code to get user's emails
    pageContext.setAttribute("notifEmails", notifEmails);
%>
<c:forEach begin="0" end="2" var="index">
    <li>
        <label>adresse ${index + 1} :</label>
        <input type="email" value="${notifEmails[index]}">
    </li>
</c:forEach>

我很惊讶没有一个IndexOutOfBoundsException当我有一个用户在这个表达式${notifEmails[index]}少于3封电子邮件。我试图找到一些解释在网络上,但我发现没有关于这种情况。我想确保了解这里发生了什么。
有人知道原因吗?

n9vozmp4

n9vozmp41#

我需要大量的调试,但我找到了它。当你阅读规范时,EL是一种语言,它选择只有在没有可能的默认值可以替代时才抛出异常。在我的例子中,表达式${notifEmails[index]}ArrayELResolver在此方法中解析:

public Object getValue(ELContext context, Object base, Object property) {
    Objects.requireNonNull(context);

    if (base != null && base.getClass().isArray()) {
        context.setPropertyResolved(base, property);
        int idx = coerce(property);
        if (idx < 0 || idx >= Array.getLength(base)) {
            return null;
        }
        return Array.get(base, idx);
    }

    return null;
}

如果index不在数组的边界内,EL将返回null作为“我找不到该值”。
然后EL将null强制为String,并且在规范中必须将null强制为空字符串。

public static final String coerceToString(final ELContext ctx, final Object obj) {

    if (ctx != null) {
        boolean originalIsPropertyResolved = ctx.isPropertyResolved();
        try {
            Object result = ctx.getELResolver().convertToType(ctx, obj, String.class);
            if (ctx.isPropertyResolved()) {
                return (String) result;
            }
        } finally {
            ctx.setPropertyResolved(originalIsPropertyResolved);
        }
    }

    if (obj == null) {
        return "";
    } else if (obj instanceof String) {
        return (String) obj;
    } else if (obj instanceof Enum<?>) {
        return ((Enum<?>) obj).name();
    } else {
        return obj.toString();
    }
}

因此,该行为符合规范,属于正常行为。
(对不起,tomcat异常屏幕!:D)

相关问题