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 修改请求体 / 响应体想必做过的各位懂的都懂。

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

相关推荐
aiopencode2 小时前
Swift 加密工具推荐,构建可落地的多层安全体系(源码混淆+IPA 加固+动态对抗+映射治理)
后端
Moe4882 小时前
合并Pdf、excel、图片、word为单个Pdf文件的工具类(技术点的选择与深度解析)
java·后端
又过一个秋2 小时前
CyberRT Transport传输层设计
后端
Java水解2 小时前
20个高级Java开发面试题及答案!
spring boot·后端·面试
Moe4882 小时前
合并Pdf、excel、图片、word为单个Pdf文件的工具类(拿来即用版)
java·后端
bcbnb2 小时前
手机崩溃日志导出的工程化方法,构建多工具协同的跨平台日志获取与分析体系(iOS/Android 全场景 2025 进阶版)
后端
Java水解2 小时前
为何最终我放弃了 Go 的 sync.Pool
后端·go
二川bro3 小时前
第41节:第三阶段总结:打造一个AR家具摆放应用
后端·restful
油丶酸萝卜别吃3 小时前
什么是分布式?什么是微服务?什么是集群?什么是单体?这些都是什么?又有什么关联?
分布式·微服务·架构