美文网首页
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