【SpringMVC笔记】 - 9 - 异常处理器

SpringMVC 笔记 - 9 - 异常处理器

一、异常处理器的核心概念

在 SpringMVC 框架中,控制器(Controller)的处理器方法执行过程中,可能因参数错误、业务逻辑异常、IO 异常等各种原因抛出异常。如果不做特殊处理,异常会直接暴露给前端,既不友好也可能泄露系统敏感信息。

异常处理器(HandlerExceptionResolver) 是 SpringMVC 提供的异常处理核心接口,专门用于统一拦截、处理处理器方法执行过程中抛出的异常。

核心作用(一句话概括):拦截处理器方法执行时抛出的异常,通过预设的逻辑跳转到指定视图,并向前端展示友好的异常提示信息,避免原始异常直接暴露。

核心接口与方法

SpringMVC 通过HandlerExceptionResolver接口定义异常处理的规范,其核心方法为:

java 复制代码
ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
  • 参数说明:

    • request/response:当前请求和响应对象;
    • handler:抛出异常的处理器(Controller 方法);
    • ex:捕获到的异常对象。
  • 返回值:ModelAndView,指定异常处理完成后跳转的视图名称,以及需要传递到视图的异常数据。

二、异常处理器的两大默认实现

SpringMVC 为HandlerExceptionResolver提供了两个常用的默认实现类,分别对应 "默认异常处理" 和 "自定义异常处理" 场景。

1. DefaultHandlerExceptionResolver(默认异常处理器)

这是 SpringMVC 内置的默认异常处理器,无需手动配置,框架会自动启用。

核心特性
  • 针对 SpringMVC 框架自身的常见异常(如请求方式不匹配、参数绑定失败、视图找不到等)进行标准化处理;
  • 例如:当前端发送POST请求,但处理器方法仅支持GET请求时,该处理器会捕获RequestMethodNotSupportedException,并返回 405(Method Not Allowed)状态码;
  • 优先级高于自定义异常处理器(若未手动调整优先级);
  • 缺点:仅处理框架内置异常,无法灵活适配业务自定义异常,且提示信息固定,无法自定义前端展示视图。

2. SimpleMappingExceptionResolver(自定义异常处理器)

这是开发中最常用的自定义异常处理器实现类,支持通过配置灵活指定 "异常类型 - 跳转视图" 的映射关系,还能将异常对象传递到视图层展示。

核心优势
  • 支持按异常类型(如NullPointerExceptionException等)指定不同的跳转视图;
  • 可将异常对象存入 Request 域,供前端页面展示自定义提示;
  • 支持调整优先级,覆盖默认异常处理器的逻辑。

三、自定义异常处理器的实现方式

SpringMVC 提供两种主流方式配置SimpleMappingExceptionResolver:XML 配置文件方式、注解方式。

方式 1:XML 配置文件(springmvc.xml)

通过 SpringMVC 的 XML 配置文件声明SimpleMappingExceptionResolver Bean,适用于传统 XML 配置的项目。

完整配置示例(结合实战代码)
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 组件扫描:确保Controller被Spring管理 -->
    <context:component-scan base-package="com.zzz"/>

    <!-- 视图解析器:配置Thymeleaf模板解析(需配合前端页面路径) -->
    <bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver">
        <property name="characterEncoding" value="UTF-8"/>
        <property name="order" value="1"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring6.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver">
                        <property name="prefix" value="/WEB-INF/templates/"/> <!-- 视图前缀 -->
                        <property name="suffix" value=".html"/> <!-- 视图后缀 -->
                        <property name="templateMode" value="HTML"/>
                        <property name="characterEncoding" value="UTF-8"/>
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

    <!-- 自定义异常处理器:SimpleMappingExceptionResolver -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <!-- 优先级:设置为-1,让自定义处理器优先级高于默认处理器(DefaultHandlerExceptionResolver) -->
        <!-- <property name="order" value="-1"/> -->
        <!-- 异常映射:key=异常全类名,value=跳转的视图名称 -->
        <property name="exceptionMappings">
            <props>
                <!-- 匹配所有Exception及其子类,跳转到tip视图 -->
                <prop key="java.lang.Exception">tip</prop>
                <!-- 可扩展:针对特定异常配置专属视图 -->
                <!-- <prop key="java.lang.NullPointerException">nullTip</prop> -->
                <!-- <prop key="com.zzz.exception.BusinessException">businessTip</prop> -->
            </props>
        </property>
        <!-- 异常对象存储:将异常存入Request域,key为"yiChang",供前端页面获取 -->
        <property name="exceptionAttribute" value="yiChang"/>
    </bean>

    <!-- 开启MVC注解驱动 -->
    <mvc:annotation-driven/>
    <!-- 静态资源处理 -->
    <mvc:default-servlet-handler/>
</beans>
关键配置说明
配置项 作用
order 异常处理器优先级,值越小优先级越高;默认处理器优先级为 0,自定义设为 - 1 可覆盖
exceptionMappings 异常类型与视图的映射关系,key 必须是异常的全类名(如java.lang.Exception
exceptionAttribute 将异常对象存入 Request 域的 key 名称,前端可通过该 key 获取异常信息

方式 2:注解方式(@ControllerAdvice + @ExceptionHandler)

基于注解的异常处理更灵活,无需 XML 配置,适用于注解驱动的现代 SpringMVC 项目。

完整实现示例(结合实战代码)
java 复制代码
package com.zzz.controller;

import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * 全局异常处理器(注解版)
 * @ControllerAdvice:标识这是一个全局控制器增强类,可拦截所有Controller的异常
 */
@ControllerAdvice // 核心注解:开启全局异常处理
public class ExceptionController {

    /**
     * 异常处理方法:@ExceptionHandler指定处理的异常类型
     * 方法参数:
     * - Exception e:捕获到的异常对象
     * - Model model:用于向视图传递数据(存入Request域)
     * 返回值:跳转的视图名称
     */
    @ExceptionHandler // 不指定异常类型时,默认处理所有Exception
    // @ExceptionHandler({NullPointerException.class, BusinessException.class}) // 精准处理指定异常
    public String handleException(Exception e, Model model) {
        // 将异常对象存入Model(最终传递到Request域),key为"yiChang"
        model.addAttribute("yiChang", e);
        // 跳转到tip视图(需配合视图解析器的前缀/后缀)
        return "tip";
    }
}
注解核心说明
注解 作用
@ControllerAdvice 全局控制器增强注解,可指定扫描的 Controller 包(如@ControllerAdvice(basePackages = "com.zzz.controller")
@ExceptionHandler 标注在方法上,指定该方法处理的异常类型(支持数组,如{Exception.class, NullPointerException.class}

前端视图展示异常信息(tip.html)

通过 Thymeleaf 模板引擎获取 Request 域中的异常对象,展示友好提示:

html 复制代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Tip</title>
</head>
<body>
    <!-- 友好提示 -->
    <h1>出错了,请联系管理员</h1>
    <hr>
    <!-- Thymeleaf表达式获取Request域中的异常对象(key为yiChang) -->
    <div th:text="${yiChang}"></div>
    <!-- 可扩展:展示异常详情(如堆栈信息) -->
    <!-- <div th:text="${yiChang.stackTrace}"></div> -->
    <!-- <div th:text="${yiChang.message}"></div> -->
</body>
</html>

四、异常处理器的执行流程

  1. 前端发送请求(如POST /index),DispatcherServlet 将请求分发到对应的 Controller 处理器方法(如IndexController.toIndex());
  2. 处理器方法执行过程中抛出异常(如空指针、请求方式不匹配等);
  3. DispatcherServlet 检测到异常,调用已配置的HandlerExceptionResolver异常处理器;
  4. 异常处理器按优先级执行(自定义处理器优先级高于默认处理器),根据exceptionMappings找到对应的跳转视图;
  5. 异常处理器将异常对象存入 Request 域(key 由exceptionAttribute指定),并返回ModelAndView
  6. 视图解析器(如 ThymeleafViewResolver)解析视图名称,跳转到指定的 HTML 页面;
  7. 前端页面通过 Thymeleaf 表达式获取异常信息,展示友好提示。

五、实战注意事项

1. 视图路径匹配

SpringMVC 的视图解析器配置了前缀(/WEB-INF/templates/)和后缀(.html),因此异常处理器中指定的视图名称(如tip)会被解析为/WEB-INF/templates/tip.html,需确保该文件存在。

2. 优先级调整

  • 默认情况下,DefaultHandlerExceptionResolver(默认处理器)优先级高于SimpleMappingExceptionResolver(自定义处理器);
  • 若需让自定义处理器优先执行,需给SimpleMappingExceptionResolver配置order属性(如order=-1)。

3. 注解方式与 XML 方式的兼容

  • 项目中可同时存在 XML 配置和注解配置的异常处理器,优先级由@Order(注解)或order(XML)决定;
  • 注解方式的@ControllerAdvice优先级默认高于 XML 配置的SimpleMappingExceptionResolver(可通过@Order调整)。

4. 异常信息的安全控制

  • 生产环境中,不建议直接展示完整的异常堆栈信息(避免泄露系统信息);
  • 可在异常处理器中对异常信息进行封装,仅向前端返回友好提示(如 "系统繁忙,请稍后重试"),详细异常日志通过log4j/slf4j记录到日志文件。

5. 扩展:自定义业务异常

开发中可自定义业务异常类,针对性处理不同业务场景的异常:

java 复制代码
// 自定义业务异常
public class BusinessException extends RuntimeException {
    private String code; // 异常码
    private String msg;  // 异常提示

    // 构造方法、getter/setter
}

// 注解版异常处理器扩展
@ControllerAdvice
public class ExceptionController {
    // 处理业务异常
    @ExceptionHandler(BusinessException.class)
    public String handleBusinessException(BusinessException e, Model model) {
        model.addAttribute("errorCode", e.getCode());
        model.addAttribute("errorMsg", e.getMsg());
        return "businessTip"; // 业务异常专属视图
    }

    // 处理通用异常
    @ExceptionHandler(Exception.class)
    public String handleException(Exception e, Model model) {
        model.addAttribute("yiChang", e);
        return "tip";
    }
}

六、两种实现方式的对比

实现方式 优点 缺点 适用场景
XML 配置方式 配置集中,无需修改代码 灵活性低,不支持复杂逻辑 传统 XML 配置项目、简单异常处理
注解方式 灵活度高,支持复杂业务逻辑 配置分散在代码中 注解驱动项目、复杂异常处理

七、总结

  1. 异常处理器是 SpringMVC 统一处理处理器方法异常的核心机制,核心接口为HandlerExceptionResolver
  2. DefaultHandlerExceptionResolver是默认处理器,处理框架内置异常;SimpleMappingExceptionResolver是自定义处理器,支持灵活配置;
  3. 自定义异常处理器有两种实现方式:XML 配置(适合简单场景)、注解(@ControllerAdvice + @ExceptionHandler,适合复杂场景);
  4. 异常处理器的核心价值是统一拦截异常、跳转友好视图、隐藏原始异常信息,提升用户体验和系统安全性。
相关推荐
DianSan_ERP2 小时前
淘宝订单接口集成中如何正确处理消费者敏感信息的安全与合规问题?
大数据·运维·网络·人工智能·安全·servlet
下地种菜小叶2 小时前
Spring Boot 2.x 升级 3.x / 4.x 怎么做?一次讲清 JDK、Jakarta、依赖兼容与上线策略
java·spring boot·后端
iiiiyu2 小时前
常用API(StringJoiner类 & Math类 & System类)
java·大数据·开发语言·数据结构·编程语言
有梦想的小何2 小时前
`Java并发排障实录:没有报错,却把正确数据覆盖错了`
java·spring boot·mysql·spring cloud
Xiu Yan2 小时前
Java 转 C++ 系列:函数对象、谓词和内建函数对象
java·开发语言·c++
那个失眠的夜2 小时前
Spring整合Mybatis实现用户的CRUD
java·spring·mybatis
superantwmhsxx2 小时前
Spring Initializr创建springboot项目,提示java 错误 无效的源发行版:16
java·spring boot·spring
山河梧念2 小时前
【保姆级教程】VMware虚拟机安装全流程
android·java·数据库
莫逸风2 小时前
【java-core-collections】红黑树深度解析
java·开发语言