loveqq 作为网关框架时如何修改请求体 / 响应体,和 spring 又有什么区别?

前言

loveqq-framework 作为网关框架使用时,修改响应体是一个十分常见的需求。

而作为一个使用过 spring gateway 的作者,我觉得 spring gateway 中修改响应体实在是复杂,因此 loveqq 框架在实现修改响应体时,则力求简洁易用。

如何实现?

loveqq 框架修改响应体是基于网关过滤器(GatewayFilter)实现的,因此要实现修改响应体只需两步:

1、自定义网关过滤器

2、给指定的路由配置这个过滤器

下面给出相应的示例:

网关过滤器:

java 复制代码
    /**
     * 这里手动设置 bean name 为:FormatResponseBody
     * 后面配置时会用到,当然自动生成的也可以,只是名称比较长而已
     * <p>
     * 注意:这里设置过滤器优先级为最低级别,因为需要转发请求之后才能获取下游响应体,而转发过滤器默认的级别比较低
     */
    @Order(Integer.MAX_VALUE)
    @Component("FormatResponseBody")
    public static class FormatResponseBodyGatewayFilter implements GatewayFilter {

        @Override
        public Mono<Void> doFilter(ServerRequest request, ServerResponse response, GatewayFilterChain chain) {
            return chain.doFilter(request, response)
                    .then(Mono.defer(response::getAggregateBody))               // 可以直接获取聚合后的响应体,避免 Flux 分段处理数据
                    .map(e -> {
                        byte[] bytes = NIOUtil.read(e);
                        JSON json = new JSON();
                        json.put("data", new String(bytes));
                        json.put("code", 0);
                        return NIOUtil.from(json.toString());                   // 修改响应体
                    })
                    .flatMap(json -> response.writeBody(Flux.just(json)))       // 响应体写入响应
                    .then();
        }
    }

应用过滤器:

yaml 复制代码
k:
  server:
    gateway:
      routes:
        - uri: lb://demo
          predicates: Path=/api/demo/**
          filters:
            - id: StripPrefix               # 去除 /api
              args:
                stripPrefix: 1
            - id: FormatResponseBody        # 修改响应体

这样就可以了。

响应体校验不通过想抛出异常?

很简单,直接抛出异常就可以了,例如:

java 复制代码
        @Override
        public Mono<Void> doFilter(ServerRequest request, ServerResponse response, GatewayFilterChain chain) {
            return chain.doFilter(request, response)
                    .then(Mono.defer(response::getAggregateBody))               // 可以直接获取聚合后的响应体,避免 Flux 分段处理数据
                    .map(e -> {
                        String body = new String(NIOUtil.read(e));
                        if (body.charAt(0) != '{' || body.charAt(0) != '[') {
                            throw new ResolvableException("not json");
                        }
                        JSON json = new JSON();
                        json.put("data", body);
                        json.put("code", 0);
                        return NIOUtil.from(json.toString());                   // 修改响应体
                    })
                    .flatMap(json -> response.writeBody(Flux.just(json)))       // 响应体写入响应
                    .then();
        }

这样的话,网关会输出正常的错误信息吗?

当然可以,因为网关异常同样可以走 mvc 模式的全局异常处理器进行处理!

java 复制代码
@RestControllerAdvice(supportAny = true)
public class GlobalExceptionHandler {
    /**
     * 异常处理
     *
     * @param request 抽象的统一的请求对象
     * @param e       异常
     * @return 返回错误信息
     */
    @ExceptionHandler
    public String onException(ServerRequest request, Exception e) {
        return e.getClass().getName() + ":" + e.getMessage();
    }
}

看起来相当简洁,几乎和修改请求体没什么区别,但是 spring gateway 修改请求体 / 响应体想必做过的各位懂的都懂。

感兴趣的同学可以尝试一下~

相关推荐
涡能增压发动积1 天前
同样的代码循环 10次正常 循环 100次就抛异常?自定义 Comparator 的 bug 让我丢尽颜面
后端
Wenweno0o1 天前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
行乾1 天前
鸿蒙端 IMSDK 架构探索
架构·harmonyos
石小石Orz1 天前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
swg3213211 天前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
tyung1 天前
一个 main.go 搞定协作白板:你画一笔,全世界都看见
后端·go
gelald1 天前
SpringBoot - 自动配置原理
java·spring boot·后端
若风的雨1 天前
【deepseek】RISC-V 的CSR寄存器详解
架构
殷紫川1 天前
深入拆解 Java 内存模型:从原子性、可见性到有序性,彻底搞懂 happen-before 规则
java·后端
元宝骑士1 天前
FIND_IN_SET使用指南:场景、优缺点与MySQL优化策略
后端·mysql