Browse Source

网关提交

wangtao 3 years ago
parent
commit
9964a9b8ff

+ 18 - 6
pom.xml

@@ -11,7 +11,7 @@
         lb-gateway网关模块
     </description>
     <properties>
-        <spring-boot.version>2.5.5</spring-boot.version>
+        <spring-boot.version>2.5.11</spring-boot.version>
         <spring-cloud.version>2020.0.4</spring-cloud.version>
         <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
         <alibaba.nacos.version>2.0.3</alibaba.nacos.version>
@@ -73,7 +73,14 @@
             <groupId>com.alibaba.cloud</groupId>
             <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+        </dependency>
         <!--&lt;!&ndash; SpringCloud Alibaba Sentinel &ndash;&gt;-->
         <!--<dependency>-->
             <!--<groupId>com.alibaba.cloud</groupId>-->
@@ -87,10 +94,10 @@
         <!--</dependency>-->
 
         <!-- Sentinel Datasource Nacos -->
-        <dependency>
-            <groupId>com.alibaba.csp</groupId>
-            <artifactId>sentinel-datasource-nacos</artifactId>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>com.alibaba.csp</groupId>-->
+<!--            <artifactId>sentinel-datasource-nacos</artifactId>-->
+<!--        </dependency>-->
 
         <dependency>
             <groupId>com.alibaba</groupId>
@@ -103,6 +110,11 @@
             <artifactId>commons-lang3</artifactId>
             <version>3.11</version>
         </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
         <!--<dependency>-->
             <!--<groupId>com.ydd</groupId>-->
             <!--<artifactId>lb-common</artifactId>-->

+ 9 - 5
src/main/java/com/ydd/gateway/GatewayApplication.java

@@ -4,19 +4,23 @@ import com.alibaba.nacos.api.config.annotation.NacosProperty;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.cglib.core.Predicate;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.context.annotation.Bean;
 
 /**
  * 网关启动程序
- * 
+ *
  * @author
  */
 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
 @EnableDiscoveryClient
-public class GatewayApplication
-{
-    public static void main(String[] args)
-    {
+public class GatewayApplication {
+    public static void main(String[] args) {
         SpringApplication.run(GatewayApplication.class, args);
     }
+
+
+
+
 }

+ 59 - 9
src/main/java/com/ydd/gateway/filter/AuthorizeGatewayFilterFactory.java

@@ -1,25 +1,47 @@
 package com.ydd.gateway.filter;
 
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.ydd.gateway.config.GatewayConfig;
 import com.ydd.gateway.service.FilterService;
+import com.ydd.gateway.service.GatewayContext;
+import com.ydd.gateway.service.RecorderServerHttpRequestDecorator;
 import com.ydd.gateway.util.StringUtils;
+import io.netty.buffer.ByteBufAllocator;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
 import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.core.io.ByteArrayResource;
 import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.core.io.buffer.NettyDataBufferFactory;
 import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
 import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
 import org.springframework.http.server.reactive.ServerHttpResponse;
 import org.springframework.stereotype.Component;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  @author Administrator
@@ -46,7 +68,7 @@ public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<
     }
 
     // url白名单
-    public static final String URL = "/**/**,/doc.html/**";
+    public static final String URL = "/doc.html/**";
 //    @Value("${waimai.meituan.developerId}")
 //    public String aa ;
     @Override
@@ -64,18 +86,48 @@ public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<
             String url = request.getURI().getPath();
             logger.info(GatewayConfig.NACOS_SERVER_ADDR);
             String path = request.getPath().pathWithinApplication().value();
-			if (URL.contains(path.substring(path.indexOf("/", 1), path.lastIndexOf("/")))) {
-				return chain.filter(exchange);
-			}
-
+            System.out.println(path.substring(path.indexOf("/", 1), path.lastIndexOf("/")));
+            System.out.println(URL.contains(path.substring(path.indexOf("/", 1), path.lastIndexOf("/"))));
+//			if (URL.contains(path.substring(path.indexOf("/", 1), path.lastIndexOf("/")))) {
+//				return chain.filter(exchange);
+//			}
             HttpHeaders headers = request.getHeaders();
+            String method = request.getMethodValue();
+          //  String contentType = request.getHeaders().getFirst("Content-Type");
+            MediaType contentType = headers.getContentType();
+//            GatewayContext gatewayContext = exchange.getAttribute(GatewayContext.CACHE_GATEWAY_CONTEXT);
+//            System.out.println(gatewayContext.getCacheBody());
+//            System.out.println(gatewayContext.getFormData().toSingleValueMap());
+//            System.out.println(gatewayContext.getAllRequestData().toSingleValueMap());
+            if ("POST".equals(method)&&MediaType.APPLICATION_JSON.equals(contentType)){
+                AtomicReference<String> requestBody = new AtomicReference<>("");
+                RecorderServerHttpRequestDecorator requestDecorator = new RecorderServerHttpRequestDecorator(request);
+                Flux<DataBuffer> body = requestDecorator.getBody();
+                body.subscribe(buffer -> {
+                    CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
+                    requestBody.set(charBuffer.toString());
+                });
+                //获取body参数
+                JSONObject requestParams = JSONObject.parseObject(requestBody.get());
+                System.out.println("**********************"+requestParams);
+            }
+            if(MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)){
+                GatewayContext gatewayContext = exchange.getAttribute(GatewayContext.CACHE_GATEWAY_CONTEXT);
+                System.out.println(gatewayContext.getFormData());
+            }
+            if("GET".equals(method)){
+                MultiValueMap<String, String> map =  request.getQueryParams();
+                System.out.println("**********************"+JSONObject.toJSONString(map));
+            }
+
+
 //			String remoteIP = headers.getFirst("x-real-ip");
 //			if (!StringUtils.hasText(remoteIP)) {
 //				remoteIP = request.getRemoteAddress().getHostName();
 //			}
 
             // 请求信息打印
-            logInfo(request, headers);
+           // logInfo(request, headers);
             TreeMap<String, String> params = new TreeMap<>();
             String signStr = headers.getFirst("sign");
 
@@ -92,10 +144,8 @@ public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<
             // 签名校验
             Mono<DataBuffer> mono = filterService.validateSign(params, signStr, response);
             if (mono != null) {
-                return response.writeWith(mono);
+                //return response.writeWith(mono);
             }
-
-
             return chain.filter(exchange);
         };
     }

+ 1 - 1
src/main/java/com/ydd/gateway/filter/BlackListUrlFilter.java

@@ -13,7 +13,7 @@ import java.util.regex.Pattern;
  * 
  * @author ruoyi
  */
-@Component
+//@Component
 public class BlackListUrlFilter extends AbstractGatewayFilterFactory<BlackListUrlFilter.Config>
 {
     @Override

+ 105 - 105
src/main/java/com/ydd/gateway/filter/CacheRequestFilter.java

@@ -1,105 +1,105 @@
-package com.ydd.gateway.filter;
-
-import java.util.Collections;
-import java.util.List;
-import org.springframework.cloud.gateway.filter.GatewayFilter;
-import org.springframework.cloud.gateway.filter.GatewayFilterChain;
-import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
-import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
-import org.springframework.core.io.buffer.DataBuffer;
-import org.springframework.core.io.buffer.DataBufferFactory;
-import org.springframework.core.io.buffer.DataBufferUtils;
-import org.springframework.http.HttpMethod;
-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;
-
-/**
- * 获取body请求数据(解决流不能重复读取问题)
- * 
- * @author ruoyi
- */
-//@Component
-public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config>
-{
-    public CacheRequestFilter()
-    {
-        super(Config.class);
-    }
-
-    @Override
-    public String name()
-    {
-        return "CacheRequestFilter";
-    }
-
-    @Override
-    public GatewayFilter apply(Config config)
-    {
-        CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter();
-        Integer order = config.getOrder();
-        if (order == null)
-        {
-            return cacheRequestGatewayFilter;
-        }
-        return new OrderedGatewayFilter(cacheRequestGatewayFilter, order);
-    }
-
-    public static class CacheRequestGatewayFilter implements GatewayFilter
-    {
-        @Override
-        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
-        {
-            // GET DELETE 不过滤
-            HttpMethod method = exchange.getRequest().getMethod();
-            if (method == null || method.matches("GET") || method.matches("DELETE"))
-            {
-                return chain.filter(exchange);
-            }
-            return DataBufferUtils.join(exchange.getRequest().getBody()).map(dataBuffer -> {
-                byte[] bytes = new byte[dataBuffer.readableByteCount()];
-                dataBuffer.read(bytes);
-                DataBufferUtils.release(dataBuffer);
-                return bytes;
-            }).defaultIfEmpty(new byte[0]).flatMap(bytes -> {
-                DataBufferFactory dataBufferFactory = exchange.getResponse().bufferFactory();
-                ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest())
-                {
-                    @Override
-                    public Flux<DataBuffer> getBody()
-                    {
-                        if (bytes.length > 0)
-                        {
-                            return Flux.just(dataBufferFactory.wrap(bytes));
-                        }
-                        return Flux.empty();
-                    }
-                };
-                return chain.filter(exchange.mutate().request(decorator).build());
-            });
-        }
-    }
-
-    @Override
-    public List<String> shortcutFieldOrder()
-    {
-        return Collections.singletonList("order");
-    }
-
-    static class Config
-    {
-        private Integer order;
-
-        public Integer getOrder()
-        {
-            return order;
-        }
-
-        public void setOrder(Integer order)
-        {
-            this.order = order;
-        }
-    }
-}
+//package com.ydd.gateway.filter;
+//
+//import java.util.Collections;
+//import java.util.List;
+//import org.springframework.cloud.gateway.filter.GatewayFilter;
+//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+//import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
+//import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+//import org.springframework.core.io.buffer.DataBuffer;
+//import org.springframework.core.io.buffer.DataBufferFactory;
+//import org.springframework.core.io.buffer.DataBufferUtils;
+//import org.springframework.http.HttpMethod;
+//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;
+//
+///**
+// * 获取body请求数据(解决流不能重复读取问题)
+// *
+// * @author ruoyi
+// */
+////@Component
+//public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config>
+//{
+//    public CacheRequestFilter()
+//    {
+//        super(Config.class);
+//    }
+//
+//    @Override
+//    public String name()
+//    {
+//        return "CacheRequestFilter";
+//    }
+//
+//    @Override
+//    public GatewayFilter apply(Config config)
+//    {
+//        CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter();
+//        Integer order = config.getOrder();
+//        if (order == null)
+//        {
+//            return cacheRequestGatewayFilter;
+//        }
+//        return new OrderedGatewayFilter(cacheRequestGatewayFilter, order);
+//    }
+//
+//    public static class CacheRequestGatewayFilter implements GatewayFilter
+//    {
+//        @Override
+//        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
+//        {
+//            // GET DELETE 不过滤
+//            HttpMethod method = exchange.getRequest().getMethod();
+//            if (method == null || method.matches("GET") || method.matches("DELETE"))
+//            {
+//                return chain.filter(exchange);
+//            }
+//            return DataBufferUtils.join(exchange.getRequest().getBody()).map(dataBuffer -> {
+//                byte[] bytes = new byte[dataBuffer.readableByteCount()];
+//                dataBuffer.read(bytes);
+//                DataBufferUtils.release(dataBuffer);
+//                return bytes;
+//            }).defaultIfEmpty(new byte[0]).flatMap(bytes -> {
+//                DataBufferFactory dataBufferFactory = exchange.getResponse().bufferFactory();
+//                ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest())
+//                {
+//                    @Override
+//                    public Flux<DataBuffer> getBody()
+//                    {
+//                        if (bytes.length > 0)
+//                        {
+//                            return Flux.just(dataBufferFactory.wrap(bytes));
+//                        }
+//                        return Flux.empty();
+//                    }
+//                };
+//                return chain.filter(exchange.mutate().request(decorator).build());
+//            });
+//        }
+//    }
+//
+//    @Override
+//    public List<String> shortcutFieldOrder()
+//    {
+//        return Collections.singletonList("order");
+//    }
+//
+//    static class Config
+//    {
+//        private Integer order;
+//
+//        public Integer getOrder()
+//        {
+//            return order;
+//        }
+//
+//        public void setOrder(Integer order)
+//        {
+//            this.order = order;
+//        }
+//    }
+//}

+ 210 - 0
src/main/java/com/ydd/gateway/filter/GatewayContextFilter.java

@@ -0,0 +1,210 @@
+//package com.ydd.gateway.filter;
+//import com.ydd.gateway.service.GatewayContext;
+//import io.netty.buffer.ByteBufAllocator;
+//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.ByteArrayResource;
+//import org.springframework.core.io.buffer.DataBuffer;
+//import org.springframework.core.io.buffer.DataBufferUtils;
+//import org.springframework.core.io.buffer.NettyDataBufferFactory;
+//import org.springframework.http.HttpHeaders;
+//import org.springframework.http.MediaType;
+//import org.springframework.http.codec.HttpMessageReader;
+//import org.springframework.http.server.reactive.ServerHttpRequest;
+//import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
+//import org.springframework.stereotype.Component;
+//import org.springframework.util.MultiValueMap;
+//import org.springframework.web.reactive.function.server.HandlerStrategies;
+//import org.springframework.web.reactive.function.server.ServerRequest;
+//import org.springframework.web.server.ServerWebExchange;
+//import reactor.core.publisher.Flux;
+//import reactor.core.publisher.Mono;
+//
+//import java.io.UnsupportedEncodingException;
+//import java.net.URLEncoder;
+//import java.nio.charset.Charset;
+//import java.nio.charset.StandardCharsets;
+//import java.util.List;
+//import java.util.Map;
+//
+//@Slf4j
+////@Component
+//public class GatewayContextFilter implements GlobalFilter, Ordered {
+//
+//    /**
+//     * default HttpMessageReader
+//     */
+//    private static final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();
+//
+//    @Override
+//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+//        /**
+//         * save request path and serviceId into gateway context
+//         */
+//        ServerHttpRequest request = exchange.getRequest();
+//        String path = request.getPath().pathWithinApplication().value();
+//        GatewayContext gatewayContext = new GatewayContext();
+//        gatewayContext.getAllRequestData().addAll(request.getQueryParams());
+//        gatewayContext.setPath(path);
+//        /**
+//         * save gateway context into exchange
+//         */
+//        HttpHeaders headers = request.getHeaders();
+//        MediaType contentType = headers.getContentType();
+//        long contentLength = headers.getContentLength();
+//        if(contentLength>0){
+//            if(MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)){
+//                return readBody(exchange, chain,gatewayContext);
+//            }
+//            if(MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)){
+//                return readFormData(exchange, chain,gatewayContext);
+//            }
+//        }
+//        log.debug("[GatewayContext]ContentType:{},Gateway context is set with {}",contentType, gatewayContext);
+//        return chain.filter(exchange);
+//
+//    }
+//
+//
+//
+//    /**
+//     * ReadFormData
+//     * @param exchange
+//     * @param chain
+//     * @return
+//     */
+//    private Mono<Void> readFormData(ServerWebExchange exchange,GatewayFilterChain chain,GatewayContext gatewayContext){
+//        HttpHeaders headers = exchange.getRequest().getHeaders();
+//        return exchange.getFormData()
+//                .doOnNext(multiValueMap -> {
+//                    gatewayContext.setFormData(multiValueMap);
+//                    exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT,gatewayContext);
+//                    log.debug("[GatewayContext]Read FormData:{}",multiValueMap);
+//                })
+//                .then(Mono.defer(() -> {
+//                    Charset charset = headers.getContentType().getCharset();
+//                    charset = charset == null? StandardCharsets.UTF_8:charset;
+//                    String charsetName = charset.name();
+//                    MultiValueMap<String, String> formData = gatewayContext.getFormData();
+//                    /**
+//                     * formData is empty just return
+//                     */
+//                    if(null == formData || formData.isEmpty()){
+//                        return chain.filter(exchange);
+//                    }
+//                    StringBuilder formDataBodyBuilder = new StringBuilder();
+//                    String entryKey;
+//                    List<String> entryValue;
+//                    try {
+//                        /**
+//                         * repackage form data
+//                         */
+//                        for (Map.Entry<String, List<String>> entry : formData.entrySet()) {
+//                            entryKey = entry.getKey();
+//                            entryValue = entry.getValue();
+//                            if (entryValue.size() > 1) {
+//                                for(String value : entryValue){
+//                                    formDataBodyBuilder.append(entryKey).append("=").append(URLEncoder.encode(value, charsetName)).append("&");
+//                                }
+//                            } else {
+//                                formDataBodyBuilder.append(entryKey).append("=").append(URLEncoder.encode(entryValue.get(0), charsetName)).append("&");
+//                            }
+//                        }
+//                    }catch (UnsupportedEncodingException e){
+//                        //ignore URLEncode Exception
+//                    }
+//                    /**
+//                     * substring with the last char '&'
+//                     */
+//                    String formDataBodyString = "";
+//                    if(formDataBodyBuilder.length()>0){
+//                        formDataBodyString = formDataBodyBuilder.substring(0, formDataBodyBuilder.length() - 1);
+//                    }
+//                    /**
+//                     * get data bytes
+//                     */
+//                    byte[] bodyBytes =  formDataBodyString.getBytes(charset);
+//                    int contentLength = bodyBytes.length;
+//                    ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
+//                            exchange.getRequest()) {
+//                        /**
+//                         * change content-length
+//                         * @return
+//                         */
+//                        @Override
+//                        public HttpHeaders getHeaders() {
+//                            HttpHeaders httpHeaders = new HttpHeaders();
+//                            httpHeaders.putAll(super.getHeaders());
+//                            if (contentLength > 0) {
+//                                httpHeaders.setContentLength(contentLength);
+//                            } else {
+//                                httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
+//                            }
+//                            return httpHeaders;
+//                        }
+//
+//                        /**
+//                         * read bytes to Flux<Databuffer>
+//                         * @return
+//                         */
+//                        @Override
+//                        public Flux<DataBuffer> getBody() {
+//                            return DataBufferUtils.read(new ByteArrayResource(bodyBytes),new NettyDataBufferFactory(ByteBufAllocator.DEFAULT),contentLength);
+//                        }
+//                    };
+//                    ServerWebExchange mutateExchange = exchange.mutate().request(decorator).build();
+//                  //  log.debug("[GatewayContext]Rewrite Form Data :{}",formDataBodyString);
+//                    return chain.filter(mutateExchange);
+//                }));
+//    }
+//
+//    /**
+//     * ReadJsonBody
+//     * @param exchange
+//     * @param chain
+//     * @return
+//     */
+//    private Mono<Void> readBody(ServerWebExchange exchange,GatewayFilterChain chain,GatewayContext gatewayContext){
+//        /**
+//         * join the body
+//         */
+//        return DataBufferUtils.join(exchange.getRequest().getBody())
+//                .flatMap(dataBuffer -> {
+//                    /**
+//                     * read the body Flux<Databuffer>
+//                     */
+//                    DataBufferUtils.retain(dataBuffer);
+//                    Flux<DataBuffer> cachedFlux = Flux.defer(() -> Flux.just(dataBuffer.slice(0, dataBuffer.readableByteCount())));
+//                    /**
+//                     * repackage ServerHttpRequest
+//                     */
+//                    ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
+//                        @Override
+//                        public Flux<DataBuffer> getBody() {
+//                            return cachedFlux;
+//                        }
+//                    };
+//                    /**
+//                     * mutate exchage with new ServerHttpRequest
+//                     */
+//                    ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();
+//                    /**
+//                     * read body string with default messageReaders
+//                     */
+//                    return ServerRequest.create(mutatedExchange, messageReaders)
+//                            .bodyToMono(String.class)
+//                            .doOnNext(objectValue -> {
+//                                gatewayContext.setCacheBody(objectValue);
+//                                exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT,gatewayContext);
+//                                log.debug("[GatewayContext]Read JsonBody:{}",objectValue);
+//                            }).then(chain.filter(mutatedExchange));
+//                });
+//    }
+//
+//    @Override
+//    public int getOrder() {
+//        return HIGHEST_PRECEDENCE;
+//    }
+//}

+ 199 - 0
src/main/java/com/ydd/gateway/filter/RequestParamGlobalFilter.java

@@ -0,0 +1,199 @@
+package com.ydd.gateway.filter;
+
+import com.ydd.gateway.service.GatewayContext;
+import io.netty.buffer.ByteBufAllocator;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.core.io.buffer.NettyDataBufferFactory;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.codec.HttpMessageReader;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
+import org.springframework.stereotype.Component;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.reactive.function.server.HandlerStrategies;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author wangtao
+ * @date 2022/4/1
+ */
+@Component
+public class RequestParamGlobalFilter implements GlobalFilter, Ordered {
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+
+        /**
+         * save request path and serviceId into gateway context
+         */
+        ServerHttpRequest request = exchange.getRequest();
+        HttpHeaders headers = request.getHeaders();
+
+        // 处理参数
+        MediaType contentType = headers.getContentType();
+        long contentLength = headers.getContentLength();
+
+        if (contentLength > 0) {
+            if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)) {
+                return readBody(exchange, chain);
+            }
+            if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)) {
+                GatewayContext gatewayContext = new GatewayContext();
+                return readFormData(exchange, chain,gatewayContext);
+            }
+        }
+
+        return chain.filter(exchange);
+    }
+
+
+    /**
+     * default HttpMessageReader
+     */
+    private static final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();
+    /**
+     * ReadJsonBody
+     *
+     * @param exchange
+     * @param chain
+     * @return
+     */
+    private Mono<Void> readBody(ServerWebExchange exchange, GatewayFilterChain chain) {
+        /**
+         * join the body
+         */
+        return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {
+            byte[] bytes = new byte[dataBuffer.readableByteCount()];
+            dataBuffer.read(bytes);
+            DataBufferUtils.release(dataBuffer);
+            Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
+                DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
+                DataBufferUtils.retain(buffer);
+                return Mono.just(buffer);
+            });
+            /**
+             * repackage ServerHttpRequest
+             */
+            ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
+                @Override
+                public Flux<DataBuffer> getBody() {
+                    return cachedFlux;
+                }
+            };
+            /**
+             * mutate exchage with new ServerHttpRequest
+             */
+            ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();
+            /**
+             * read body string with default messageReaders
+             */
+            return ServerRequest.create(mutatedExchange, messageReaders).bodyToMono(String.class)
+                    .doOnNext(objectValue -> {
+//                        log.debug("[GatewayContext]Read JsonBody:{}", objectValue);
+                    }).then(chain.filter(mutatedExchange));
+        });
+    }
+
+    private Mono<Void> readFormData(ServerWebExchange exchange, GatewayFilterChain chain, GatewayContext gatewayContext){
+        HttpHeaders headers = exchange.getRequest().getHeaders();
+        exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT,gatewayContext);
+        return exchange.getFormData()
+                .doOnNext(multiValueMap -> {
+                    gatewayContext.setFormData(multiValueMap);
+                })
+                .then(Mono.defer(() -> {
+                    Charset charset = headers.getContentType().getCharset();
+                    charset = charset == null? StandardCharsets.UTF_8:charset;
+                    String charsetName = charset.name();
+                    MultiValueMap<String, String> formData = gatewayContext.getFormData();
+                    /**
+                     * formData is empty just return
+                     */
+                    if(null == formData || formData.isEmpty()){
+                        return chain.filter(exchange);
+                    }
+                    StringBuilder formDataBodyBuilder = new StringBuilder();
+                    String entryKey;
+                    List<String> entryValue;
+                    try {
+                        /**
+                         * repackage form data
+                         */
+                        for (Map.Entry<String, List<String>> entry : formData.entrySet()) {
+                            entryKey = entry.getKey();
+                            entryValue = entry.getValue();
+                            if (entryValue.size() > 1) {
+                                for(String value : entryValue){
+                                    formDataBodyBuilder.append(entryKey).append("=").append(URLEncoder.encode(value, charsetName)).append("&");
+                                }
+                            } else {
+                                formDataBodyBuilder.append(entryKey).append("=").append(URLEncoder.encode(entryValue.get(0), charsetName)).append("&");
+                            }
+                        }
+                    }catch (UnsupportedEncodingException e){
+                        //ignore URLEncode Exception
+                    }
+                    /**
+                     * substring with the last char '&'
+                     */
+                    String formDataBodyString = "";
+                    if(formDataBodyBuilder.length()>0){
+                        formDataBodyString = formDataBodyBuilder.substring(0, formDataBodyBuilder.length() - 1);
+                    }
+                    /**
+                     * get data bytes
+                     */
+                    byte[] bodyBytes =  formDataBodyString.getBytes(charset);
+                    int contentLength = bodyBytes.length;
+                    ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
+                            exchange.getRequest()) {
+                        /**
+                         * change content-length
+                         * @return
+                         */
+                        @Override
+                        public HttpHeaders getHeaders() {
+                            HttpHeaders httpHeaders = new HttpHeaders();
+                            httpHeaders.putAll(super.getHeaders());
+                            if (contentLength > 0) {
+                                httpHeaders.setContentLength(contentLength);
+                            } else {
+                                httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
+                            }
+                            return httpHeaders;
+                        }
+
+                        /**
+                         * read bytes to Flux<Databuffer>
+                         * @return
+                         */
+                        @Override
+                        public Flux<DataBuffer> getBody() {
+                            return DataBufferUtils.read(new ByteArrayResource(bodyBytes),new NettyDataBufferFactory(ByteBufAllocator.DEFAULT),contentLength);
+                        }
+                    };
+                    ServerWebExchange mutateExchange = exchange.mutate().request(decorator).build();
+                    return chain.filter(mutateExchange);
+                }));
+    }
+    @Override
+    public int getOrder() {
+        return HIGHEST_PRECEDENCE;
+    }
+}

+ 30 - 0
src/main/java/com/ydd/gateway/service/GatewayContext.java

@@ -0,0 +1,30 @@
+package com.ydd.gateway.service;
+
+/**
+ * @author wangtao
+ * @date 2022/4/1
+ */
+
+import lombok.Data;
+import org.springframework.util.MultiValueMap;
+
+@Data
+public class GatewayContext {
+
+    public static final String CACHE_GATEWAY_CONTEXT = "cacheGatewayContext";
+
+    /**
+     * cache json body
+     */
+    private String cacheBody;
+    /**
+     * cache formdata
+     */
+    private MultiValueMap<String, String> formData;
+    /**
+     * cache reqeust path
+     */
+    private String path;
+
+    private MultiValueMap<String, String> allRequestData;
+}

+ 35 - 0
src/main/java/com/ydd/gateway/service/RecorderServerHttpRequestDecorator.java

@@ -0,0 +1,35 @@
+package com.ydd.gateway.service;
+
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
+import reactor.core.publisher.Flux;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author wangtao
+ * @date 2022/4/1
+ */
+public class RecorderServerHttpRequestDecorator  extends ServerHttpRequestDecorator {
+    private final List<DataBuffer> dataBuffers = new ArrayList<>();
+
+    public RecorderServerHttpRequestDecorator(ServerHttpRequest delegate) {
+        super(delegate);
+        super.getBody().map(dataBuffer -> {
+            dataBuffers.add(dataBuffer);
+            return dataBuffer;
+        }).subscribe();
+    }
+
+    @Override
+    public Flux<DataBuffer> getBody() {
+        return copy();
+    }
+
+    private Flux<DataBuffer> copy() {
+        return Flux.fromIterable(dataBuffers)
+                .map(buf -> buf.factory().wrap(buf.asByteBuffer()));
+    }
+}

+ 4 - 4
src/main/resources/application.yml

@@ -8,8 +8,8 @@ spring:
           enabled: false
       routes:
         - id: api-beta
-          #url: lb://API
-          uri: http://www.baidu.com/
+          uri: lb://lb-app
+          # uri: http://www.baidu.com/
           predicates:
             #匹配所有请求路径以
             - Path=/**
@@ -17,8 +17,8 @@ spring:
           filters:
             - Authorize=true
         - id: api-release
-          #url: lb://API
-          uri:  http://www.2500sz.com/
+          uri: lb://lb-app
+          #  uri:  http://www.2500sz.com/
           predicates:
             #匹配所有请求路径以
             - Path=/**

+ 6 - 22
src/main/resources/bootstrap.yml

@@ -12,29 +12,13 @@ spring:
     nacos:
       discovery:
       # 服务注册地址
-        server-addr: 153.37.175.42:8848
+        server-addr: 153.37.175.42:28848
       config:
        # 配置中心地址
-        server-addr: 153.37.175.42:8848
-        file-extension: yml         # 配置文件格式
-        # 共享配置
+        server-addr: 153.37.175.42:28848
+        file-extension: yaml         # 配置文件格式
+      # 共享配置
         shared-configs[0]:
-          data-id: application-dev.yaml
+          data-id: lb_application-dev.yaml
           refresh: false
-#        shared-configs:
-#          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
-            #    sentinel:
-#      # 取消控制台懒加载
-#      eager: true
-#      transport:
-#        # 控制台地址
-#        dashboard: 127.0.0.1:8718
-      # nacos配置持久化
-#      datasource:
-                            ##        ds1:
-                            ##          nacos:
-                            ##            server-addr: 153.37.175.42:8848
-                            ##            dataId: sentinel-ruoyi-gateway
-                            ##            groupId: DEFAULT_GROUP
-                            ##            data-type: json
-                            ##            rule-type: flow
+