【Spring cloud gateway 获取RequestBody】

Spring cloud gateway 获取RequestBody

在gateway中获取请求的json 数据



环境

项目开发所在环境

名称版本号
spring cloud alibaba2021.0.4.0
spring gateway3.1.6
spring boot2.6.11

提示:以下是本篇文章正文内容,下面案例可供参考

一、自定义读取RequestBody的bean

此类主要继承 ReadBodyRoutePredicateFactory 一定要自己查看下此类

import org.springframework.cloud.gateway.handler.predicate.ReadBodyRoutePredicateFactory;
import org.springframework.stereotype.Component;

/**
 * @ClassName JsonReadBodyRoutePredicate
 * @Description gateway 中 读取 请求的jsonBody
 * 这里是 将 请求数据中的json 放到 'cachedRequestBodyObject' 此属性中
 * @Version 1.0
 */
@Component
public class JsonReadBodyRoutePredicate extends ReadBodyRoutePredicateFactory {
// 此类可重写,亦可不重写 ,根据自己需要
// 父类方法完全够我用的,所以不做改动
}

二、自定义根据数据判断是否继续路由的bean

继承Predicate 由于我们能的json 是字符串 所以是String类型

import org.springframework.stereotype.Component;

import java.util.function.Predicate;

/**
 * @ClassName JsonRequestBody
 * @Version 1.0
 */
@Component
public class JsonRequestBodyPredicate implements Predicate<String> {

    /**
     * @param reqJson 此json 为请求的json字符串
     * @return 如果返回true则继续路由访问真正的接口,如果返回false 则不会路由
     */
    @Override
    public boolean test(String reqJson) {
        // 这里可以根据 请求字符串 或者 自行添加 path 来判断是否需要继续路由
        return true;
    }
}

三、修改路由配置

(新增) 表示 需要添加的配置

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: user-server-route
          uri: lb://user-server
          predicates:
            - Path=/user-api/**
            - name: JsonReadBodyRoutePredicate # 新增 这里是(一)中定义的bean
              args: # 新增
                inClass: "java.lang.String"  # 新增 这里要注意 springboot 2.6以后使用此写法
#                inClass: "#{T(String)}" #spring boot 2.5(包含2.5)以下 使用此写法
                predicate: "#{@jsonRequestBodyPredicate}" # 新增 这里是(二)中定义的bean
          filters:
            - StripPrefix=1
            - name: Retry  # Retry 为重试过滤器,当后端服务不可用时,网关会根据配置参数来发起重试请求
              args:
                retries: 3
                status: 505

四、怎么获取

获取Json 中有2个地方 ,第一 :(二)中配置的bean 可直接获取json 第二:使用全局拦截器,然后从exchange中获取
第一种,自行debug 查看就好,主要说第二种

创建全局过滤

代码如下


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Optional;

/**
 * @ClassName ElapseFilter
 * @Description 计时过滤器--全局过滤器
 * @Author [Miller-hw]
 * @Version 1.0
 */
//全局过滤器必须实现两个接口:GlobalFilter、Ordered
//GlobalFilter是全局过滤器接口,实现类要实现filter()方法进行功能扩展
//Ordered接口用于排序,通过实现getOrder()方法返回整数代表执行当前过滤器的前后顺序
@Component
public class GatewayGlobalFilter implements GlobalFilter, Ordered {
    private static final Logger log = LoggerFactory.getLogger(GatewayGlobalFilter.class);
    private static final String SERVICE_TIME_BEGIN = "serviceTimeBegin";

// 这个放我 我写了记录 接口耗时的方法 有其他需求自行填写
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 记录请求时间 和 ip
        ServerHttpRequest request = exchange.getRequest();
        if (null == request) {
            exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
            return exchange.getResponse().setComplete();
        }
        List<String> remoteAddressList = request.getHeaders().get("Remote_address");// 当走nginx转发时,获取此值 真实用户IP
        String remoteAddressStr = (null != remoteAddressList && !remoteAddressList.isEmpty()) ? remoteAddressList.get(0) : "empty";
        exchange.getAttributes().put(SERVICE_TIME_BEGIN, System.currentTimeMillis());


        // 如果需要获取请求头 ,只支持json,其他格式无法解析
//        Object reqJson = exchange.getAttributes().get("cachedRequestBodyObject");

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            long endTime = System.currentTimeMillis();
            Long startTime = exchange.getAttribute(SERVICE_TIME_BEGIN);
            Optional.ofNullable(startTime).ifPresent(l->{
                String reqPath = request.getRemoteAddress()+"("+Optional.ofNullable(remoteAddressStr).orElse("empty")+")" + "|" + request.getPath() + "| cost " + (endTime - startTime) + "ms";
                log.warn(reqPath);
            });
        }));
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

结束

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值