美文网首页
SpringBoot-异常处理

SpringBoot-异常处理

作者: 张明学 | 来源:发表于2020-04-23 01:03 被阅读0次

    SpringBoot的异常处理,主要是指对异常进行包装,以友好的方式返回给调用方。处理方式主要通过@RestControllerAdvice、@ExceptionHandler来处理。

    1. 定义一个统一返回对象
    @Data
    @Accessors(chain = true)
    public class BaseResponse implements Serializable {
        private String code;
        private String message;
    }
    
    1. 异常拦截
    @RestControllerAdvice
    @Slf4j
    public class GlobalExceptionHandler {
    
        /**
         * 非预期的运行时异常
         */
        @ExceptionHandler(RuntimeException.class)
        @ResponseStatus(HttpStatus.OK)
        public BaseResponse tryRuntimeException(HttpServletRequest request, HandlerMethod handlerMethod, RuntimeException e) {
            log.error("系统异常,url={},{}#{}", request.getRequestURL(), handlerMethod.getClass(), handlerMethod.getMethod().getName(), e);
            return new BaseResponse().setCode("10").setMessage("出错了");
        }
    
    
        /**
         * 业务异常
         */
        @ExceptionHandler(BusinessException.class)
        @ResponseStatus(HttpStatus.OK)
        public BaseResponse tryBusinessException(HttpServletRequest request, HandlerMethod handlerMethod, BusinessException e) {
            log.error("业务异常,url={},{}#{}", request.getRequestURL(), handlerMethod.getClass(), handlerMethod.getMethod().getName(), e);
            return new BaseResponse().setCode("20").setMessage("系统繁忙");
        }
    
        /**
         * 参数校验异常
         */
        @ExceptionHandler({
                MethodArgumentNotValidException.class,
                BindException.class,
                ValidationException.class,
                ConstraintViolationException.class})
        @ResponseStatus(HttpStatus.OK)
        public BaseResponse tryValidationException(HttpServletRequest request, HandlerMethod handlerMethod, Exception e) {
            log.error("参数校验异常,url={},{}#{}", request.getRequestURL(), handlerMethod.getClass(), handlerMethod.getMethod().getName(), e);
            return new BaseResponse().setCode("30").setMessage("参数不合法");
        }
    }
    

    注意:这个类确保能被纳入Spring的管理
    通过@ExceptionHandler我们可以拦截想要处理的异常类型,一般我们可以把异常分为三类:一类为系统错误,二类为业务异常,三类为参数校验异常。方法名可以随意定义,request,response,handlerMethod,Exception这些参数都不是必须的,也都可以由SpringBoot传入进来。由于SpringBoot通常返回的都是JSON格式数据(@RestControllerAdvice拦截就是RestController,这里返回的对象也会就会被转成JSON)。只有一些特殊的情况,类似SpringMVC的方式,可以通过request的请求头和Controller的配置来判断是返回JSON还是错误页面。

        /**
         * 根据HttpServletRequest请求头来判断是否是ajax请求
         */
        public static boolean isAsyncRequest(HttpServletRequest request) {
            String requestHeader = request.getHeader("x-requested-with");
            if (StringUtils.isEmpty(requestHeader) && "XMLHttpRequest".equals(requestHeader)) {
                return true;
            } else {
                return false;
            }
        }
    
    /**
         * 根据handlerMethod的注解来判断是不是ajax请求
         */
        public static boolean isAsyncRequest(HttpServletRequest request, HandlerMethod handlerMethod) {
            boolean isAjax = isAsyncRequest(request);
            if (isAjax) {
                return true;
            }
    
            // 方法上有@ResponseBody 表示返回JSON
            ResponseBody responseBody = handlerMethod.getMethodAnnotation(ResponseBody.class);
            if (null != responseBody) {
                return true;
            }
    
            //判断Controller类上有没有@RestController
            RestController restController = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), RestController.class);
            if (null != restController) {
                return true;
            }
    
            //判断Controller类上有没有@ResponseBody
            responseBody = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), ResponseBody.class);
            if (null != responseBody) {
                return true;
            }
            return false;
        }
    

    对异常处理后,根据请求类型,返回ModelAndView

    /**
         * 对异常处理后,根据请求类型,返回ModelAndView
         */
        @ExceptionHandler(Exception.class)
        public ModelAndView businessException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception ex) {
            if (isAsyncRequest(request, handlerMethod)) {
                return buildJsonResponse(request, response, handlerMethod, ex);
            } else {
                return buildViewResponse(request, response, handlerMethod, ex);
            }
        }
    
        private ModelAndView buildJsonResponse(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception ex) {
    
            BaseResponse baseResponse = new BaseResponse().setCode("40").setMessage(ex.getMessage());
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json;charset=UTF-8");
            PrintWriter writer = null;
            try {
                writer = response.getWriter();
            } catch (IOException e) {
                e.printStackTrace();
            }
            writer.write(JSON.toJSONString(baseResponse));
            return null;
        }
    
        private ModelAndView buildViewResponse(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception ex) {
            ModelAndView errorView = new ModelAndView();
            errorView.setViewName("redirect:/error-page");
            return errorView;
        }
    

    相关文章

      网友评论

          本文标题:SpringBoot-异常处理

          本文链接:https://www.haomeiwen.com/subject/yceuihtx.html