异常处理器与拦截器 深入探究 --拦截器状态码无法被识别
不多bb 直入主题
首先来阐述前景提要 我先是做了一个什么拦截器
下面是引用回我之前做过的思维导图 以及拦截器的实现
拦截器
那么前面发生了什么问题呢?
首先客户端的每一个请求都需要经过两个拦截器 然后报错的话直接返回
代码语言:text复制Java
@Slf4j
@RestControllerAdvice
public class WebExceptionAdvice {
@ExceptionHandler(RuntimeException.class)
public Result handleRuntimeException(RuntimeException e) {
log.error(e.toString(), e);
return Result.fail(“服务器异常”);
}
}
报错就直接报服务器异常了 虽然在拦截器2中也有设置状态码
代码语言:text复制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!这是个极其不好的点 设计的时候贪图方便没有管他 导致了后面 实际发生异常跟没有登录的报错没办法区分开 于是 我做了以下的改进
首先是重写了 报错体系
代码语言:text复制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 下面是他的定义
代码语言:text复制Java
public class UnAuthorException extends RuntimeException {
public UnAuthorException(String message) {
super(message);
}
}//非常简单_
然后在合适的地方抛出他 当然是在拦截器中 表示用户未登录的时候 抛出这个自定义异常UnAuthorException
代码语言:text复制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方法并没有重新定义他的状态码 这是个很大的问题 在下一个项目中不应该出现 应该提前定义好