ControllerAdvice或者RestControllerAdvice无效问题

项目中使用springboot Security的时候,配置的ControllerAdvice全局异常失效了

正常使用全局异常捕获没有问题,我是这样使用的

  • GlobalExceptionHanlder
//基于@ControllerAdvice注解的Controller层的全局异常统一处理
@ControllerAdvice
public class GlobalExceptionHanlder {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHanlder.class);

    // Throwable是所有异常的父类
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(value = Throwable.class)
    @ResponseBody
    public RestResponse handler(HttpServletRequest req, Throwable throwable){
        String errmsg = throwable.getMessage();
        StackTraceElement[] stackTraceElements = throwable.getStackTrace();
        if (stackTraceElements.length != 0){
            StackTraceElement stackTraceElement = stackTraceElements[0];
            errmsg += "\n" + "问题出处:" + stackTraceElement.toString();
        }
        logger.error(errmsg, throwable);
        RestCode restCode = Exception2CodeRepo.getCode(throwable);
        RestResponse response = RestResponse.error(restCode);
        return response;
    }
}
 
 
  • Exception2CodeRepo,这类是把常出现的异常统一识别处理了
public class Exception2CodeRepo {
    private static Object getType(Throwable throwable) {
        try {
            return FieldUtils.readDeclaredField(throwable, "type", true);
        } catch (Exception e) {
            return null;
        }
    }
    public static RestCode getCode(Throwable throwable) {
        if (throwable == null) {
            return RestCode.UNKNOWN_ERROR_NULL;
        }
        RestCode restCode = exceptionType(throwable);
        return restCode;
    }
    private static RestCode exceptionType(Throwable throwable){
        /**
         * HttpMediaTypeNotSupportedException
         */
        String exceptionString = throwable.toString();
        if (exceptionString.contains("HttpMessageConversionException")){
            return RestCode.PARSMS_TYPE_ERROR;
        }else if (exceptionString.contains("NullPointerException")
                || exceptionString.contains("BeanPropertyBindingResult")
                || exceptionString.contains("MissingServletRequestParameterException")
                || exceptionString.contains("MethodArgumentNotValidException")){
            return RestCode.ParamsAndInstanceIsNull;
        }else if (exceptionString.contains("HttpMediaTypeNotSupportedException")){
            return RestCode.HttpMediaTypeNotSupportedException;
        }else if (exceptionString.contains("HttpRequestMethodNotSupportedException")){
            return RestCode.HttpRequestMethodNotSupportedException;
        }else if (exceptionString.contains("HttpMessageNotReadableException")
                || exceptionString.contains("JsonParseException")
                || exceptionString.contains("JSONException")){
            return RestCode.JsonParseException;
        }else if (exceptionString.contains("DuplicateKeyException")){
            return RestCode.RepeatAddData;
        }else if (exceptionString.contains("MissingServletRequestPartException")){
            return RestCode.NoNeedUploadFile;
        }else if (exceptionString.contains("请登录")){
            return RestCode.NoLogin;
        }else if (exceptionString.contains("请注册")){
            return RestCode.NoRegister;
        }else if (exceptionString.contains("登录已过期")){
            return RestCode.LoginTokenExpired;
        }else if (exceptionString.contains("token无效")){
            return RestCode.TokenInvalid;
        }
        return RestCode.UNKNOWN_ERROR;
    }
}
接下来出现问题了

当你项目中使用springboot Security的时候,上面配置的全局异常失效了。这是因为Security的异常捕获覆盖了ControllerAdvice或者他们有冲突了导致失效,这个时候需要改变或者拦截Security的异常。【我在百度上,搞了好长时间,都没有找到问题,最后不得已去了google】

  • 1、处理如下,修改原来的全局异常,继承OncePerRequestFilter
@Component
public class GlobalExceptionHanlderFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHanlderFilter.class);

    public void handler(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Throwable throwable) throws IOException {
        String errmsg = throwable.getMessage();
        StackTraceElement[] stackTraceElements = throwable.getStackTrace();
        if (stackTraceElements.length != 0){
            StackTraceElement stackTraceElement = stackTraceElements[0];
            errmsg += "\n" + "问题出处:" + stackTraceElement.toString();
        }
        logger.error(errmsg, throwable);
        RestCode restCode = Exception2CodeRepo.getCode(throwable);
        RestResponse response = RestResponse.error(restCode);

        PrintWriterOut.writeOut(httpServletRequest, httpServletResponse, 200, response);
    }
    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
        try {
            filterChain.doFilter(httpServletRequest, httpServletResponse);
        }catch (Throwable e) {
            this.handler(httpServletRequest, httpServletResponse, e);
        }
    }
}
 
 
  • 2、配置Security中的异常过滤器,直接覆盖这个bean就行。把自定义的过滤器添加进去
@Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new GlobalExceptionHanlderFilter());
        // 任何接口路径都要执行
        bean.addUrlPatterns("/*");
        // 优先级最高
        bean.setOrder(Integer.MIN_VALUE);
        return bean;
    }

项目测试没有问题,正常捕获异常,Security的权限、角色、账号密码异常还是Security自己处理

你可能感兴趣的:(ControllerAdvice或者RestControllerAdvice无效问题)