SpringBoot系列: Spring支持的异常处理方式

===================================
视图函数返回 status code 的方式
===================================
Spring 有一个专门的枚举类型 HttpStatus, 比如 HttpStatus.NOT_FOUND
1. 视图函数返回 ResponseEntity 类型的对象.
2. 在 exception 类加注解 @ResponseStatus, 一旦视图函数抛出这个异常, Spring 就会自动返回设定的 status code.
3. 在视图函数上加 @ResponseStatus, 只要该函数没有报异常, Spring 就会自动返回设定的 status code.

===================================

方式一: 在业务 Controller 内部增加异常视图函数
===================================
在我们的 Controller 类中专门加一个或几个处理异常的视图函数, 这些异常处理视图需要加 @ExceptionHandler 注解.

将 @ExceptionHandler 注解的加到异常视图函数上, 也可以将 @ResponseStatus 注解一起加上. 异常视图函数的参数和普通视图函数的参数不一样, 能传入 Exception/HttpServletRequest/HttpServletResponse/HttpSession/Principle 等参数, 但是不能传入 Model 之类的参数, 视图方法的返回类型可以是: void/String 或 ModelAndView.

该方式缺点是: 这种异常处理仅仅在本 controller 有效, 不太好做到通用的异常处理. 当然也可设计一个通用的 Controller base 类, 在 base 类中加上异常处理视图函数, 所有业务 controller 都继承这个基类.

===================================
方式二: 实现一个基于 HandlerExceptionResolver 接口的 bean
===================================
在 Spring Web 项目中, 如果我们的 bean 实现了 HandlerExceptionResolver 接口, 一旦某个 controller 抛出异常, 这个 bean 会截获并处理异常.
该方法的缺点是: 不太好返回具体的报错内容.

一般情况下, 我们的 bean 并不直接实现 HandlerExceptionResolver 接口, 而是继承 SimpleMappingExceptionResolver 类.

通常做法是, 我们先自定义一个 SimpleMappingExceptionResolver 子类, 实现 doResolveException() 方法, 然后在 Mvc Configruation 配置类中, 声明一个名为 simpleMappingExceptionResolver 的 bean. 之所以继承 SimpleMappingExceptionResolver 类, 是因为它已经实现了很多有用的功能, 我们直接使用即可, 比如:
1. 设定 exception 和 view 视图的 mapping 关系等
2. 设置缺省的异常处理视图名
3. 异常 log 功能 (需启用)

除了 SimpleMappingExceptionResolver 类之外, Spring 还有其他几个 HandlerExceptionResolver 实现类, 作用分别是:
1. ExceptionHandlerExceptionResolver, 用来截获标注 @ExceptionHandler 注解的视图函数异常, @ExceptionHandler 加在专门的异常处理视图函数上.
2. ResponseStatusExceptionResolver, 用来截获和 @ResponseStatus 注解相关的异常, @ResponseStatus 可以加在 Exception 类或视图函数上.
3. DefaultHandlerExceptionResolver, 用来截获标准的 Spring exception, 并将异常转成相应 Http status code, 比如 404 等.

===================================
方式三: 使用 @ControllerAdvice 注解声明一个异常处理类
===================================
@ControllerAdvice 是 Spring 3.2 之后引入的. 在一个业务 controller 抛出异常后, @ControllerAdvice 标注的类会截获该异常. @ControllerAdvice 还有一个兄弟 @RestControllerAdvice 注解.
@ControllerAdvice 标注在类上, 具体异常视图函数仍然通过加 @ExceptionHandler 注解声明的, 该视图函数能传入 Exception/HttpServletRequest/HttpServletResponse/HttpSession/Principle 等参数, 但是不能传入 Model 之类的参数, 视图方法的返回类型可以是: void/String 或 ModelAndView.

@ControllerAdvice 优点有:
1. @ControllerAdvice 处理机制能接管所有 controller 类的异常, 更容易实现全局统一的异常处理.
2. 可以自由组合不同的 Exception 的异常处理视图.
3. 异常视图函数可以用 @ResponseStatus 注解指定返回码. 视图函数返回类型可以是 void/String 或 ModelAndView, 所以很容易返回报错内容.
4. 我们 @ControllerAdvice 注解类最好继承至 ResponseEntityExceptionHandler, 该 ResponseEntityExceptionHandler 类已经内置了很多标准异常的异常处理视图, 所以我们不需要再关心标准异常的处理, 只需要关心和业务相关的异常即可.

===================================
Spring Boot 默认的出错处理
===================================
Spring MVC 没有提供缺省的 fall-back 出错页, 而 Spring Boot 默认情况下就有很完善的报错处理机制, 一旦视图函数报错, Spring boot 先看有没有映射 /error 路径的视图, 有的话渲染该视图, 没有的话, 会展现 "Whitelabel Error Page", 该页面能显示出 Status code 和详细的报错信息. 如果是 Restful 请求的话, Whitelabel 报错也是 json 格式的反馈.

比如:

$> curl -H "Accept: application/json" http://localhost:8080/no-such-page

返回是:

{"timestamp":"2018-04-11T05:56:03.845+0000","status":404,"error":"Not Found","message":"No message available","path":"/no-such-page"}

默认缺省的异常处理路径是 /error,  也可以通过 server.error.path 属性修改.

===================================
推荐的做法:
===================================
1. 在一个项目中, 仅使用一种异常处理方法, 不要组合使用, 因为有可能和我们的预期不一致.
2. 推荐使用全局性的异常处理, 而不是 Controller 级别的异常处理; 推荐 @ControllerAdvice, 而不是基于 HandlerExceptionResolver 接口的 bean.
3. @ControllerAdvice 注解类最好继承至 ResponseEntityExceptionHandler, 该 ResponseEntityExceptionHandler 类已经内置了很多标准异常的异常处理视图, 所以我们不需要再关心标准异常的处理, 只需要关心和业务相关的异常即可.

需要说明的是, 只有进入 Controller 的异常, @ControllerAdvice 才能捕获, 对于拦截器的异常和 url写错这类404 这样的异常, 是捕获不到的, 当然一般情况下我们也没有必要处理这些异常.

下面是一个简单的示意代码:

class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    // 针对不同的异常, 定义其处理视图函数
    // some view functions

    // 对应 uncaughted 异常, 使用下面这个视图函数来兜底
    public static final String DEFAULT_ERROR_VIEW = "error";
    @ExceptionHandler(value = Exception.class)
    public ModelAndView defaultErrorHandler(HttpServletRequest req, HttpServletResponse rep, Exception e) throws Exception {
       //针对 500 错误, 需要记录 error 日志.
       logger.error(e.getMessage(),e);
       if (req.getHeader("Accept").contains("application/json"))
       {
           //write json to HttpServletResponse
           return null;
       }
       else{
            ModelAndView mav = new ModelAndView();
            mav.addObject("exception", e);
            mav.addObject("url", req.getRequestURL());
            mav.setViewName(DEFAULT_ERROR_VIEW);
            return mav;
        }
    }
}

===================================
参考:
===================================
https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
https://blog.csdn.net/aiyaya_/article/details/78725755
http://blog.didispace.com/springbootexception/
https://blog.csdn.net/chinrui/article/details/71036544
http://tengj.top/2018/05/16/springboot13/

原文地址:https://www.cnblogs.com/harrychinese/p/SpringBoot_exception_handler.html

时间: 2024-08-29 15:35:07

SpringBoot系列: Spring支持的异常处理方式的相关文章

SpringBoot系列之集成Dubbo的方式

本博客介绍Springboot框架集成Dubbo实现微服务的3种常用方式,对于Dubbo知识不是很熟悉的,请先学习我上一篇博客:SpringBoot系列之集成Dubbo实现微服务教程,本博客只是对上篇博客的补充,上篇博客已经介绍过的就不重复介绍 还是使用上篇博客的例子,业务场景: 某个电商系统,订单服务需要调用用户服务获取某个用户的所有地址: 我们现在 需要创建两个服务模块进行测试 模块 功能 订单服务模块 创建订单等 用户服务模块 查询用户地址等 测试预期结果: 订单服务web模块在A服务器,

Spring MVC 系统异常处理方式及性能对比

大部分公司所用的Spring框架版本是3.1版本以下,所以今天暂时总结3.1版本的Spring-MVC异常处理方式. 一.Spring MVC处理异常有3种方式: (1)使用Spring-MVC提供的SimpleMappingExceptionResolver: (2)实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器: (3)使用@ExceptionHandler注解实现异常处理: 二.分别介绍这三种异常处理的实现方式: (1)使用Simpl

SpringBoot学习(二)-->Spring的Java配置方式

二.Spring的Java配置方式 Java配置是Spring4.x推荐的配置方式,可以完全替代xml配置. 1.@Configuration 和 @Bean Spring的Java配置方式是通过 @Configuration 和 @Bean 这两个注解实现的: 1.@Configuration 作用于类上,相当于一个xml配置文件: 2.@Bean 作用于方法上,相当于xml配置中的<bean>: 2.示例 该示例演示了通过Java配置的方式进行配置Spring,并且实现了Spring IO

Spring中的统一异常处理方式

源自:https://segmentfault.com/a/1190000016236188 在具体的SSM项目开发中,由于Controller层为处于请求处理的最顶层,再往上就是框架代码的. 因此,肯定需要在Controller捕获所有异常,并且做适当处理,返回给前端一个友好的错误码. 不过,Controller一多,我们发现每个Controller里都有大量重复的.冗余的异常处理代码,很是啰嗦.能否将这些重复的部分抽取出来,这样保证Controller层更专注于业务逻辑的处理,同时能够使得异

springMVC系列之(三) spring+springMVC集成(annotation方式)

个人认为使用框架并不是很难,关键要理解其思想,这对于我们提高编程水平很有帮助.不过,如果用都不会,谈思想就变成纸上谈兵了!!!先技术,再思想.实践出真知. 1.基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来.它是为了解决企业应用开发的复杂性而创建的.Spring使用

Springboot中IDE支持两种打包方式,即jar包和war包

Springboot中IDE支持两种打包方式,即jar包和war包 打包之前修改pom.xml中的packaging节点,改为jar或者war    在项目的根目录执行maven 命令clean package -Dmaven.test.skip=true,即可打包,如下 命令执行成功后,在target目录下即可看到打包好的文件 提示:若打的包为jar包,可通过java -jar guns-xxx.jar来启动Guns系统 原文地址:https://www.cnblogs.com/mracale

SpringBoot系列:Spring Boot定时任务Spring Schedule

Spring Schedule是Spring提供的定时任务框架,相较于Quartz,Schedule更加简单易用,在中小型应用中,对于大部分需求,Schedule都可以胜任. 一.Spring Schedule使用演示 在 SpringBoot使用Spring Schedule非常简单,因为SpringBoot自身的starter中已经集成了Schedule,而不需要我们做更多的处理. 使用@EnableScheduling注解开启定时功能,该注解可以使用在启动类上,也可以注解于定时任务的类上.

【Spring】Spring系列4之Spring支持JDBC

4.Spring支持JDBC 4.1.使用JdbcTemplate简化JDBC开发 也可以这么用(不推荐): 4.2.使用NamedParameterJdbcTemplate

【Spring】Spring系列5之Spring支持事务处理

5.Spring支持事务处理 5.1.事务准备 以上代码结构与AOP的前置通知.返回通知.异常通知.后置通知一样. 5.2.声明式事务 5.2.1.基于注解 5.2.2.基于配置文件 5. 3.事务传播属性 5.4.事务其他属性 5.4.1.事务的隔离级别 5.4.2.事物的回滚属性 5.4.3.超时与只读属性 5.5.使用xml文件配置事务