Spring Boot默认的异常处理机制

默认情况下,Spring Boot为两种情况提供了不同的响应方式。

一种是浏览器客户端请求一个不存在的页面或服务端处理发生异常时,一般情况下浏览器默认发送的请求头中Accept: text/html,所以Spring Boot默认会响应一个html文档内容,称作“Whitelabel Error Page”。

另一种是使用Postman等调试工具发送请求一个不存在的url或服务端处理发生异常时,Spring Boot会返回类似如下的Json格式字符串信息

{
"timestamp": "2018-05-12T06:11:45.209+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/index.html"
}

Spring Boot 默认提供了程序出错的结果映射路径/error。这个/error请求会在BasicErrorController中处理,其内部是通过判断请求头中的Accept的内容是否为text/html来区分请求是来自客户端浏览器(浏览器通常默认自动发送请求头内容Accept:text/html)还是客户端接口的调用,以此来决定返回页面视图还是 JSON 消息内容

如何自定义错误页面

  • 在/resources/templates下面创建error.html就可以覆盖默认的Whitelabel Error Page的错误页面

  • 访问不存在的页面时,结果如下:

  • 根据不同的状态码返回不同的视图页面,也就是对应的404,500等页面

    • 静态的:如果只是静态HTML页面,不带错误信息的,在resources/public/下面创建error目录,在error目录下面创建对应的状态码html即可

    • 如果是动态模板页面,可以带上错误信息,在resources/templates/下面创建error目录

  • 模拟下500错误
@Controller
public class BaseErrorController extends AbstractController{
private Logger logger = LoggerFactory.getLogger(this.getClass()); @RequestMapping(value="/ex")
@ResponseBody
public String error(){
int i=5/0;
return "ex";
}
}

如果同时存在静态页面500.html和动态模板的500.html,则后者覆盖前者。即templates/error/这个的优先级比resources/public/error高。

error.html会覆盖默认的 whitelabel Error Page 错误提示, 静态错误页面优先级别比error.html高

根据不同的状态码,自动转发到对应的错误的页面上

@Configuration
public class ContainerConfig {
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
//如果发生500错误,就会将请求转发到/error/500这个映射来
container.addErrorPages(new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500"));
//如果发生404错误,就会将请求转发到/error/404这个映射来
container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"));
}
};
}
} @Controller
public class MyBasicErrorController extends BasicErrorController { public MyBasicErrorController() {
super(new DefaultErrorAttributes(), new ErrorProperties());
} /**
* 定义500的ModelAndView
* @param request
* @param response
* @return
*/
@RequestMapping(produces = "text/html",value = "/500")
public ModelAndView errorHtml500(HttpServletRequest request,
HttpServletResponse response) {
response.setStatus(getStatus(request).value());
Map<String, Object> model = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.TEXT_HTML));
model.put("msg","自定义错误信息");
return new ModelAndView("error/500", model);
} /**
* 定义500的错误JSON信息
* @param request
* @return
*/
@RequestMapping(value = "/500")
@ResponseBody
public ResponseEntity<Map<String, Object>> error500(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.TEXT_HTML));
HttpStatus status = getStatus(request);
return new ResponseEntity<Map<String, Object>>(body, status);
} /**
* 定义404的ModelAndView
* @param request
* @param response
* @return
*/
@RequestMapping(produces = "text/html",value = "/404")
public ModelAndView errorHtml400(HttpServletRequest request,
HttpServletResponse response) {
response.setStatus(getStatus(request).value());
Map<String, Object> model = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.TEXT_HTML));
model.put("msg","自定义错误信息");
return new ModelAndView("error/404", model);
}
}

BasicErrorController默认对应的@RequestMapping是/error,固我们方法里面对应的@RequestMapping(produces = "text/html",value = "/500")实际上完整的映射请求是/error/500,这就跟上面 customize 方法自定义的映射路径对上了

通过@ControllerAdvice注解来处理异常

Spring Boot提供的ErrorController是一种全局性的容错机制。此外,你还可以用@ControllerAdvice注解和@ExceptionHandler注解实现对指定异常的特殊处理。

这里介绍两种情况:

  • 局部异常处理 @Controller + @ExceptionHandler
  • 全局异常处理 @ControllerAdvice + @ExceptionHandle
@RestControllerAdvice
public class BusinessExceptionHandler {
private Logger logger = LoggerFactory.getLogger(getClass()); /**
* 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器
* @param binder
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
System.out.println("请求有参数才进来");
} /**
* 把值绑定到Model中,使全局@RequestMapping可以获取到该值
* @param model
*/
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("author", "嘟嘟MD");
} @ExceptionHandler(Exception.class)
public Object handleException(Exception e,HttpServletRequest req){
AjaxObject r = new AjaxObject();
//业务异常
if(e instanceof BusinessException){
r.put("code", ((BusinessException) e).getCode());
r.put("msg", ((BusinessException) e).getMsg());
}else{//系统异常
r.put("code","500");
r.put("msg","未知异常,请联系管理员");
} //使用HttpServletRequest中的header检测请求是否为ajax, 如果是ajax则返回json, 如果为非ajax则返回view(即ModelAndView)
String contentTypeHeader = req.getHeader("Content-Type");
String acceptHeader = req.getHeader("Accept");
String xRequestedWith = req.getHeader("X-Requested-With");
if ((contentTypeHeader != null && contentTypeHeader.contains("application/json"))
|| (acceptHeader != null && acceptHeader.contains("application/json"))
|| "XMLHttpRequest".equalsIgnoreCase(xRequestedWith)) {
return r;
} else {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", e.getMessage());
modelAndView.addObject("url", req.getRequestURL());
modelAndView.addObject("stackTrace", e.getStackTrace());
modelAndView.setViewName("error");
return modelAndView;
}
}
}

全局异常类我用的是@RestControllerAdvice,而不是@ControllerAdvice,因为这里返回的主要是json格式,这样可以少写一个@ResponseBody。

参考:

原文: http://tengj.top/2018/05/16/springboot13/  作者: 嘟嘟MD

spring-boot-全局异常的更多相关文章

  1. Spring Boot 全局异常配置

    Spring Boot 全局异常配置,处理异常控制器需要和发生异常的方法在一个类中.使用 ControllerAdvice 注解 package com.li.controller; import o ...

  2. Spring Boot 全局异常捕获

    import javax.servlet.http.HttpServletRequest; import org.springframework.web.bind.annotation.Control ...

  3. Spring Boot全局异常处理

    本文为大家分享了Spring Boot全局异常处理,供大家参考,具体内容如下 1.后台处理异常 a.引入thymeleaf依赖 <!-- thymeleaf模板插件 --> <dep ...

  4. spring设置全局异常处理器

    1.spring设置全局异常,它的原理是向上捕获 spring.xml配置 <!--自定义全局异常处理器--> <bean id="globalExceptionResol ...

  5. Spring MVC全局异常后返回JSON异常数据

    问题: 当前项目是作为手机APP后台支持,使用spring mvc + mybaits + shiro进行开发.后台服务与手机端交互是发送JSON数据.如果后台发生异常,会直接返回异常页面,显示异常内 ...

  6. Spring Boot全局支持CORS(跨源请求)

    import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet. ...

  7. spring boot全局配置文件优先级

    前两篇介绍的application配置文件,即为spring boot全局配置文件.那么spring boot加载配置文件的时候,怎么确定加载哪个目录下哪个文件呢? spring boot默认的配置文 ...

  8. spring boot 拦截异常 统一处理

    spring boot 默认情况下会映射到 /error 进行异常处理,提示不友好,需要自定义异常处理,提供友好展示 1.自定义异常类(spring 对于 RuntimeException 异常才会进 ...

  9. Spring Boot 全局异常处理

    Spring Boot版本 1.5 @ControllerAdvice public class GlobalExceptionHandler extends ResponseEntityExcept ...

  10. Spring Boot 统一异常这样处理和剖析,安否?

    话说异常 「欲渡黄河冰塞川,将登太行雪满天」,无论生活还是计算机世界难免发生异常,上一篇文章RESTful API 返回统一JSON数据格式 说明了统一返回的处理,这是请求一切正常的情形:这篇文章将说 ...

随机推荐

  1. typescript 不用import?

    如果你想用ts文件,而又不想import,export,怎么办呢? 感谢开发者提供的工具.    https://github.com/domchen/typescript-plus.   感想: 仅 ...

  2. Redis和Memcache的区别总结-京东阿里面试

    集群: redis 和memcached都支持集群 数据类型 Redis支持的数据类型要丰富得多,Redis不仅仅支持简单的k/v类型的数据,同时还提供String,List,Set,Hash,Sor ...

  3. MySql的多存储引擎架构, 默认的引擎InnoDB与 MYISAM的区别(滴滴)

    1.存储引擎是什么? MySQL中的数据用各种不同的技术存储在文件(或者内存)中.这些技术中的每一种技术都使用不同的存储机制.索引技巧.锁定水平并且最终提供广泛的不同的功能和能力.通过选择不同的技术, ...

  4. 洛谷 P4301 [CQOI2013]新Nim游戏 解题报告

    P4301 [CQOI2013]新Nim游戏 题目描述 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴. ...

  5. LINUX内核分析第七周——可执行程序的装载

    一.得到一个可执行程序 1. 预处理.编译.链接 gcc hello.c -o hello.exe gcc编译源代码生成最终可执行的二进制程序,GCC后台隐含执行了四个阶段步骤. 预处理 => ...

  6. Webpack 学习笔记总结

    Webpack安装 Linux系统默认已经安装了node&npm,但版本比较低,而且没法升级,可以重新下载Node然后通过软链接替换系统自带的node和npm; ln -s /path_to/ ...

  7. ASP.NET MVC API 接口验证

    项目中有一个留言消息接口,接收其他系统的留言和展示留言,参考了网上的一些API验证方法,发现使用通用权限管理系统提供的验证方法最完美(http://www.cnblogs.com/jirigala/p ...

  8. c++ 容器弊端

    1.stack 不能直接清空,要 while (!s.empty()) s.pop(); 2.vector 增添.删除数据,也许vector首尾的地址会发生改变 如: ( watch f.begin( ...

  9. 常用Build-in Keywords

    1. Variables |- Set variable |- Create list |- Evaluate |- Get Variable Value 2. Conditional |- Run ...

  10. 从 php 源码看 php 中的对象

    从一个简单的例子说起: class Person { public $name; public $age; public function __construct($name, $age) { $th ...