try-catch在JSP与Servlet中仅捕获单次HTTP请求处理过程中doGet/doPost等方法内Java代码抛出的运行时异常,不捕获HTTP状态码、初始化异常、JSP编译错误及异步任务异常。

在JSP与Servlet体系中,try-catch的捕获边界不是由语法决定的,而是由**执行阶段、调用栈位置和容器生命周期**共同划定的。它不负责拦截HTTP协议错误(如404、500响应码本身),也不捕获JSP编译失败或Servlet初始化异常(这些发生在请求处理之前),而是聚焦于**单次HTTP请求处理过程中,Java业务代码运行时抛出的异常**。
捕获范围:仅限于doGet/doPost等方法内的运行时异常
Servlet中,只有在service()、doGet()、doPost()等请求处理方法内部执行的Java代码所抛出的异常,才能被该方法内的try-catch捕获。例如:
- 数据库查询时抛出SQLException → 可被捕获
- JSON解析失败抛出JSONException → 可被捕获
- 空指针调用导致NullPointerException → 可被捕获
- 但Servlet.init()中抛出的异常 → 不在此处捕获,会由容器记录并标记Servlet加载失败
JSP中的特殊性:脚本片段有效,表达式与声明无效
JSP页面中,只有<% ... %>脚本片段(scriptlet)内的代码可被try-catch包裹;而<%= ... %>表达式和<%! ... %>声明部分无法直接加try-catch:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
-
<% try { out.print(10/0); } catch(ArithmeticException e) { out.print("除零错误"); } %>→ 有效 -
<%= 10/0 %>→ 编译期转为service()方法内代码,但无法在表达式里写catch,错误会向上抛到Servlet层 - JSP转换成Servlet后,所有脚本片段最终都落在_jspService()方法中,因此其try-catch作用域等同于该方法体
边界之外:容器接管的几类典型异常
以下异常即使写了try-catch也大概率无法拦截,因为它们发生在更外层或不同阶段:
立即学习“Java免费学习笔记(深入)”;
- 受检异常未声明或未处理:比如在doGet()中调用throws IOException的方法,却没用try-catch或throws声明 → 编译失败,根本不会部署
- Filter或Listener抛出的异常:若过滤器中发生未捕获异常,请求甚至不会到达Servlet,容器直接返回500
- 异步任务中的异常:在Servlet中启用了线程池或CompletableFuture,其回调里的异常不在主线程try-catch范围内
- JSP编译异常:如EL表达式语法错误、标签库引用缺失 → 在翻译为.java阶段报错,不进入运行时捕获流程
最佳实践:分层防御,避免越界捕获
真正健壮的做法不是靠一层try-catch兜底,而是按责任分层:
- 在DAO层用try-catch捕获SQLException,并转换为自定义业务异常
- 在Service层做逻辑校验(if判断),只对不可控外部调用(如HTTP客户端、文件读写)用try-catch
- 在Servlet或Controller层统一捕获业务异常,设置响应状态码与友好提示,而非让异常穿透到容器默认错误页
- JSP中尽量避免复杂逻辑,把异常处理前移到后端,JSP只做安全的数据展示(如用JSTL <c:catch>作极简兜底,非主流方案)

















