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

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

相关推荐
IT枫斗者3 小时前
前端部署后如何判断“页面是不是最新”?一套可落地的版本检测方案(适配 Vite/Vue/React/任意 SPA)
前端·javascript·vue.js·react.js·架构·bug
小码哥_常3 小时前
解锁AI编程密码:程序员常用的10个AI提示词
后端
直奔標竿4 小时前
Java开发者AI转型第二十七课!Spring AI 个人知识库实战(六)——全栈闭环收官,解锁前端流式渲染终极技巧
java·开发语言·前端·人工智能·后端·spring
金銀銅鐵5 小时前
[java] 编译之后的记录类(Record Classes)长什么样子(上)
java·jvm·后端
uzong6 小时前
我研读了 500 个 Spring Boot 生产级代码库,90% 都犯了这 7 个致命错误
后端
AI自动化工坊6 小时前
Late框架技术深度解析:5GB VRAM实现10倍AI编码效率的工程架构
人工智能·5g·架构·ai编程·late
空中海6 小时前
第六篇:架构篇 — 微服务、部署、高并发与专家级能力
微服务·云原生·架构
xiaobaoyu6 小时前
ssm知识点梳理
后端
IT_陈寒7 小时前
Vite的public文件夹放静态资源?这坑我替你踩了
前端·人工智能·后端
浮游本尊7 小时前
合同同步逻辑
后端