===================================
视图函数返回 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 属性修改.

Spring Boot 之所以有一个 whitelabel error页面, 是因为 Spring Boot 会注入一个 BasicErrorController 用来处理异常, 相关的 application 属性有:

server.error.include-exception=false # Include the "exception" attribute.
server.error.include-stacktrace=never # When to include a "stacktrace" attribute.
server.error.path=/error # Path of the error controller.
server.error.whitelabel.enabled=true # Whether to enable the default error page displayed in browsers in case of a server error.

如果缺省的 whitelabel 页面不能满足需求, 可以简单定制 page 页, 在 resources 目录下, 新建一个 error.html 模板文件, 在文件中, 可以使用下面的变量.
${timestamp} 、 ${path} 、 ${error} 、 ${status} 、 ${message} 、 ${exception}、 ${trace}

比如要对 404 访问做日志,  我们可以仿造 BasicErrorController 写一个自己的 ErrorController 类. Spring boot 会自动这个 ErrorController 实例代替缺省的 ErrorController.

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

需要说明的是, 只有进入 Controller 的异常, @ControllerAdvice 才能捕获, 对于拦截器的异常和 url写错这类404 这样的异常, 是捕获不到的, 当然一般情况下我们也没有必要处理这些异常, 如果一定要对 404 访问做日志,  我们可以仿造 BasicErrorController 写一个自己的 ErrorController 类.

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

@ControllerAdvice
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/

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

  1. SpringBoot系列之集成Dubbo的方式

    SpringBoot系列之集成Dubbo的方式 本博客介绍Springboot框架集成Dubbo实现微服务的3种常用方式,对于Dubbo知识不是很熟悉的,请先学习我上一篇博客:SpringBoot系列 ...

  2. SpringBoot系列: Spring项目异常处理最佳实践

    ===================================自定义异常类===================================稍具规模的项目, 一般都要自定义一组异常类, 这 ...

  3. SpringBoot系列-整合Mybatis(注解方式)

    目录 一.常用注解说明 二.实战 三.测试 四.注意事项 上一篇文章<SpringBoot系列-整合Mybatis(XML配置方式)>介绍了XML配置方式整合的过程,本文介绍下Spring ...

  4. SpringBoot系列: Spring MVC视图方法的补充

    SpringMVC 视图方法的参数, 已经在这个文章中写得非常清楚了, 链接为 https://www.cnblogs.com/morethink/p/8028664.html 这篇文章做一些补充. ...

  5. [SpringBoot系列]--Spring Hibernate search 注解实现(未测试)

    1.maven项目pom.xml加入依赖 <dependency> <groupId>org.hibernate</groupId> <artifactId& ...

  6. SpringBoot系列随笔 - BootJar的启动方式

    前言 写完maven的加密插件后,尝试在boot启动时的类加载过程中编写解密代码时,发现了一个平常没有注意的地方. 那就是boot-jar的启动方式与我们平常编写的可执行jar是存在很大差别的. 所以 ...

  7. SpringBoot系列之学习教程汇总

    对应SpringBoot系列博客专栏,例子代码,本博客不定时更新 一.配置篇 SpringBoot系列之@PropertySource读取yaml文件     >> source down ...

  8. SpringBoot系列之从入门到精通系列教程

    对应SpringBoot系列博客专栏,例子代码,本博客不定时更新 Spring框架:作为JavaEE框架领域的一款重要的开源框架,在企业应用开发中有着很重要的作用,同时Spring框架及其子框架很多, ...

  9. SpringBoot系列: RestTemplate 快速入门

    ====================================相关的文章====================================SpringBoot系列: 与Spring R ...

随机推荐

  1. SQLServer删除数据

    使用SSMS删除数据 1.连接数据库.选择数据表->右键点击,选择所有行(或者选择前200行). 2.在数据窗口中选择数据行(注意点击最左边列选择整个数据行)->在最左侧右键点击-> ...

  2. C#中@的作用

    1.在书写文件路径时,消除"/"的转义功能 string FileDirect = "C:\Text\Debug\Text.txt"; \\编译会报错 stri ...

  3. SQL CHECK 约束

    SQL CHECK 约束 CHECK 约束用于限制列中的值的范围. 如果对单个列定义 CHECK 约束,那么该列只允许特定的值. 如果对一个表定义 CHECK 约束,那么此约束会在特定的列中对值进行限 ...

  4. Notepad++设置背景色

    点击菜单“设置”-“语言格式设置” 在语言中,选中Global Styles,在样式栏选 中Default Style,再在右边点击背景色的颜色方块. 在打开的颜色对话框中点击 More Colour ...

  5. 前端——JavaScript

    何谓JavaScript?它与Java有什么关系? JavaScript与HTML.CSS组合使用应用于前端开发,JavaScript是一门独立的语言,浏览器内置了JS的解释器.它除了和Java名字长 ...

  6. 类别不平衡问题和Softmax回归

    目录 类别不平衡(class-imbalance) Softmax回归模型 类别不平衡(class-imbalance) 当不同类别的训练样本数目差别很大,则会对学习过程造成困扰.如有998个反例,但 ...

  7. VSCode 必装的 10 个高效开发插件

    本文介绍了目前前端开发最受欢迎的开发工具 VSCode 必装的 10 个开发插件,用于大大提高软件开发的效率. VSCode 的基本使用可以参考我的原创视频教程「VSCode 高效开发必装插件」. V ...

  8. springboot使用多数据源以及配置

    1. 首先在application中配置数据源地址 my.datasource.koi.type=com.alibaba.druid.pool.DruidDataSource my.datasourc ...

  9. spring boot 操作MySQL pom添加的配置

    1 在项目中的pom.xml配置文件添加依赖 <!--MySQL依赖 --> <dependency> <groupId>mysql</groupId> ...

  10. 数据库优化-mysql中INNODB和MYIASM引擎的区别

    Innodb引擎 Innodb引擎提供了对数据库ACID事务的支持,并且实现了SQL标准的四种隔离级别. 该引擎还提供了行级锁和外键约束,它的设计目标是处理大容量数据库系统,它本身其实就是基于MySQ ...