zoukankan      html  css  js  c++  java
  • spring boot-11.全局捕获异常

    1.在Spring boot 中如果发生错误,浏览器访问会默认跳转到Whitelabel Error Page 这个错误页面,如果是客户端访问的话返回JSON格式的错误数据,说明spring boot 为全局的异常处理做了自适应处理,浏览器和客户端分别响应不同的形式的错误数据。

    {
        "timestamp": 1534818780468,
        "status": 404,
        "error": "Not Found",
        "message": "No message available",
        "path": "/amain.html"
    }

    2.spring boot 对错误信息的处理都在它的自动的配置里实现,对于异常的自动配置都在org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration 中实现。首先,我们来看浏览器端如何响应错误。这个自动配置类为容器中添加一下几个组件:

    (1)当系统发生错误以后,ErrorPageCustomizer 会响应错误,就会发送/error请求去处理错误。

    @Bean
    public ErrorPageCustomizer errorPageCustomizer() {
      return new ErrorPageCustomizer(this.serverProperties);
    }

    (2)由BasicErrorController 去处理error请求,在BasicErrorController 中根据请求报文头的produces = "text/html" 判断是浏览器还是客户端请求, 用方法errorHtml 响应浏览器请求的错误页面,  error响应客户端请求而的错误页面 。

    @Bean
        @ConditionalOnMissingBean(value = ErrorController.class, search = SearchStrategy.CURRENT)
        public BasicErrorController basicErrorController(ErrorAttributes errorAttributes) {
            return new BasicErrorController(errorAttributes, this.serverProperties.getError(),
                    this.errorViewResolvers);
        }

    (3)接下来由 DefaultErrorViewResolver 去解析错误页面的视图,最终解析出来的视图的名称是: error/ +status,如果模板引擎可用的话就在模板文件夹下的error文件夹下找以错误状态码命名的错误页面,如果不可用则在静态资源文件夹下的error文件夹下找以错误状态码命名的错误文件。如果没有错误状态码命名的出错误文件,还可以按照以4开头的错误去找4xx命名的错误页面,5开头的错误去找5xx命名的错误页面,如果以上都没有的话就会来到默认的Whitelabel Error Page 这个错误页面

    @Bean
            @ConditionalOnBean(DispatcherServlet.class)
            @ConditionalOnMissingBean
            public DefaultErrorViewResolver conventionErrorViewResolver() {
                return new DefaultErrorViewResolver(this.applicationContext,
                        this.resourceProperties);
            }

    (4)DefaultErrorAttributes这个组件里面放置了错误信息,封装了

    timestamp:时间戳

    status:状态码

    error:错误提示

    exception:异常对象

    message:异常消息

    errors:JSR303数据校验的错误

    这些错误信息

    @Bean
        @ConditionalOnMissingBean(value = ErrorAttributes.class, search = SearchStrategy.CURRENT)
        public DefaultErrorAttributes errorAttributes() {
            return new DefaultErrorAttributes();
        }

    (5)综上所述,对于浏览器端的错误响应页面,我们只需要在模板文件夹夹下简历error文件夹,在这里放置以错误状态码命名的错误页面,或者放置以4xx,5xx命名的错误页面,来响应所有以4或者5开头的错误页面。

    2.如何定制客户端返回的json形式的错误信息

    定制json格式的错误信息的原理就是,在我们拦截到错误错误信息后,设置错误信息后将错误转发给/error请求,这样BasicErrorController 就会去处理这个请求,进行自适应处理。在进行BasicErrorController 中进行自适应处理的时候,是根据请求的状态码来映射错误页面的,而这个错误的状态码是从request中获取的,这样只要我们在异常处理的过程中设置状态码,他就会去找相应的错误页面,从而达到自适应的效果。

    Integer statusCode = (Integer) request
                    .getAttribute("javax.servlet.error.status_code");

    那么我就可以来定制自己的错误处理类

    @ControllerAdvice
    public class MyExceptionHandler {
        @ExceptionHandler(Exception.class)
        public String handlerException(Exception e,HttpServletRequest request) {
             request.setAttribute("javax.servlet.error.status_code",500);
            return "forward:/error";
        }
    }

    但是,这里返回的信息只是错误本身的一些信息,如果我们需要自己定义一些额外的信息,比如异常的说明或者提示,那该怎么办呢?我们上面介绍了DefaultErrorAttributes 这个足迹是用来封装错误信息的,而且这个组件添加了@ConditionalOnMissingBean注解,只有在容器中没有这个组件的时候它才能生效,这样我们就可以定做自己的ErrorAttributes ,将我们需要的额外信息添加进去,然后将我们自己定制的组件添加进容器即可。如果希望浏览器也返回json格式的错误信息的话,可以添加@ResponseBody注解,将错误信息封装好,返回即可。

    @ControllerAdvice
    public class MyExceptionHandler {
        @ExceptionHandler(Exception.class)
        public String handlerException(Exception e,HttpServletRequest request) {
             request.setAttribute("javax.servlet.error.status_code",500);
             Map<String, Object> map = new HashMap<>();
          //捕获异常后添加自己的错误信息 map.put(
    "code", "0000"); map.put("msg", "出错了,请稍后再试!"); request.setAttribute("errorMsg", map);
          //转发给BaseErrorController
    return "forward:/error"; } }
    @Component
    public class MyErrorattributes extends DefaultErrorAttributes{
      //重写 @Override
    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) { // TODO Auto-generated method stub Map<String,Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace);
         //获取并将自定义的错误信息添加到ErrorAttributes Map
    <String, Object> errorMsg = (Map<String, Object>) requestAttributes.getAttribute("errorMsg", 0); map.put("errorMsg", errorMsg); return map; } }

    浏览器效果:

    客户端效果:

  • 相关阅读:
    配置samba
    extern c
    剑指offer 孩子们的游戏
    剑指offer 扑克牌顺子
    剑指offer 翻转单词顺序列
    剑指offer 左旋转字符串
    mysql查看或显示当前存在多少数据库
    vim替换
    平衡二叉树
    将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分
  • 原文地址:https://www.cnblogs.com/li-zhi-long/p/9510467.html
Copyright © 2011-2022 走看看