zoukankan      html  css  js  c++  java
  • @ControllerAdvice的异常捕获与响应增强处理

           做WEB项目,发展到现在,前后端分离的框架已经成为主流面对前后端分离项目,基本思路都是后端提供restful接口,前端接受数据往组件上绑定(vue)。但是想要把框架做好,接口、数据的统一是绕不开的话题,这是基础中的基础。本篇内容将先分析springboot框架下的ControllerAdvice是怎样对异常、response进行统一拦截处理的。而后会附上一篇示例代码,用程序来讲述其运用。

      下面这张图是我跟踪源码后简单画下来的(源码内容过多不宜粘贴),只求达意,并不是完整的运行流程。需要知道的是ResponseBodyAdvice是在将数据最终写入response流前发生的,一定在异常处理的后面。

    源码:查询Bean工厂中的ControllerAdvice类型的Bean

     

    源码:对ControllerAdviceBean进行解析,获取继承自ResponseBodyAdvice的Bean,解析有异常处理程序的Bean


      接下来附上我的测试示例。其作用一是捕获自己定义的业务校验类异常,二是将restful接口的返回值统一封装成 JsonResult 这样的一个对象。前端项目在解析接口返回值的时候,不管是异常还是正常数据,其基础结构都是一致的,偏于编写统一处理的代码。(小东西,用途很大)东西比较简单,不细说了,大家看看就好。

      一、异常捕获

    /**
     * @author simm
     */
    @ControllerAdvice
    public class MyExceptionHandlerAdvice {
        /**
         * 处理业务异常
         * @param request
         * @param response
         * @param handler
         * @param ex
         * @return
         */
        @ExceptionHandler(BizException.class)
        @ResponseBody
        JsonResult handleBizException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler, Throwable ex) {
            JsonResult result = new JsonResult(false);
            result.error(ex.getMessage());
            return result;
        }
    
        /**
         * 处理业务异常
         * @param request
         * @param response
         * @param handler
         * @param ex
         * @return
         */
        @ExceptionHandler(Exception.class)
        @ResponseBody
        JsonResult handleException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler, Throwable ex) {
            JsonResult result = new JsonResult(false);
            result.error(Throwables.getStackTraceAsString(ex));
            return result;
        }
    }

      二、responsebody统一封装

    /**
     * 数据返回结构统一组装
     *
     * @author simm
     */
    @ControllerAdvice
    public class MyResponseBodyAdvice implements ResponseBodyAdvice {
        @Override
        public boolean supports(MethodParameter returnType, Class converterType) {
            return true;
        }
    
        /**
         * 处理string转换器
         */
        private final static String HTTP_MESSAGE_CONVERTER = "StringHttpMessageConverter";
    
        @Override
        public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                      Class selectedConverterType,
                                      ServerHttpRequest request, ServerHttpResponse response) {
            if(JsonResult.class.isAssignableFrom(body.getClass())){
                //异常已经被包装
                return body;
            }
            //将返回值包装成jsonresult结构
            JsonResult<Object> jsonResult = new JsonResult<>(true);
            jsonResult.setData(body);
    //        if (selectedConverterType.getSimpleName().contains(HTTP_MESSAGE_CONVERTER)) {
    //            return JSON.toJSONString(jsonResult);
    //        }
            return jsonResult;
        }
    }

      三、抛个业务异常试试

    /**
     * 测试异常
     * @author simm
     */
    @Controller
    @RequestMapping("exception")
    public class ExceptionTestController {
        /**
         * 抛出业务异常
         * @return
         */
        @RequestMapping("/biz")
        @ResponseBody
        public Object biz() {
            throw new BizException("这是我的自定义异常");
        }
    
        /**
         * 抛出程序异常
         * @return
         */
        @RequestMapping("/process")
        @ResponseBody
        public Object process() {
            int i = 0;
            int j = 100/0;
            return true;
        }
    }

  • 相关阅读:
    精简版的MySQL制作步骤
    WCF中常用的binding方式 z
    SQLite的.NET应用自适应32位/64位系统 z
    DEV GridControl 常用属性 z
    SpringBoot项目设置热部署
    SpringBoot整合Quartz定时任务
    单引号、双引号 转义符
    Java几种常见的四舍五入的方法
    Java集合之保持compareTo和equals同步
    你真的了解try{ return }finally{}中的return?(转载)
  • 原文地址:https://www.cnblogs.com/MrSi/p/13512223.html
Copyright © 2011-2022 走看看