Spring Boot统一异常处理

2018-07-06  本文已影响0人  wencai

Spring通过@ControllerAdvice和@ExceptionHandler两个注解即可实现异常的统一处理。

一、用法介绍

  @ControllerAdvice和@ExceptionHandler可拦截异常,通过这两个注解可实现对异常的自定义处理。


二、示例

1.需求

  提供两种异常返回方式:对RESTful风格返回特定的json格式;对text/html风格,返回特定的页面。

2.实现

第一步:定义全局异常捕获类

@RestControllerAdvice
public class GlobalExceptionHandle {

    private Logger logger = LoggerFactory.getLogger("GlobalExceptionHandler");

    public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e){
        ModelAndView mav = new ModelAndView();
        mav.addObject("msg","异常咯");
        mav.setViewName("error");
        return mav;
    }

    @ExceptionHandler(BaseException.class)
    public Object baseErrorHandler(HttpServletRequest req, Exception e) throws Exception {
        logger.error("---BaseException Handler---Host {} invokes url {} ERROR: {}", req.getRemoteHost(), req.getRequestURL(), e.getMessage());
        return e.getMessage();
    }
}

第二步:定义异常处理类

public class BaseException extends Exception {
    public BaseException(String message) {
        super(message);
    }
}

第三步:定义Controller测试异常

@RequestMapping("/ex")
    public Object throwIOException() throws Exception {
        throw new IOException("This is IOException.");
    }

第四步:为Controller定义特定的异常@ExceptionHandler
在Controller中增加以下代码:

 @RequestMapping("/ex5")
    public Object throwNullPointerException() throws Exception {
        throw new NullPointerException("This is NullPointerException.");
    }

    @ExceptionHandler(NullPointerException.class)
    public String controllerExceptionHandler(HttpServletRequest req, Exception e) {
        logger.error("---ControllerException Handler---Host {} invokes url {} ERROR: {}", req.getRemoteHost(), req.getRequestURL(), e.getMessage());
        return e.getMessage();
    }

Tips:在SpringBoot中,当用户访问一个不存在的链接时,Spring默认将页面重定向到/error上,而不会抛出异常。既然如此,可以告诉SpringBoot,当出现404错误时,抛出一个异常即可。在application.properties中添加如下代码:

spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

三、源码解析

1.默认情况,SpringBoot为两种情况提供了不同的响应方式。
  1)浏览器请求一个不存在的页面或服务端发生异常时,一般情况浏览器默认会发送的请求头中Accept: text/html,所以SpringBoot默认会响应一个html文档内容,称作“Whitelabel Error Page”。
  2)使用postman工具或者js发送请求一个不存在的url或者服务端发生异常时,SpringBoot会返回如下格式的Json字符串:


222.png

2.原理很简单:
  SpringBoot默认提供了程序出错的映射路径/error。这个/error请求会在BasicErrorController中处理,其内部是通过判断请求头中的Accept内容是text/html还是其他,来决定返回页面视图还是JSON消息内容。代码如下:

public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = this.getStatus(request);
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.TEXT_HTML)));
        response.setStatus(status.value());
        ModelAndView modelAndView = this.resolveErrorView(request, response, status, model);
        return modelAndView != null ? modelAndView : new ModelAndView("error", model);
    }

    @RequestMapping
    @ResponseBody
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = this.getErrorAttributes(request, this.isIncludeStackTrace(request, MediaType.ALL));
        HttpStatus status = this.getStatus(request);
        return new ResponseEntity(body, status);
    }

如何自定义Whitelabel Error Page
  直接在/resources/template下面创建error.html即可覆盖Whitelabel Error Page的错误页面。如果想定义

四、更多详情

https://segmentfault.com/a/1190000006749441
https://blog.csdn.net/zzz___bj/article/details/80368071
http://tengj.top/2018/05/16/springboot13/#%E4%BB%8B%E7%BB%8DSpring-Boot%E9%BB%98%E8%AE%A4%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%E6%9C%BA%E5%88%B6

上一篇 下一篇

猜你喜欢

热点阅读