Spring MVC 中的统一异常处理

文章目录

  • [Spring MVC 中的统一异常处理](#Spring MVC 中的统一异常处理)
    • [Spring MVC 中跳转自定义 404 页面的两种常见方式](#Spring MVC 中跳转自定义 404 页面的两种常见方式)
      • [在 web.xml 中指定自定义的 404 页面](#在 web.xml 中指定自定义的 404 页面)
      • [提供一个匹配 * 的 Controller 请求处理方法](#提供一个匹配 * 的 Controller 请求处理方法)
    • [使用 @ExceptionHandler 注解](#使用 @ExceptionHandler 注解)
    • [使用 @ControllerAdvice + @ExceptionHandler 注解](#使用 @ControllerAdvice + @ExceptionHandler 注解)
      • 使用示例
      • [控制生效的 Controller 范围](#控制生效的 Controller 范围)

Spring MVC 中的统一异常处理

Spring MVC 中跳转自定义 404 页面的两种常见方式

在 web.xml 中指定自定义的 404 页面

xml 复制代码
<error-page>
  <error-code>404</error-code>
  <location>/WEB-INF/jsp/404.jsp</location>
</error-page>

提供一个匹配 * 的 Controller 请求处理方法

java 复制代码
// 凡是不能精确匹配的 url,都会由这个请求处理方法处理
@RequestMapping("*")
public String error404() {
    return "404";
}

使用 @ExceptionHandler 注解

@ExceptionHandler 注解用于标注于某个 Controller 的方法上,例如:

java 复制代码
@Controller      
public class GlobalController {               

    /**    
     * 用于处理异常的
     */      
    @ExceptionHandler({AException.class, BException.class, ...})       
    public String exception(MyException e) {    
        ...
    }

    @RequestMapping("test1")       
    public void test2() {
        ...
    }
    
    @RequestMapping("test2")       
    public void test2() {
        ...
    }
}

当 Controller 的请求方法发生指定异常时,@ExceptionHandler 所标注的方法将会被执行。返回给服务器的数据也就由该方法的返回值决定。

@ExceptionHandler 所标注的方法的常见参数有以下几种:

  • 一个异常参数。代表所发生的异常(最常用)

  • HttpServletRequest / HttpServletResponse 对象

  • HttpSession 对象

  • Model 对象

  • 等等。

@ExceptionHandler 所标注的方法的返回值的类型支持:

  • ModelAndView 对象(最常用)

  • Model 对象

  • Map 对象

  • View 对象

  • 被解析成一个视图名称的 String 值(次常用)

  • 等等

另外,可以将 @ResponseStatus@ExceptionHandler 结合使用,来定义 HTTP 响应的响应状态。

可以看到,这种方式最大的缺陷就是不能全局控制异常。每个类都要写一遍。

使用 @ControllerAdvice + @ExceptionHandler 注解

@ExceptionHandler 需要进行异常处理的方法必须与出错的方法在同一个 Controller 里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个 controller 中了。

这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。

使用示例

请确保此 WebExceptionHandle 类能被扫描到并装载进 Spring 容器中。由于标注了 @ControllerAdvice 注解,在开启了包扫描的情况下,Spring 会创建该类的单例对象。

java 复制代码
@Slf4j
@ControllerAdvice(assignableTypes = FirstController.class)
public class FirstControllerExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    public String demo1(Exception e) {
        log.warn("IllegalArgumentException");
        return "";
    }

    @ExceptionHandler(NullPointerException.class)
    public String demo(Exception e) {
        log.warn("NullPointerException");
        return "";
    }
}

上述方法中的参数对象就是 Controller 层抛出的异常对象。注意,该方法如果有第二个参数,那么该机制会失效,无法捕获-处理 Controller 抛出的异常!

控制生效的 Controller 范围

注意到,我是这样编写注解的:

java 复制代码
@ControllerAdvice(assignableTypes = { FirstController.class })

它用来限定这些异常处理函数起作用的 Controller 的范围。如果不写,则默认对所有 Controller 有效。

这也是 ControllerAdvice 进行统一异常处理的优点,它能够细粒度的控制该异常处理器针对哪些 Controller 有效,这样的好处是:

  1. 一个系统里就能够存在不同的异常处理器,Controller 也可以有选择的决定使用哪个,更加灵活。

  2. 不同的业务模块可能对异常处理的方式不同,通过该机制就能做到。

  3. 设想一个一开始并未使用全局异常处理的系统,如果直接引入全局范围内生效的全局异常处理,势必可能会改变已有 Controller 的行为,有侵入性。

    也就是说,如果不控制生效范围,即默认对所有 Controller 生效。如果控制生效范围,则默认对所有 Controller 不生效,降低侵入性。

ControllerAdvice 支持的限定范围:

  1. 按注解:@ControllerAdvice(annotations = RestController.class)

  2. 按包名:@ControllerAdvice("org.example.controllers")

  3. 按类型:@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})

相关推荐
ZC跨境爬虫1 分钟前
LeetCode 13. 罗马数字转整数(多解法详解 + Java Python 实现)
java·python·leetcode
省长7 分钟前
Sa-Token v1.46.0 发布 🚀,来看看有没有令你心动的功能!
java·后端·开源
LayZhangStrive31 分钟前
融360 一面
java·面试·后端开发
城管不管1 小时前
重生——第十次面试之开源中国一面挂
java·linux·开发语言·算法·面试·职场和发展·开源
Java小白笔记1 小时前
Windows系统免软件命令激活
java·网络·人工智能·windows·ai·ai编程
爱敲键盘的猴子1 小时前
深入理解 Java HashMap
java·hashmap
霸道流氓气质1 小时前
Java开发者AI编程常用MCP、Skills、Rules全景汇总
java·开发语言·ai编程
天涯醉青楼1 小时前
Spring Boot 接口返回 Bean 时字段名“变形”的深度剖析与解决方案
java
小小龙学IT2 小时前
Qt 模型/视图框架(Model/View)深度解析:从 MVC 演化到数据展示架构的王者
qt·架构·mvc
步行cgn2 小时前
MyBatis 高级映射与延迟加载完全指南
java·tomcat·mybatis