springboot统一处理异常,处理404,判断url等

/ 后端 / 没有评论 / 811浏览

统一处理异常

@RestControllerAdvice
public class CommonExceptionHandler {

    @ExceptionHandler(CommonException.class)
    public Result exception(CommonExceptionex) {
       ...
    }

    @ExceptionHandler(Exception.class)
    public Result exception(Exceptionex) {
       ...
    }
}

小技巧

通过错误日志,如何追踪到请求日志? 可以在过滤器通过埋点设置请求id

     request.setAttribute("requestId", UUID.randomUUID());

然后在需要打印日志的地方,统一打印该请求链请求id即可(使用MDC或者手动拼接);

request.getAttribute("requestId");

设置默认错误处理器

@RestController
public class DefaultErrorController extends AbstractErrorController {
   
    public DefaultErrorControllerPROD(ErrorAttributes errorAttributes) {
        super(errorAttributes);
    }

    @ResponseStatus(code = HttpStatus.OK)
    @RequestMapping(value = "/error", produces = MediaType.APPLICATION_JSON_VALUE)
    public R handleError(HttpServletRequest request) {
        Map<String, Object> errorAttributes = super.getErrorAttributes(request, true);
        Object status = errorAttributes.get("status");
        return R.error("错误码->" + status);
    }

    @Override
    public String getErrorPath() {
        return "/error";
    }
}

注意拦截器添加排除路径/error;

以前遇到拦截器引发的小问题

默认拦截所有路径

  @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenCheckInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns(excludePath)
                .order(1);
}

此处判断登录逻辑,并判断如果有注解@IgnoreToken则放行不用判断;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        IgnoreToken annotation;
        if (handler instanceof HandlerMethod) {
            annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreToken.class);
            if (annotation != null) {
                return true;
            }
        } 
        //处理判断登录逻辑...
        if(登录){
           return true;
        }
        return false;
}

以上设置导致的结果是不存在的url也会处理判断登录逻辑,然后不通过报错未登录,我们想要的是404;

问题在于,如果路径不存在对应controller,则不会存在对应的HandlerMethod,所以需要判断放行;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        IgnoreToken annotation;
        if (handler instanceof HandlerMethod) {
            annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreToken.class);
            if (annotation != null) {
                return true;
            }
        } else {
            //如果不存在,放行
            return true;
        }
}

手动判断是否存在url是否存在;

    @Autowired
    RequestMappingHandlerMapping requestMappingHandlerMapping;

    try {
            HandlerExecutionChain handler = requestMappingHandlerMapping.getHandler((HttpServletRequest) request);
        } catch (Exception e) {
            //不存在url
           
        }