SpringMVC设置全局异常处理器

文章目录

  • 背景
  • 分析
    • 使用@ControllerAdvice(@RestControllerAdvice)+@ExceptionHandler实现全局异常
    • 全局异常处理-多个处理器匹配顺序
      • 存在一个类中
      • 存在不同的类中
  • 对于过滤器和拦截器中的异常,有两种思路可以考虑

背景

在项目中我们有需求做一个全局异常处理,来规范所有出去的异常信息。

参考:官方文档

分析

首先 ControllerAdvice(RestControllerAdvice ) ,ControllerAdvice 是无法处理过滤器和拦截器中的异常的。

引用一张图

SpringMVC设置全局异常处理器_第1张图片

下面介绍controller层的全局异常设置

全局异常处理也有多种方式

使用@ControllerAdvice(@RestControllerAdvice)+@ExceptionHandler实现全局异常

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;



@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理参数错误的异常
     * @param e
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = IllegalParamsException.class)
    public ResultVO<Object> handleIllegalParamsException(IllegalParamsException e) {
        ResultVO<Object> resultVo = new ResultVO<>();
        resultVo.setStatus(HttpStatus.BAD_REQUEST.value());
        resultVo.setErrorCode(e.getErrorInfo().getErrorCode());
        resultVo.setErrorMsg(e.getErrorInfo().getErrorDesc());
        return resultVo;
    }

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ResultVO<Object> handleException(Exception e) {
        ResultVO<Object> resultVo = new ResultVO<>();
        resultVo.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        resultVo.setErrorMsg(e.getMessage());
        return resultVo;
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultVO<T> {

    private Integer status;

    private String errorCode;

    private String errorMsg;

    private T data;

    public ResultVO(Integer status, String errorCode, String errorMsg) {
        this.status = status;
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
    }
}
public class IllegalParamsException extends RuntimeException {


    private static final long serialVersionUID = -6298406656682893468L;

    private OperationErrorEnum errorInfo;

    public IllegalParamsException(OperationErrorEnum errorInfo) {
        this.errorInfo = errorInfo;
    }

    public IllegalParamsException(String message, OperationErrorEnum errorInfo) {
        super(message);
        this.errorInfo = errorInfo;
    }

    public IllegalParamsException(String message, Throwable cause, OperationErrorEnum errorInfo) {
        super(message, cause);
        this.errorInfo = errorInfo;
    }

    public IllegalParamsException(Throwable cause, OperationErrorEnum errorInfo) {
        super(cause);
        this.errorInfo = errorInfo;
    }

    public IllegalParamsException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, OperationErrorEnum errorInfo) {
        super(message, cause, enableSuppression, writableStackTrace);
        this.errorInfo = errorInfo;
    }

    public OperationErrorEnum getErrorInfo() {
        return errorInfo;
    }
}

全局异常处理-多个处理器匹配顺序

参考:参考

多个处理器的两种情况:

存在一个类中

子类异常处理器优先

存在不同的类中

与多个异常处理类放入LinkedHashMap的顺序有关,
可以利用Order指定顺序,如果没有,则默认最小顺序;

那么,如果都没有指定顺序的话,那就是list中的顺序

对于过滤器和拦截器中的异常,有两种思路可以考虑

1、catch后通过转发到异常页面(设置ModelAndView)
参考:参考

2、拦截器中发生异常,拦截器中直接返回错误(通过response.getOutputStream().write() 直接写错误信息)
如:

     
         @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
     try {
     // 业务代码

 } catch (Exception e) {
            response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
            ResultVO<Object> resultVo = new ResultVO<>();
            resultVo.setStatus(HttpStatus.UNAUTHORIZED.value());
            resultVo.setErrorMsg(ACCESS_PARAM_ERROR.getErrorDesc());
            response.getOutputStream().write(new String(JSON.toJSONString(resultVo)).getBytes(StandardCharsets.UTF_8));
            logger.error("==== WhiteListAndAuthenticationInterceptor拦截器拦截到了方法:{} 解析鉴权参数异常  ====", methodName);
            return false;
        }
    }

你可能感兴趣的:(java,spring)