Spring Cloud Gateway之全局异常拦截器
阅读原文时间:2021年11月25日阅读:1

/**
* @version 2019/8/14
* @description: 异常拦截器
* @modified:
*/
@Slf4j
public class JsonExceptionHandler implements ErrorWebExceptionHandler {

/\*\*  
 \* MessageReader  
 \*/  
private List<HttpMessageReader<?>> messageReaders = Collections.emptyList();

/\*\*  
 \* MessageWriter  
 \*/  
private List<HttpMessageWriter<?>> messageWriters = Collections.emptyList();

/\*\*  
 \* ViewResolvers  
 \*/  
private List<ViewResolver> viewResolvers = Collections.emptyList();

/\*\*  
 \* 存储处理异常后的信息  
 \*/  
private ThreadLocal<ResEntity> exceptionHandlerResult = new ThreadLocal<>();

/\*\*  
 \* 参考AbstractErrorWebExceptionHandler  
 \*/  
public void setMessageReaders(List<HttpMessageReader<?>> messageReaders) {  
    Assert.notNull(messageReaders, "'messageReaders' must not be null");  
    this.messageReaders = messageReaders;  
}

/\*\*  
 \* 参考AbstractErrorWebExceptionHandler  
 \*/  
public void setViewResolvers(List<ViewResolver> viewResolvers) {  
    this.viewResolvers = viewResolvers;  
}

/\*\*  
 \* 参考AbstractErrorWebExceptionHandler  
 \*/  
public void setMessageWriters(List<HttpMessageWriter<?>> messageWriters) {  
    Assert.notNull(messageWriters, "'messageWriters' must not be null");  
    this.messageWriters = messageWriters;  
}

@Override  
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {  
    // 按照异常类型进行处理 默认500  

      int httpStatus = HttpStatus.INTERNAL_SERVER_ERROR.value();
      String body = "系统异常,请联系管理员";
      if (ex instanceof NotFoundException) {
      httpStatus = HttpStatus.NOT_FOUND.value();
       body = ex.getMessage();
      }else if(ex instanceof ResponseStatusException){
      ResponseStatusException responseStatusException = (ResponseStatusException) ex;
      httpStatus = responseStatusException.getStatus().value();
      body = responseStatusException.getMessage();
      } else if (ex instanceof BusinessException) {
      body = ex.getMessage();
      httpStatus = ((BusinessException) ex).toResEntity().getHttpStatus();
      } else if (ex instanceof RuntimeException) {
      Throwable cause = ex.getCause();
       body = ex.getMessage();
      if(null != cause && cause.getMessage().contains("Load balancer does not have available server for client")){
       body = "服务不存在";
       }
      }
      //错误记录
ServerHttpRequest request = exchange.getRequest();
log.error("[全局异常处理]异常请求路径:{}", request.getPath());
log.error("异常详细信息:{}",ex);
//封装响应体
ResEntity res = new ResEntity();
res.setHttpStatus(httpStatus);
res.setMsg(body);

    //参考AbstractErrorWebExceptionHandler  
    if (exchange.getResponse().isCommitted()) {  
        return Mono.error(ex);  
    }  
    exceptionHandlerResult.set(res);  
    ServerRequest newRequest = ServerRequest.create(exchange, this.messageReaders);  
    return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse).route(newRequest)  
            .switchIfEmpty(Mono.error(ex))  
            .flatMap((handler) -> handler.handle(newRequest))  
            .flatMap((response) -> write(exchange, response));

}

/\*\*  
 \* 参考DefaultErrorWebExceptionHandler  
 \*/  
protected Mono<ServerResponse> renderErrorResponse(ServerRequest request) {  
    ResEntity result = exceptionHandlerResult.get();

    //404 因前端框架问题,不转换处理 ,因此目前只有系统报500才转换为自定义的状态码  
    if(HttpStatus.INTERNAL\_SERVER\_ERROR.value() == result.getHttpStatus()){  
        return ServerResponse.status(HttpStatus.OK.value())  
                .contentType(MediaType.APPLICATION\_JSON\_UTF8)  
                .body(BodyInserters.fromObject(result));  
    }  
    return ServerResponse.status(result.getHttpStatus())  
            .contentType(MediaType.APPLICATION\_JSON\_UTF8)  
            .body(BodyInserters.fromObject(result));  
}

/\*\*  
 \* 参考AbstractErrorWebExceptionHandler  
 \*/  
private Mono<? extends Void> write(ServerWebExchange exchange,  
                                   ServerResponse response) {  
    exchange.getResponse().getHeaders()  
            .setContentType(response.headers().getContentType());  
    return response.writeTo(exchange, new ResponseContext());  
}

/\*\*  
 \* 参考AbstractErrorWebExceptionHandler  
 \*/  
private class ResponseContext implements ServerResponse.Context {

    @Override  
    public List<HttpMessageWriter<?>> messageWriters() {  
        return JsonExceptionHandler.this.messageWriters;  
    }

    @Override  
    public List<ViewResolver> viewResolvers() {  
        return JsonExceptionHandler.this.viewResolvers;  
    }  
}  

}