SpringCloud GateWay通过过滤器GatewayFilter修改请求或响应内容

本文介绍了如何在Spring Cloud Gateway中通过创建GatewayFilter获取和修改请求体内容。利用ServerWebExchange作为服务网络交换器,实现了针对application/json和application/x-www-form-urlencoded类型请求的处理,并讨论了如何通过ServerHttpResponseDecorator装饰器统一处理返回数据。
摘要由CSDN通过智能技术生成

Spring Cloud Gateway在有些场景中需要获取request body内容进行参数校验或参数修改,我们通过在GatewayFilter中获取请求内容来获取和修改请求体,下面我们就基于ServerWebExchange来实现:

ServerWebExchange命名为服务网络交换器,存放着重要的请求-响应属性、请求实例和响应实例等等,有点像Context的角色,其中有两个重要的接口方法:

   // 获取ServerHttpRequest对象
    ServerHttpRequest getRequest();

    // 获取ServerHttpResponse对象
    ServerHttpResponse getResponse();

创建一个GatewayFilter,必须实现Ordered接口,返回一个小于-1的order值,这是因为NettyWriteResponseFilter的order值为-1,我们需要覆盖返回响应体的逻辑,自定义的GlobalFilter必须比NettyWriteResponseFilter优先执行。

public class RequestGatewayFilter implements GatewayFilter, Ordered {
   
@Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
   
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();

        // 处理参数
        MediaType contentType = headers.getContentType();

        if (exchange.getRequest().getMethod().equals(HttpMethod.POST)) {
   
        //Content-type为“application/json”
            if (MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) {
   
                return readBody(exchange, chain);
            }
            //Content-type为“application/x-www-form-urlencoded”
            else if(MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)){
   
                GatewayContext gatewayContext = new GatewayContext();
                gatewayContext.setRequestHeaders(headers);
                gatewayContext.getAllRequestData().addAll(request.getQueryParams());
                exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT,gatewayContext);

                return readFormData(exchange, chain, gatewayContext);

            }
//Content-type为“multipart/form-data”
else if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) {
   
                GatewayContext gatewayContext = new GatewayContext();
                gatewayContext.setRequestHeaders(headers);
                gatewayContext.getAllRequestData().addAll(request.getQueryParams());
                exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT,gatewayContext);

                return readMultipartData(exchange, chain, gatewayContext);
            }
        } else {
   
            return readGetData(exchange, chain);
        }
        return chain.filter(exchange);
    }
    @Override
    public int getOrder() {
   
        return -2;
    }
}

处理content-type为application/json的方法:

/**
     * ReadJsonBody
     *
     * @param exchange
     * @param chain
     * @return
     */
    private Mono<Void> readBody(ServerWebExchange exchange, GatewayFilterChain chain) {
   
        /**
         * join the body
         */
        return DataBufferUtils.join(exchange.getRequest().getBody(
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
除了全局过滤器之外,Spring Cloud Gateway还提供了局部过滤器的功能,可以对某个路由进行特定的处理。 使用局部过滤器,需要在路由配置中添加一个filters属性,并且在该属性中指定过滤器的名称或者类名。例如: ```yaml spring: cloud: gateway: routes: - id: myRoute uri: http://localhost:8080 predicates: - Path=/myPath/** # 添加一个局部过滤器 filters: - MyLocalFilter ``` 上面的配置中,我们为名为myRoute的路由添加了一个局部过滤器MyLocalFilter,该过滤器可以是一个Bean的名称或者一个类的全限定名。如果是一个类的全限定名,则需要通过@Component或者@Bean注解将该类加入到Spring容器中。 在局部过滤器中,同样需要实现GatewayFilter接口,并且实现filter方法。在该方法中,可以对请求进行特定的处理,例如添加请求头、修改请求等。 下面是一个示例代码: ```java @Component public class MyLocalFilter implements GatewayFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 在请求头中添加一个自定义的token exchange.getRequest().mutate().header("token", "myToken").build(); // 继续执行过滤器链 return chain.filter(exchange); } } ``` 在上面的代码中,我们实现了一个局部过滤器,将一个自定义的token添加到请求头中,并且继续执行过滤器链。在这个过程中,可以通过exchange对象获取到请求响应等信息。 需要注意的是,局部过滤器只对指定的路由进行处理,如果需要对多个路由进行相同的处理,可以将该过滤器添加到多个路由的filters属性中。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值