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

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

相关推荐
vipxieliang1 分钟前
事件驱动架构实战:解耦、异步与可扩展性
架构
回家路上绕了弯3 分钟前
Agent in the Sandbox:当 AI 有了自己的开发环境
后端
陈随易12 分钟前
TanStarter,从搭建到支付,一步到位开始赚美元
前端·后端·程序员
Rain的Java大神之路13 分钟前
公交App上“还有2站,约5分钟”怎么实现?90%的人答错这道大厂面试题:GPS漂移、ETA不准、10万QPS热点读全拆透(附完整代码)
java·后端·面试
挖掘狂人17 分钟前
MySQL 深分页优化:limit 100000, 10 慢在哪,怎么救
后端·sql·mysql
敲代码的小小酥1 小时前
谈SpringMVC与Spring WebFlux的区别与适用场景
java·后端·spring
IT_陈寒1 小时前
Redis开发实战:从入门到精通
前端·人工智能·后端
日日大王学编程1 小时前
2026主流AI Agent产品分类、核心差异与技术特性全解析
人工智能·后端·python
mldong1 小时前
同一个节点接力办几轮,流程才往下走:jeeflow 的后加签
后端·架构
量化分析码农1 小时前
【Python量化多因子实战 03】多因子怎么合成?等权、IC 加权与回归加权实测
后端