You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让JSP表达式语言(EL)在表达式无效时抛出明确错误

JSP EL无效表达式抛异常配置方法

默认JSP EL采用容错设计:当表达式中的标识符找不到、对象不存在对应属性、类型转换失败时,不会抛出异常,只会返回null,页面渲染时null会被输出为空串,这就是你测试时只看到"Hello,"的原因。

可以通过以下配置关闭容错机制,让错误直接抛出:

1. Tomcat容器全局配置(最常用)

修改Tomcat目录下conf/catalina.properties,增加以下配置项:

# 解析不到bean/属性时直接抛出PropertyNotFoundException,不返回null
org.apache.el.BeanELResolver.IGNORE_PROPERTY_NOT_FOUND=false
# 类型转换失败时抛出异常,不返回0、false这类默认值
org.apache.el.parser.COERCE_TO_ZERO=false

修改后重启Tomcat即可全局生效,所有EL写错变量名、属性名的情况都会直接抛出明确异常,堆栈里会标注出错的EL表达式位置和找不到的属性/变量名。

2. 应用级配置

在你项目的WEB-INF/web.xml中添加JSP配置,确保EL没有被全局禁用:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!-- 其他现有配置 -->
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.jsp</url-pattern>
            <el-ignored>false</el-ignored>
        </jsp-property-group>
    </jsp-config>
</web-app>

如果是单个JSP页面需要单独控制EL开关,可以在页面顶部加page指令:

<%@ page isELIgnored="false" %>

3. 跨容器通用方案

如果你使用的是Jetty、Undertow等其他Servlet容器,没有提供上述配置开关,可以自定义一个ELResolver实现,在解析对象/属性返回null时主动抛出异常,再将该解析器注册到应用的EL上下文即可,这种方案不依赖特定容器,所有符合Servlet规范的容器都能生效。


Form Bean名称确定规则

JSP EL本身没有"form bean"的内置概念,所有能在EL里访问的对象,都是存放在四大作用域(page、request、session、application)中的属性,EL会按照作用域从小到大依次查找匹配名称的属性,名称的确定规则如下:

  • 手动存入作用域的对象:名称完全和你调用setAttribute(key, value)时传入的key一致。比如你在Servlet里写request.setAttribute("loginForm", formObj),EL里就用${loginForm.xxx}访问,key是什么就写什么。
  • Spring MVC自动暴露的对象:默认规则是类名首字母小写,比如类名是UserRegisterForm,默认名称就是userRegisterForm;如果类名前两个字母连续大写(比如OSSConfigForm),名称和类名一致为OSSConfigForm。如果用@ModelAttribute("customName")指定了名称,就用你指定的customName访问。
  • Struts2框架的对象:框架会自动把Action的属性、ModelDriven的模型对象压入值栈,EL访问时不需要加bean前缀,直接写${propertyName}就能取到对应属性。

如果不确定当前页面有哪些可访问的bean,可以临时在JSP页面加以下调试代码,运行后会列出所有作用域内的合法属性名,直接对着用就不会写错:

<%
out.println("<h3>Page域属性:</h3>");
java.util.Enumeration<String> pageAttrs = pageContext.getAttributeNamesInScope(PageContext.PAGE_SCOPE);
while(pageAttrs.hasMoreElements()) out.println(pageAttrs.nextElement() + "<br>");

out.println("<h3>Request域属性:</h3>");
java.util.Enumeration<String> reqAttrs = request.getAttributeNames();
while(reqAttrs.hasMoreElements()) out.println(reqAttrs.nextElement() + "<br>");

out.println("<h3>Session域属性:</h3>");
java.util.Enumeration<String> sessionAttrs = session.getAttributeNames();
while(sessionAttrs.hasMoreElements()) out.println(sessionAttrs.nextElement() + "<br>");

out.println("<h3>Application域属性:</h3>");
java.util.Enumeration<String> appAttrs = application.getAttributeNames();
while(appAttrs.hasMoreElements()) out.println(appAttrs.nextElement() + "<br>");
%>

你最开始写的formBeanBame本身就是其他示例里的占位符,还有拼写错误(Bame应为Name),你没有手动存入对应名称的对象,自然是取不到的。


内容的提问来源于stack exchange,提问作者Ian Boyd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 17:25:32