异常处理器与拦截器 深入探究 --拦截器状态码无法被识别
首先来阐述前景提要 我先是做了一个什么拦截器
那么前面发生了什么问题呢?
首先客户端的每一个请求都需要经过两个拦截器 然后报错的话直接返回
Java @Slf4j @RestControllerAdvice public class WebExceptionAdvice { @ExceptionHandler(RuntimeException.class) public Result handleRuntimeException(RuntimeException e) { log.error(e.toString(), e); return Result.fail(“服务器异常”); } }
报错就直接报服务器异常了 虽然在拦截器2中也有设置状态码
Java public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //1.判断是否需要拦截(ThreadLocal中是否有用户) if (UserHolder.getUser() == null&&ListenerHolder.getListener()==null) { response.setStatus(10002); System.out.println(“拦截器报错啦!!!”); response.getHeader(“erro”); return false; } return true; } }
但实际上 在支付宝小程序中这里的状态码却无法被识别 这是一个极其奇怪的事情 在前端看到的状态码是不一样的
后面发现在定义fail的时候就把外层的状态码给定死为了200!这是个极其不好的点 设计的时候贪图方便没有管他 导致了后面 实际发生异常跟没有登录的报错没办法区分开 于是 我做了以下的改进
首先是重写了 报错体系
Java @Slf4j @RestControllerAdvice public class WebExceptionAdvice { @ExceptionHandler(RuntimeException.class) public ResponseEntity handleRuntimeException(HttpServletRequest request, RuntimeException e) { log.error(e.toString(), e); Result result = Result.fail(“服务器异常”); HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR; if (e instanceof UnAuthorException) { //这个是拦截器报错才设置的状态码 status = HttpStatus.UNAUTHORIZED; } ResponseEntity resultResponseEntity = new ResponseEntity<>(result, status); log.error(resultResponseEntity.toString()); return resultResponseEntity; } }
自己定义了一个特殊的错误类型 用到RuntimeException 下面是他的定义
Java public class UnAuthorException extends RuntimeException { public UnAuthorException(String message) { super(message); } }//非常简单_
然后在合适的地方抛出他 当然是在拦截器中 表示用户未登录的时候 抛出这个自定义异常UnAuthorException
Java public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //1.判断是否需要拦截(ThreadLocal中是否有用户) if (UserHolder.getUser() == null&&ListenerHolder.getListener()==null) { System.out.println(“拦截器报错啦!!!”); //response.getHeader(“erro”); throw new UnAuthorException(“用户未登录”); } return true; } }
后面反思了一下为什么没被识别到状态码 因为在定义Result对象的时候 对于fail方法并没有重新定义他的状态码 这是个很大的问题 在下一个项目中不应该出现 应该提前定义好