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})

相关推荐
方也_arkling6 小时前
【Java-Day08】static / final / 枚举
java·开发语言
橙淮6 小时前
Spring Bean作用域与生命周期全解析
java·spring
Chengbei116 小时前
一站式源码安全检测工具、云安全 / APP / 小程序源码敏感信息递归多层目录扫描AK、JWT、手机号、身份证等敏感信息
java·开发语言·安全·web安全·网络安全·系统安全·安全架构
llz_1126 小时前
web-第一次课后作业
java·开发语言·idea
秋96 小时前
Java项目运行5天左右自动宕机:系统性定位与解决方案
java·开发语言·python
小江的记录本7 小时前
【JVM虚拟机】垃圾回收GC:垃圾收集器:CMS:核心原理、回收流程、优缺点、废弃原因(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·spring·面试·maven
DIY源码阁7 小时前
JavaSwing学生成绩管理系统 - MySQL版
java·数据库·mysql·eclipse
basketball6168 小时前
C++ NULL 和 nullptr 区别 以及 nullptr 的核心实现
java·开发语言·c++
JAVA面经实录9179 小时前
MyBatis面试题库
java·mybatis
小江的记录本9 小时前
【JVM虚拟机】垃圾回收GC:垃圾回收算法:标记-清除、标记-复制、标记-整理、分代收集(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·算法·安全·面试