===================================
视图函数返回 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. RabbitMQ消费者消息权重,

    有的消费者处理速度快,有的消费者处理速度慢,我们想给处理快的多发消息,处理慢的少发消息, 怎么办呢?按照之前的轮询模式,肯定不行的,这里可以检测消息数量,如果消费者正在处理就不给他发 .... def ...

  2. duilib

    https://www.cnblogs.com/lin1270/p/4109305.html

  3. SQL MAX() 函数

    MAX() 函数 MAX 函数返回一列中的最大值.NULL 值不包括在计算中. SQL MAX() 语法 SELECT MAX(column_name) FROM table_name 注释:MIN ...

  4. mysql 有没有参数都报错“mysql: unknown option”

    报错: [root@XXXX tmp]# mysql -uroot -pmysql: unknown option '--You have new mail in /var/spool/mail/ro ...

  5. 监控zookeeper

    [4ajr@db1 scripts]$ cat zookeeper_mode.sh #!/bin/bash mode=`echo srvr|nc 127.0.0.1 2181|awk '/Mode/{ ...

  6. Linux配置外网访问mysql

    stream{    upstream abc{        server 192.168.8.249:3306;    }    server{        listen 9211 ; prox ...

  7. MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网络训练实现及比较(三)

    版权声明:本文为博主原创文章,欢迎转载,并请注明出处.联系方式:460356155@qq.com 在前两篇文章MINIST深度学习识别:python全连接神经网络和pytorch LeNet CNN网 ...

  8. Android——分割线中夹文字

    内容不多,只是感觉平时很容易遇上,那就做个笔记吧! 其实很简单,如下: <RelativeLayout android:layout_width="match_parent" ...

  9. python爬取中国天气网站数据并对其进行数据可视化

    网址:http://www.weather.com.cn/textFC/hb.shtml 解析:BeautifulSoup4 爬取所有城市的最低天气   对爬取的数据进行可视化处理 按温度对城市进行排 ...

  10. dijstra算法

    无向图.赋权有向图 的最短路径