Spring Cloud Gateway实践(一):获取参数

这篇具有很好参考价值的文章主要介绍了Spring Cloud Gateway实践(一):获取参数。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

SCG(Spring Cloud Gateway)就我个人理解,是想让开发者把它作为一个较为简单的网关框架,只需简单在yml文件中写几个配置项就可以运行。所以它不大推荐在网关这一层获取body数据或者做一下复杂的业务处理。故而在实际编写代码中,获取queryParam很容易,但body数据就比较麻烦了,如果要修改就更麻烦。在本篇文章主要讨论如何获取请求方式中的参数。
SCG获取参数一般有两种方式:

  1. 通过Filter过滤器
  2. 通过Predicate断言

原理都类似,通过事先缓存doby到attribute中,再读取。至于这两种区别主要在于缓存方式:filter直接加一层globalFilter即可,而Predicate则需要加一个配置项。具体请看代码

配置Filter获取

import lombok.NonNull;  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.cloud.gateway.filter.GatewayFilterChain;  
import org.springframework.cloud.gateway.filter.GlobalFilter;  
import org.springframework.core.Ordered;  
import org.springframework.core.io.buffer.DataBuffer;  
import org.springframework.core.io.buffer.DataBufferUtils;  
import org.springframework.http.server.reactive.ServerHttpRequest;  
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;  
import org.springframework.stereotype.Component;  
import org.springframework.web.server.ServerWebExchange;  
import reactor.core.publisher.Flux;  
import reactor.core.publisher.Mono;  
   
@Component  
public class ReadParamFilter implements GlobalFilter, Ordered {  
  
    @Override  
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {  
        if (exchange.getRequest().getHeaders().getContentType() == null) {  
            return chain.filter(exchange);  
        } else {  
            return DataBufferUtils.join(exchange.getRequest().getBody())  
                    .flatMap(dataBuffer -> {  
                        DataBufferUtils.retain(dataBuffer);  
                        Flux<DataBuffer> cachedFlux = Flux  
                                .defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));  
                        ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {  
                            @Override  
                            public @NonNull Flux<DataBuffer> getBody() {  
                                return cachedFlux;  
                            }  
  
                        };  
                        exchange.getAttributes().put("cachedRequestBodyObject", cachedFlux);   
                    });  
        }  
    }  
  
    @Override  
    public int getOrder() {  
        return Ordered.HIGHEST_PRECEDENCE;  
    }  
}

缺点:在断言阶段不能获取参数

配置Predicate获取

predicate缓存request body需要加一个配置项

spring:  
  cloud:  
    gateway:  
      predicate:  
        read-body:  
          enabled: true 

另外再加一个读取body的Predicate类。


## 断言类

```java
@Component  
public class BodyPredicate implements Predicate {  
   @Override  
   public boolean test(Object o) {  
      return true;  
   }  
}


缓存到之后,后边获取参数就比较方便了。文章来源地址https://www.toymoban.com/news/detail-750226.html

获取参数

@Service  
public class ParamFactory {  
   @Autowired  
   Map<String, ParamStrategy> getParamFactoryMap;  
  
   public ParamStrategy getParamStrategy(HttpMethod requestMethod){  
      return getParamFactoryMap.get(requestMethod.name());  
   }  
}

获取参数策略

public abstract class ParamStrategy {  
  
    public RequestParamBO analyzeRequestParam(ServerWebExchange exchange) {  
        return doAnalyzeRequestParam(exchange);  
    }  
  
    /**  
     * 解析请求数据  
     *  
     * @param exchange  
    * @return  
     */  
    protected abstract RequestParamBO doAnalyzeRequestParam(ServerWebExchange exchange);  
  
    /**  
     * 获取某个请求参数  
     *  
     * @param requestMessage  
     * @param paramKey  
     * @param position  
     * @return  
     */  
    public abstract String getParamValue(RequestMessageBO requestMessage, String paramKey,  
                                         String position);  
  
  
}

get

@Component("GET")  
public class GetParamStrategy extends ParamStrategy {  
  
    /**  
     * 解析请求数据  
     *  
     * @param exchange@return  
     */    @Override  
    protected RequestParamBO doAnalyzeRequestParam(ServerWebExchange exchange) {  
        Map<String, String> paramMap = new HashMap<>();  
        MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();  
        if (!queryParams.isEmpty()) {  
            paramMap =  
                    queryParams.entrySet().stream()  
                            .collect(  
                                    Collectors.toMap(  
                                            Map.Entry::getKey,  
                                            entry -> {  
                                                List<String> list =  
                                                        new ArrayList<>(entry.getValue());  
                                                // list包含空数据  
                                                list.removeIf(Objects::isNull);  
                                                if (list.size() != 0) {  
                                                    return entry.getValue().get(0);  
                                                } else {  
                                                    return "";  
                                                }  
                                            }));  
        }  
        return RequestParamBO.builder()  
                .queryParams(paramMap)  
                .build();  
    }  
  
    @Override  
    public String getParamValue(RequestMessageBO requestMessage, String paramKey, String position) {  
        Map<String,String> queryParam = requestMessage.getParam().getQueryParams();  
        if (CollectionUtils.isEmpty(queryParam)){  
            return null;  
        }  
        return queryParam.get(paramKey);  
    }  

}

post

@Component("POST")  
public class PostParamStrategy extends ParamStrategy {  
  
    private static final String XW_FORM_PARAM_REGEX = "&";  
    private static final String XW_KEY_VALUE_REGEX = "=";  
  
    /**  
     * 解析请求数据  
     *  
     * @param exchange  
     * @return  
     */  
    @Override  
    protected RequestParamBO doAnalyzeRequestParam(ServerWebExchange exchange) {  
        Map<String, String> paramMap = new HashMap<>();  
        Map<String, Object> attributes = exchange.getAttributes();  
        MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();  
        RequestParamBO requestParams = new RequestParamBO();  
        if (CollectionUtil.isNotEmpty(queryParams)) {  
            paramMap =  
                    queryParams.entrySet().stream()  
                            .collect(  
                                    Collectors.toMap(  
                                            Map.Entry::getKey,  
                                            entry -> {  
                                                List<String> list =  
                                                        new ArrayList<>(entry.getValue());  
                                                // list包含空数据  
                                                list.removeIf(Objects::isNull);  
                                                if (list.size() != 0) {  
                                                    return entry.getValue().get(0);  
                                                } else {  
                                                    return "";  
                                                }  
                                            }));  
        }  
        requestParams.setQueryParams(paramMap);  
        MediaType contentType = exchange.getRequest().getHeaders().getContentType();  
        String body = (String) attributes.get(CACHE_REQUEST_BODY_OBJECT);  
  
        if (MULTIPART_FORM_DATA.isCompatibleWith(contentType)) {  
            assert contentType != null;  
            requestParams.setFormParams(getFormParam(contentType.toString(), body));  
        } else if (APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) {  
            requestParams.setFormParams(getXwFormParam(body));  
        } else if (APPLICATION_JSON.isCompatibleWith(contentType)) {  
            //json body就直接作为String处理保存了,
            requestParams.setJsonBody(body);  
        }  
  
        return requestParams;  
    }  
  
    @Override  
    public String getParamValue(RequestMessageBO requestMessage, String paramKey, String position) {  
        MediaType mediaType = requestMessage.getMediaType();  
        if (APPLICATION_JSON.isCompatibleWith(mediaType)) {  
            Object document = Configuration.defaultConfiguration()  
                    .jsonProvider().parse(requestMessage.getParam().getJsonBody());  
            JSONArray paramValues = Objects.requireNonNull(JsonPath.read(document, position));  
            return String.valueOf(paramValues.get(0));  
        }else {  
            return requestMessage.getParam().getFormParams().get(paramKey);  
        }  
    }  
  
   //获取 表单数据
  
    @SneakyThrows  
    private Map<String, String> getFormParam(String contentType, String bodyString) {  
  
        String boundary = contentType.substring(contentType.lastIndexOf("boundary=") + 9);  
        Map<String, String> formMap = Maps.newHashMap();  
        String part =  
                "^\r\nContent-Disposition: form-data; name=\"([^/?]+)\"\r\n\r\n([^/?]+)\r\n--?$";  
        Pattern r = Pattern.compile(part);  
        String[] split = bodyString.split(boundary);  
        for (int x = 1; x < split.length - 1; x++) {  
            Matcher m = r.matcher(split[x]);  
            if (m.find()) {  
                String name = m.group(1);  
                String value = m.group(2);  
                formMap.put(name, value);  
            }  
        }  
        return formMap;  
    }  
  //获取xw表单数据
    private Map<String, String> getXwFormParam(String bodyStr) {  
        Map<String, String> paramMap = new HashMap<>();  
        try {  
            bodyStr = URLDecoder.decode(bodyStr, "utf-8");  
        } catch (UnsupportedEncodingException e) {  
            throw new RuntimeException(e);  
        }  
        String[] params = bodyStr.split(XW_FORM_PARAM_REGEX);  
        for (String paramKeyValue : params) {  
            String[] keyValue = paramKeyValue.split(XW_KEY_VALUE_REGEX);  
            if (keyValue.length == 2) {  
                paramMap.put(keyValue[0], keyValue[1]);  
            }  
        }  
        return paramMap;  
    }
}

到了这里,关于Spring Cloud Gateway实践(一):获取参数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Kubernetes-03-实践篇 Spring-cloud-kubernetes 自动引入 K8S的 ConfigMap 参数(参数引用 和 文件挂载)

    此篇文章中,我们将讲述如何从configMap中引入参数配置,如何从挂载文件中引入文件配置。其中文件挂载是应用部署中常见的形式。 1、通过 valueRef 引入 ConfigMap 配置信息 1.1: 初始化项目 1.2: 定义将外部引入的配置项 1.3: 构建镜像 发布应用 1.4: 确认配置的引用 2、通过 fileMo

    2024年02月03日
    浏览(42)
  • spring cloud gateway中出现503 spring cloud gateway中出现503

    当搭建网关模块的时候出现503的错误的最大的可能就是没有设置负载均衡的依赖包  原先搭建的时候采用的是下面的方式进行设置的 上面的这种方式可以直接进行注册和发现,但是要求必须导入下面的依赖 希望简单的随笔能够帮助你!

    2024年02月11日
    浏览(48)
  • 【Spring Cloud 八】Spring Cloud Gateway网关

    【Spring Cloud一】微服务基本知识 【Spring Cloud 三】Eureka服务注册与服务发现 【Spring Cloud 四】Ribbon负载均衡 【Spring Cloud 五】OpenFeign服务调用 【Spring Cloud 六】Hystrix熔断 【Spring Cloud 七】Sleuth+Zipkin 链路追踪 在项目中是使用了Gateway做统一的请求的入口,以及统一的跨域处理以及

    2024年02月12日
    浏览(46)
  • Spring Cloud Gateway 超时、CORS配置 | Spring Cloud 17

    Spring Cloud Gateway 可以为所有路由配置 Http 超时(响应和连接) ,并为每个特定路由覆盖设置。 配置全局 http 超时: connect-timeout 必须 以毫秒为单位 指定。 response-timeout 必须指定为 java.time.Duration 使用示例:

    2024年02月14日
    浏览(53)
  • Spring Cloud Gateway

    目录 一、Spring Cloud Gateway 1、网关介绍 2、GateWay 3、GateWay项目搭建 4、GateWay配置路由的两种方式 4.1、YML配置 4.2、配置类 5、GateWay实现负载均衡 5.1、自动负载均衡 5.2、手动负载均衡 6、GateWay断言Predicate 7、GateWay的Filter         在 微服务架构 中,一个 系统会被拆分为很多

    2024年02月10日
    浏览(48)
  • 聊聊Spring Cloud Gateway

    网关概述 整体来看,网关有点类似于门面,所有的外部请求都会先经过网关这一层。 网关不仅只是做一个请求的转发及服务的整合,有了网关这个统一的入口之后,它还能提供以下功能。 针对所有请求进行统一鉴权、限流、熔断、日志。 协议转化。针对后端多种不同的协议

    2024年02月07日
    浏览(43)
  • Spring Cloud GateWay简介

    网关是一种充当转换重任的计算机系统或设备,使用在不同的通信协议、数据格式或语言,甚至网关是一种充当转换重任的计算机系统或设备,使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间进行数据传输. 网关具备转发, 路由和数据过滤的功

    2024年02月05日
    浏览(54)
  • spring cloud 之 gateway

    在微服务架构体系中,一个系统会被拆分为很多个微服务,那么作为客户端要如何去调用这么多的微服务呢?如果没有网关的存在,我们只能在客户端记录每个微服务的地址,然后分别调用,当然这样是不现实的 Kong    基于Nginx+Lua开发,性能高,稳定,有多个可用的插件

    2024年02月12日
    浏览(37)
  • Spring Cloud Gateway学习

    传统的单体架构只有一个服务开放给客户端调用,但是在微服务架构体系中是将一个系统拆分成多个微服务,那么作为客户端如何去调用这些微服务呢?如果没有网关的存在,就只能在本地记录每个微服务的调用地址。 无网关的微服务架构存在的问题: 客户端多次请求不同

    2024年02月07日
    浏览(69)
  • Spring Cloud Gateway:配置

    Spring Cloud Gateway提供了多种配置选项,以便您根据需要自定义和调整其行为。以下是一些常见的配置选项: 路由配置:您可以使用 spring.cloud.gateway.routes 属性配置网关的路由规则。通过定义路由规则,您可以将传入请求映射到相应的后端服务。 负载均衡配置:您可以配置网关

    2024年02月13日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包