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

相关推荐
ok!ko几秒前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
2402_8575893632 分钟前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
吾爱星辰1 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
哎呦没2 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
编程、小哥哥2 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
IT学长编程3 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统
莹雨潇潇3 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
杨哥带你写代码4 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
郭二哈4 小时前
C++——模板进阶、继承
java·服务器·c++
A尘埃4 小时前
SpringBoot的数据访问
java·spring boot·后端