@Component
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
ServerHttpRequest request = serverWebExchange.getRequest();
ServerHttpResponse response = serverWebExchange.getResponse();
Integer code = 200;
String message = "";
if(throwable instanceof SaTokenException) { //如果异常对象为SaTokenException的实现类
code = 401; //和登录、无权限等相关的错误返回用户无权限
message = "用户无权限";
} else {
code = 500; // 限流、熔断降级等错误返回系统繁忙
message = "系统繁忙";
}
Result fail = Result.fail(code, message);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON); //设置客户端返回的响应体数据格式是JSON
return response.writeWith(Mono.fromSupplier(new Supplier<DataBuffer>() {
@Override
public DataBuffer get() {
DataBufferFactory dataBufferFactory = response.bufferFactory();
byte[] bytes = null;
try {
bytes = objectMapper.writeValueAsBytes(fail);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
return dataBufferFactory.wrap(bytes);
}
}));
代码解读:
-
response.writeWith:方法是 Spring WebFlux 中用于将给定的 Publisher(发布者,在响应式编程中用于异步提供数据)中的数据写入到服务器响应体的方法。这里传入的参数是一个 Mono,Mono 是一种特殊的 Publisher,表示它最多只发布一个元素(在这个场景下,就是包含错误信息的 DataBuffer),非常适合用于返回单个响应体这种情况。
-
Mono.fromSupplier:方法接受一个 Supplier 接口的实现作为参数,并基于此创建一个 Mono。Supplier 接口是一个函数式接口,它定义了一个无参的 get 方法,用于提供一个值(在这里就是要返回一个 DataBuffer 对象)。
-
Supplier《DataBuffer》: 代表我们要获取一个DataBuffer对象,在匿名内部类中首先要创建DataBufferFactory工厂,用于创建DataBuffer对象(DataBuffer是响应体数据) 不同的实现可能对应不同的底层存储机制(比如内存、堆外内存等),而 DataBufferFactory 则提供了统一的创建方式来适配这些不同的场景。
-
objectMapper:是Jackson位于Jackson包下,用于 JSON 序列化和反序列化。此处将fail信息转为byte数组。
-
dataBufferFactory.wrap:方法是将字节数组 bytes 包装成一个 DataBuffer 对象。
此外,还需将全局过滤器中的异常处理删除,否则会覆盖全局异常处理