Bladeren bron

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	lb-module/src/main/java/com/ydd/module/service/impl/ShopWaimaiServiceImpl.java
#	lb-module/src/main/java/com/ydd/system/mapper/SysRoleMapper.java
#	lb-module/src/main/java/com/ydd/system/service/ISysRoleService.java
#	lb-module/src/main/java/com/ydd/system/service/ISysUserService.java
#	lb-module/src/main/java/com/ydd/system/service/impl/SysUserServiceImpl.java
#	lb-module/src/main/resources/mapper/system/SysRoleMapper.xml
#	lb-module/src/main/resources/mapper/system/SysUserRoleMapper.xml
叶君翔 3 jaren geleden
bovenliggende
commit
e6b73e26e6
37 gewijzigde bestanden met toevoegingen van 3571 en 5 verwijderingen
  1. 2 1
      lb-app/src/main/java/com/ydd/app/service/impl/ApiOrderBackServiceImpl.java
  2. 1 0
      lb-app/src/main/java/com/ydd/app/service/impl/ApiWaimaiServiceImpl.java
  3. 3 1
      lb-app/src/main/java/com/ydd/app/task/SyncRiderTask.java
  4. 2 2
      lb-feginclient/src/main/java/com/ydd/api/MeiTuanApi.java
  5. 3 0
      lb-feginclient/src/main/java/com/ydd/api/MeiTuanSgApi.java
  6. 25 0
      lb-feginclient/src/main/java/com/ydd/api/WaimaiApi.java
  7. 114 0
      lb-gateway/pom.xml
  8. 25 0
      lb-gateway/src/main/java/com/ydd/gateway/GatewayApplication.java
  9. 26 0
      lb-gateway/src/main/java/com/ydd/gateway/config/GatewayConfig.java
  10. 33 0
      lb-gateway/src/main/java/com/ydd/gateway/config/properties/IgnoreWhiteProperties.java
  11. 48 0
      lb-gateway/src/main/java/com/ydd/gateway/config/properties/XssProperties.java
  12. 128 0
      lb-gateway/src/main/java/com/ydd/gateway/filter/AuthFilter.java
  13. 189 0
      lb-gateway/src/main/java/com/ydd/gateway/filter/AuthorizeGatewayFilterFactory.java
  14. 65 0
      lb-gateway/src/main/java/com/ydd/gateway/filter/BlackListUrlFilter.java
  15. 105 0
      lb-gateway/src/main/java/com/ydd/gateway/filter/CacheRequestFilter.java
  16. 210 0
      lb-gateway/src/main/java/com/ydd/gateway/filter/GatewayContextFilter.java
  17. 199 0
      lb-gateway/src/main/java/com/ydd/gateway/filter/RequestParamGlobalFilter.java
  18. 39 0
      lb-gateway/src/main/java/com/ydd/gateway/filter/ResponseObject.java
  19. 120 0
      lb-gateway/src/main/java/com/ydd/gateway/filter/XssFilter.java
  20. 56 0
      lb-gateway/src/main/java/com/ydd/gateway/handler/GatewayExceptionHandler.java
  21. 41 0
      lb-gateway/src/main/java/com/ydd/gateway/handler/SentinelFallbackHandler.java
  22. 119 0
      lb-gateway/src/main/java/com/ydd/gateway/service/FilterService.java
  23. 30 0
      lb-gateway/src/main/java/com/ydd/gateway/service/GatewayContext.java
  24. 35 0
      lb-gateway/src/main/java/com/ydd/gateway/service/RecorderServerHttpRequestDecorator.java
  25. 85 0
      lb-gateway/src/main/java/com/ydd/gateway/util/CharsetKit.java
  26. 1012 0
      lb-gateway/src/main/java/com/ydd/gateway/util/Convert.java
  27. 107 0
      lb-gateway/src/main/java/com/ydd/gateway/util/Md5Util.java
  28. 90 0
      lb-gateway/src/main/java/com/ydd/gateway/util/StrFormatter.java
  29. 480 0
      lb-gateway/src/main/java/com/ydd/gateway/util/StringUtils.java
  30. 26 0
      lb-gateway/src/main/resources/application.yml
  31. 10 0
      lb-gateway/src/main/resources/banner.txt
  32. 24 0
      lb-gateway/src/main/resources/bootstrap.yml
  33. 74 0
      lb-gateway/src/main/resources/logback.xml
  34. 1 1
      lb-module/src/main/resources/mapper/system/SysUserRoleMapper.xml
  35. 6 0
      lb-third/lb-third-waimai/src/main/java/com/ydd/third/controller/MeiTuanSgController.java
  36. 37 0
      lb-third/lb-third-waimai/src/main/java/com/ydd/third/controller/WaimaiController.java
  37. 1 0
      pom.xml

+ 2 - 1
lb-app/src/main/java/com/ydd/app/service/impl/ApiOrderBackServiceImpl.java

@@ -6,6 +6,7 @@ import com.alibaba.fastjson.parser.Feature;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.ydd.api.DeliveryService;
 import com.ydd.api.MeiTuanApi;
+import com.ydd.api.WaimaiApi;
 import com.ydd.app.callback.controller.ShanTangSignUtils;
 import com.ydd.app.service.ApiCouponService;
 import com.ydd.app.service.ApiOrderBackService;
@@ -80,7 +81,7 @@ public class ApiOrderBackServiceImpl implements ApiOrderBackService {
 
     private final IDspWaimaiService iDspWaimaiService;
 
-    private final MeiTuanApi waimaiClient;
+    private final WaimaiApi waimaiClient;
 
     private final IShopWaimaiService iShopWaimaiService;
 

+ 1 - 0
lb-app/src/main/java/com/ydd/app/service/impl/ApiWaimaiServiceImpl.java

@@ -470,6 +470,7 @@ public class ApiWaimaiServiceImpl implements ApiWaimaiService {
             waimaiOrder.setReceiptLng(orderVo.getLongitude().toString());
             orderVo.setWmPoiAddress(URLDecoder.decode(orderVo.getWmPoiAddress(), "utf-8"));
             waimaiOrder.setPoiAddress(orderVo.getWmPoiAddress());
+            orderVo.setWmPoiName(URLDecoder.decode(orderVo.getWmPoiName(), "utf-8"));
             waimaiOrder.setPoiName(orderVo.getWmPoiName());
             waimaiOrder.setPoiPhone(orderVo.getWmPoiPhone());
             waimaiOrder.setPoiReceiveDetail(null);

+ 3 - 1
lb-app/src/main/java/com/ydd/app/task/SyncRiderTask.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.ydd.api.EleRetailApi;
 import com.ydd.api.ElemeApi;
 import com.ydd.api.MeiTuanApi;
+import com.ydd.api.MeiTuanSgApi;
 import com.ydd.app.service.ApiRiderLocationService;
 import com.ydd.module.domain.DspDelivery;
 import com.ydd.module.domain.Order;
@@ -39,6 +40,7 @@ public class SyncRiderTask {
     private final IOrderService iOrderService;
 
     private final MeiTuanApi meituanClient;
+    private final MeiTuanSgApi meiTuanSgApi;
     private final ApiRiderLocationService apiRiderLocationService;
     @EventListener(SyncRiderEvent.class)
     @Async
@@ -88,7 +90,7 @@ public class SyncRiderTask {
                 }
                 else if (client.equals("meituansg")) {
                     syncRiderPositionVo.setLogisticsStatus(dto.getOrderMtStatus());
-                    eleRetaiClient.syncRiderPosition(syncRiderPositionVo);
+                    meiTuanSgApi.syncRiderPosition(syncRiderPositionVo);
                 }
                 TimeUnit.MINUTES.sleep(1);
             }

+ 2 - 2
lb-feginclient/src/main/java/com/ydd/api/MeiTuanApi.java

@@ -69,8 +69,8 @@ public interface MeiTuanApi {
     @PostMapping(value = "/meituan/syncNgRiderPosition")
     ResObject syncNgRiderPosition(@RequestBody SyncRiderPositionStatusVo syncRiderPositionVo);
 
-    @GetMapping(value = "/syncRiderPositionStatus")
-    ResObject syncRiderPositionStatus(@RequestBody SyncRiderPositionStatusVo vo);
+//    @GetMapping(value = "/syncRiderPositionStatus")
+//    ResObject syncRiderPositionStatus(@RequestBody SyncRiderPositionStatusVo vo);
 
     @GetMapping(value = "/queryFoodList")
     ResObject queryFoodList(@RequestParam("authToken") String authToken);

+ 3 - 0
lb-feginclient/src/main/java/com/ydd/api/MeiTuanSgApi.java

@@ -45,4 +45,7 @@ public interface MeiTuanSgApi {
 
     @PostMapping(value="/meituansg/doRemindOrder")
     ResObject<MeituanSgRemindOrderResultVo> doRemindOrder(@RequestParam Map<String, String> params);
+
+    @PostMapping(value = "/meituansg/syncRiderPosition")
+    ResObject syncRiderPosition(@RequestBody SyncRiderPositionStatusVo syncRiderPositionVo);
 }

+ 25 - 0
lb-feginclient/src/main/java/com/ydd/api/WaimaiApi.java

@@ -0,0 +1,25 @@
+package com.ydd.api;
+
+import com.ydd.third.common.vo.ResObject;
+import com.ydd.third.common.vo.waimai.SyncRiderPositionStatusVo;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * 美团外卖相关api
+ * @author 叶君翔
+ * @date 2021/11/10 11:59
+ */
+
+@FeignClient(name = "lb-waimai", url = "http://127.0.0.1:8085/waimai")
+public interface WaimaiApi {
+
+    /**
+     * 同步骑手位置
+     */
+    @PostMapping(value="/waimai/syncRiderPositionStatus")
+    public ResObject syncRiderPositionStatus(@RequestBody SyncRiderPositionStatusVo syncRiderPositionVo) ;
+
+
+}

+ 114 - 0
lb-gateway/pom.xml

@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>lb-server</artifactId>
+        <groupId>com.ydd</groupId>
+        <version>1.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>lb-gateway</artifactId>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+    <dependencies>
+
+        <!-- SpringCloud Gateway -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-gateway</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-bootstrap</artifactId>
+        </dependency>
+        <!-- SpringCloud Alibaba Nacos -->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+
+        <!-- SpringCloud Alibaba Nacos Config -->
+        <dependency>
+            <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>-->
+        <!--<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>-->
+        <!--</dependency>-->
+
+        <!--&lt;!&ndash; SpringCloud Alibaba Sentinel Gateway &ndash;&gt;-->
+        <!--<dependency>-->
+        <!--<groupId>com.alibaba.cloud</groupId>-->
+        <!--<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>-->
+        <!--</dependency>-->
+
+        <!-- Sentinel Datasource Nacos -->
+        <!--        <dependency>-->
+        <!--            <groupId>com.alibaba.csp</groupId>-->
+        <!--            <artifactId>sentinel-datasource-nacos</artifactId>-->
+        <!--        </dependency>-->
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.75</version>
+        </dependency>
+        <!--常用工具类 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <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>-->
+        <!--<version>1.0</version>-->
+        <!--</dependency>-->
+
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>8</source>
+                    <target>8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 25 - 0
lb-gateway/src/main/java/com/ydd/gateway/GatewayApplication.java

@@ -0,0 +1,25 @@
+package com.ydd.gateway;
+
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+/**
+ * 网关启动程序
+ *
+ * @author
+ */
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class, SecurityAutoConfiguration.class })
+@EnableDiscoveryClient
+public class GatewayApplication {
+    public static void main(String[] args) {
+
+        SpringApplication.run(GatewayApplication.class, args);
+    }
+
+
+}

+ 26 - 0
lb-gateway/src/main/java/com/ydd/gateway/config/GatewayConfig.java

@@ -0,0 +1,26 @@
+package com.ydd.gateway.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 网关限流配置
+ *
+        *
+        */
+@Configuration
+public class GatewayConfig
+{
+    public static String NACOS_SERVER_ADDR;
+
+    @Value("${waimai.meituan.developerId}")
+    public void setNacosServerAddr(String nacosServerAddr){
+        NACOS_SERVER_ADDR = nacosServerAddr;
+    }
+//    @Bean
+//    @Order(Ordered.HIGHEST_PRECEDENCE)
+//    public SentinelFallbackHandler sentinelGatewayExceptionHandler()
+//    {
+//        return new SentinelFallbackHandler();
+//    }
+}

+ 33 - 0
lb-gateway/src/main/java/com/ydd/gateway/config/properties/IgnoreWhiteProperties.java

@@ -0,0 +1,33 @@
+package com.ydd.gateway.config.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 放行白名单配置
+ * 
+ * @author ruoyi
+ */
+@Configuration
+@RefreshScope
+@ConfigurationProperties(prefix = "security.ignore")
+public class IgnoreWhiteProperties
+{
+    /**
+     * 放行白名单配置,网关不校验此处的白名单
+     */
+    private List<String> whites = new ArrayList<>();
+
+    public List<String> getWhites()
+    {
+        return whites;
+    }
+
+    public void setWhites(List<String> whites)
+    {
+        this.whites = whites;
+    }
+}

+ 48 - 0
lb-gateway/src/main/java/com/ydd/gateway/config/properties/XssProperties.java

@@ -0,0 +1,48 @@
+package com.ydd.gateway.config.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * XSS跨站脚本配置
+ * 
+ * @author ruoyi
+ */
+@Configuration
+@RefreshScope
+@ConfigurationProperties(prefix = "security.xss")
+public class XssProperties
+{
+    /**
+     * Xss开关
+     */
+    private Boolean enabled;
+
+    /**
+     * 排除路径
+     */
+    private List<String> excludeUrls = new ArrayList<>();
+
+    public Boolean getEnabled()
+    {
+        return enabled;
+    }
+
+    public void setEnabled(Boolean enabled)
+    {
+        this.enabled = enabled;
+    }
+
+    public List<String> getExcludeUrls()
+    {
+        return excludeUrls;
+    }
+
+    public void setExcludeUrls(List<String> excludeUrls)
+    {
+        this.excludeUrls = excludeUrls;
+    }
+}

+ 128 - 0
lb-gateway/src/main/java/com/ydd/gateway/filter/AuthFilter.java

@@ -0,0 +1,128 @@
+//package com.ydd.gateway.filter;
+//
+//import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+//import org.springframework.cloud.gateway.filter.GlobalFilter;
+//import org.springframework.core.Ordered;
+//import org.springframework.http.server.reactive.ServerHttpRequest;
+//import org.springframework.stereotype.Component;
+//import org.springframework.web.server.ServerWebExchange;
+//import com.ydd.gateway.config.properties.IgnoreWhiteProperties;
+//import io.jsonwebtoken.Claims;
+//import reactor.core.publisher.Mono;
+//
+///**
+// * 网关鉴权
+// *
+// * @author ruoyi
+// */
+//@Component
+//public class AuthFilter implements GlobalFilter, Ordered
+//{
+//    private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
+//
+//    // 排除过滤的 uri 地址,nacos自行添加
+//    @Autowired
+//    private IgnoreWhiteProperties ignoreWhite;
+//
+//    @Autowired
+//    private RedisService redisService;
+//
+//
+//    @Override
+//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
+//    {
+//        ServerHttpRequest request = exchange.getRequest();
+//        ServerHttpRequest.Builder mutate = request.mutate();
+//
+//        String url = request.getURI().getPath();
+//        // 跳过不需要验证的路径
+//        if (StringUtils.matches(url, ignoreWhite.getWhites()))
+//        {
+//            return chain.filter(exchange);
+//        }
+//        String token = getToken(request);
+//        if (StringUtils.isEmpty(token))
+//        {
+//            return unauthorizedResponse(exchange, "令牌不能为空");
+//        }
+//        Claims claims = JwtUtils.parseToken(token);
+//        if (claims == null)
+//        {
+//            return unauthorizedResponse(exchange, "令牌已过期或验证不正确!");
+//        }
+//        String userkey = JwtUtils.getUserKey(claims);
+//        boolean islogin = redisService.hasKey(getTokenKey(userkey));
+//        if (!islogin)
+//        {
+//            return unauthorizedResponse(exchange, "登录状态已过期");
+//        }
+//        String userid = JwtUtils.getUserId(claims);
+//        String username = JwtUtils.getUserName(claims);
+//        if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username))
+//        {
+//            return unauthorizedResponse(exchange, "令牌验证失败");
+//        }
+//
+//        // 设置用户信息到请求
+//        addHeader(mutate, SecurityConstants.USER_KEY, userkey);
+//        addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid);
+//        addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username);
+//        // 内部请求来源参数清除
+//        removeHeader(mutate, SecurityConstants.FROM_SOURCE);
+//        return chain.filter(exchange.mutate().request(mutate.build()).build());
+//    }
+//
+//    private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value)
+//    {
+//        if (value == null)
+//        {
+//            return;
+//        }
+//        String valueStr = value.toString();
+//        String valueEncode = ServletUtils.urlEncode(valueStr);
+//        mutate.header(name, valueEncode);
+//    }
+//
+//    private void removeHeader(ServerHttpRequest.Builder mutate, String name)
+//    {
+//        mutate.headers(httpHeaders -> httpHeaders.remove(name)).build();
+//    }
+//
+//    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg)
+//    {
+//        log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
+//        return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED);
+//    }
+//
+//    /**
+//     * 获取缓存key
+//     */
+//    private String getTokenKey(String token)
+//    {
+//        return CacheConstants.LOGIN_TOKEN_KEY + token;
+//    }
+//
+//    /**
+//     * 获取请求token
+//     */
+//    private String getToken(ServerHttpRequest request)
+//    {
+//        String token = request.getHeaders().getFirst(TokenConstants.AUTHENTICATION);
+//        // 如果前端设置了令牌前缀,则裁剪掉前缀
+//        if (StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX))
+//        {
+//            token = token.replaceFirst(TokenConstants.PREFIX, StringUtils.EMPTY);
+//        }
+//        return token;
+//    }
+//
+//    @Override
+//    public int getOrder()
+//    {
+//        return -200;
+//    }
+//}

+ 189 - 0
lb-gateway/src/main/java/com/ydd/gateway/filter/AuthorizeGatewayFilterFactory.java

@@ -0,0 +1,189 @@
+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
+ *
+ */
+@Component
+public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {
+
+    private static final Log logger = LogFactory.getLog(AuthorizeGatewayFilterFactory.class);
+
+//	private static final String AUTHORIZE_TOKEN = "clientId";
+
+    @Autowired
+    FilterService filterService;
+
+    public AuthorizeGatewayFilterFactory() {
+        super(Config.class);
+        logger.info("Loaded GatewayFilterFactory [Authorize]");
+    }
+
+    @Override
+    public List<String> shortcutFieldOrder() {
+        return Arrays.asList("enabled");
+    }
+
+    // url白名单
+    public static final String URL = "/doc.html/**";
+//    @Value("${waimai.meituan.developerId}")
+//    public String aa ;
+    @Override
+    public GatewayFilter apply(AuthorizeGatewayFilterFactory.Config config) {
+        return (exchange, chain) -> {
+            if (!config.isEnabled()) {
+                return chain.filter(exchange);
+            }
+
+            ServerHttpRequest request = exchange.getRequest();
+            ServerHttpResponse response = exchange.getResponse();
+            //	response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
+
+            // url白名单
+            String url = request.getURI().getPath();
+            logger.info(GatewayConfig.NACOS_SERVER_ADDR);
+            String path = request.getPath().pathWithinApplication().value();
+            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);
+            TreeMap<String, String> params = new TreeMap<>();
+            String signStr = headers.getFirst("sign");
+
+            String sourceType = headers.getFirst("sourceType");
+            String time = headers.getFirst("time");// 日期 yyyymmddHHmiss
+            String nonce = headers.getFirst("nonce");// 随机数
+            if (StringUtils.hasText(sourceType)) {
+                params.put("sourceType", sourceType);
+            }
+
+            params.put("time", time);
+            params.put("nonce", nonce);
+
+            // 签名校验
+            Mono<DataBuffer> mono = filterService.validateSign(params, signStr, response);
+            if (mono != null) {
+                //return response.writeWith(mono);
+            }
+            return chain.filter(exchange);
+        };
+    }
+
+    public static class Config {
+
+        // 控制是否开启认证
+        private boolean enabled;
+
+        public Config() {
+        }
+
+        public boolean isEnabled() {
+            return enabled;
+        }
+
+        public void setEnabled(boolean enabled) {
+            this.enabled = enabled;
+        }
+
+    }
+
+    public void logInfo(ServerHttpRequest request, HttpHeaders headers) {
+
+        String remoteIP = headers.getFirst("x-real-ip");
+        if (!StringUtils.hasText(remoteIP)) {
+            remoteIP = request.getRemoteAddress().getHostName();
+        }
+        String method = request.getMethodValue();
+        String reqParams = JSON.toJSONString(request.getQueryParams(), SerializerFeature.DisableCircularReferenceDetect,
+                SerializerFeature.WriteMapNullValue);
+        String path = request.getPath().pathWithinApplication().value();
+        logger.info("请求方的IP:" + remoteIP);
+        logger.info("请求的接口:" + path);
+        logger.info("请求的类型:" + method);
+        logger.info("请求的参数:" + reqParams);
+
+    }
+
+
+}

+ 65 - 0
lb-gateway/src/main/java/com/ydd/gateway/filter/BlackListUrlFilter.java

@@ -0,0 +1,65 @@
+package com.ydd.gateway.filter;
+
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * 黑名单过滤器
+ * 
+ * @author ruoyi
+ */
+//@Component
+public class BlackListUrlFilter extends AbstractGatewayFilterFactory<BlackListUrlFilter.Config>
+{
+    @Override
+    public GatewayFilter apply(Config config)
+    {
+        return (exchange, chain) -> {
+
+//            String url = exchange.getRequest().getURI().getPath();
+//            if (config.matchBlacklist(url))
+//            {
+//                return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求地址不允许访问");
+//            }
+
+            return chain.filter(exchange);
+        };
+    }
+
+    public BlackListUrlFilter()
+    {
+        super(Config.class);
+    }
+
+    public static class Config
+    {
+        private List<String> blacklistUrl;
+
+        private List<Pattern> blacklistUrlPattern = new ArrayList<>();
+
+        public boolean matchBlacklist(String url)
+        {
+            return blacklistUrlPattern.isEmpty() ? false : blacklistUrlPattern.stream().filter(p -> p.matcher(url).find()).findAny().isPresent();
+        }
+
+        public List<String> getBlacklistUrl()
+        {
+            return blacklistUrl;
+        }
+
+        public void setBlacklistUrl(List<String> blacklistUrl)
+        {
+            this.blacklistUrl = blacklistUrl;
+            this.blacklistUrlPattern.clear();
+            this.blacklistUrl.forEach(url -> {
+                this.blacklistUrlPattern.add(Pattern.compile(url.replaceAll("\\*\\*", "(.*?)"), Pattern.CASE_INSENSITIVE));
+            });
+        }
+    }
+
+}

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

@@ -0,0 +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;
+//        }
+//    }
+//}

+ 210 - 0
lb-gateway/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
lb-gateway/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;
+    }
+}

+ 39 - 0
lb-gateway/src/main/java/com/ydd/gateway/filter/ResponseObject.java

@@ -0,0 +1,39 @@
+package com.ydd.gateway.filter;
+
+public class ResponseObject {
+
+	public String result;
+
+	private String msg;
+
+	private String uri;
+
+	public ResponseObject() {
+
+	}
+
+	public String getResult() {
+		return result;
+	}
+
+	public void setResult(String result) {
+		this.result = result;
+	}
+
+	public String getMsg() {
+		return msg;
+	}
+
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+
+	public String getUri() {
+		return uri;
+	}
+
+	public void setUri(String uri) {
+		this.uri = uri;
+	}
+
+}

+ 120 - 0
lb-gateway/src/main/java/com/ydd/gateway/filter/XssFilter.java

@@ -0,0 +1,120 @@
+//package com.ydd.gateway.filter;
+//
+//import java.nio.charset.StandardCharsets;
+//
+//
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+//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.core.io.buffer.NettyDataBufferFactory;
+//import org.springframework.http.HttpHeaders;
+//import org.springframework.http.HttpMethod;
+//import org.springframework.http.MediaType;
+//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 com.ydd.gateway.config.properties.XssProperties;
+//import io.netty.buffer.ByteBufAllocator;
+//import reactor.core.publisher.Flux;
+//import reactor.core.publisher.Mono;
+//
+///**
+// * 跨站脚本过滤器
+// *
+// * @author ruoyi
+// */
+//@Component
+//@ConditionalOnProperty(value = "security.xss.enabled", havingValue = "true")
+//public class XssFilter implements GlobalFilter, Ordered
+//{
+//    // 跨站脚本的 xss 配置,nacos自行添加
+//    @Autowired
+//    private XssProperties xss;
+//
+//    @Override
+//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
+//    {
+//        ServerHttpRequest request = exchange.getRequest();
+//        // GET DELETE 不过滤
+//        HttpMethod method = request.getMethod();
+//        if (method == null || method.matches("GET") || method.matches("DELETE"))
+//        {
+//            return chain.filter(exchange);
+//        }
+//        // 非json类型,不过滤
+//        if (!isJsonRequest(exchange))
+//        {
+//            return chain.filter(exchange);
+//        }
+//        // excludeUrls 不过滤
+//        String url = request.getURI().getPath();
+////        if (StringUtils.matches(url, xss.getExcludeUrls()))
+////        {
+////            return chain.filter(exchange);
+////        }
+//        ServerHttpRequestDecorator httpRequestDecorator = requestDecorator(exchange);
+//        return chain.filter(exchange.mutate().request(httpRequestDecorator).build());
+//
+//    }
+//
+//    private ServerHttpRequestDecorator requestDecorator(ServerWebExchange exchange)
+//    {
+//        ServerHttpRequestDecorator serverHttpRequestDecorator = new ServerHttpRequestDecorator(exchange.getRequest())
+//        {
+//            @Override
+//            public Flux<DataBuffer> getBody()
+//            {
+//                Flux<DataBuffer> body = super.getBody();
+//                return body.map(dataBuffer -> {
+//                    byte[] content = new byte[dataBuffer.readableByteCount()];
+//                    dataBuffer.read(content);
+//                    DataBufferUtils.release(dataBuffer);
+//                    String bodyStr = new String(content, StandardCharsets.UTF_8);
+//                    // 防xss攻击过滤
+//                    bodyStr = EscapeUtil.clean(bodyStr);
+//                    // 转成字节
+//                    byte[] bytes = bodyStr.getBytes();
+//                    NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
+//                    DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
+//                    buffer.write(bytes);
+//                    return buffer;
+//                });
+//            }
+//
+//            @Override
+//            public HttpHeaders getHeaders()
+//            {
+//                HttpHeaders httpHeaders = new HttpHeaders();
+//                httpHeaders.putAll(super.getHeaders());
+//                // 由于修改了请求体的body,导致content-length长度不确定,因此需要删除原先的content-length
+//                httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);
+//                httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
+//                return httpHeaders;
+//            }
+//
+//        };
+//        return serverHttpRequestDecorator;
+//    }
+//
+//    /**
+//     * 是否是Json请求
+//     *
+//     * @param exchange
+//     */
+//    public boolean isJsonRequest(ServerWebExchange exchange)
+//    {
+//        String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
+//        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
+//    }
+//
+//    @Override
+//    public int getOrder()
+//    {
+//        return -100;
+//    }
+//}

+ 56 - 0
lb-gateway/src/main/java/com/ydd/gateway/handler/GatewayExceptionHandler.java

@@ -0,0 +1,56 @@
+//package com.ydd.gateway.handler;
+//
+//import com.ydd.common.utils.ServletUtils;
+//import org.springframework.cloud.gateway.support.NotFoundException;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+//import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.core.annotation.Order;
+//import org.springframework.http.server.reactive.ServerHttpResponse;
+//import org.springframework.web.server.ResponseStatusException;
+//import org.springframework.web.server.ServerWebExchange;
+//import reactor.core.publisher.Mono;
+//
+///**
+// * 网关统一异常处理
+// *
+// * @author ruoyi
+// */
+//@Order(-1)
+//@Configuration
+//public class GatewayExceptionHandler implements ErrorWebExceptionHandler
+//{
+//    private static final Logger log = LoggerFactory.getLogger(GatewayExceptionHandler.class);
+//
+//    @Override
+//    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex)
+//    {
+//        ServerHttpResponse response = exchange.getResponse();
+//
+//        if (exchange.getResponse().isCommitted())
+//        {
+//            return Mono.error(ex);
+//        }
+//
+//        String msg;
+//
+//        if (ex instanceof NotFoundException)
+//        {
+//            msg = "服务未找到";
+//        }
+//        else if (ex instanceof ResponseStatusException)
+//        {
+//            ResponseStatusException responseStatusException = (ResponseStatusException) ex;
+//            msg = responseStatusException.getMessage();
+//        }
+//        else
+//        {
+//            msg = "内部服务器错误";
+//        }
+//
+//        log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage());
+//
+//        return ServletUtils.webFluxResponseWriter(response, msg);
+//    }
+//}

+ 41 - 0
lb-gateway/src/main/java/com/ydd/gateway/handler/SentinelFallbackHandler.java

@@ -0,0 +1,41 @@
+//package com.ydd.gateway.handler;
+//
+//import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
+//import com.alibaba.csp.sentinel.slots.block.BlockException;
+//import com.ydd.common.utils.ServletUtils;
+//import org.springframework.web.reactive.function.server.ServerResponse;
+//import org.springframework.web.server.ServerWebExchange;
+//import org.springframework.web.server.WebExceptionHandler;
+//import reactor.core.publisher.Mono;
+//
+///**
+// * 自定义限流异常处理
+// *
+// * @author ruoyi
+// */
+//public class SentinelFallbackHandler implements WebExceptionHandler
+//{
+//    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange)
+//    {
+//        return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍候再试");
+//    }
+//
+//    @Override
+//    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex)
+//    {
+//        if (exchange.getResponse().isCommitted())
+//        {
+//            return Mono.error(ex);
+//        }
+//        if (!BlockException.isBlockException(ex))
+//        {
+//            return Mono.error(ex);
+//        }
+//        return handleBlockedRequest(exchange, ex).flatMap(response -> writeResponse(response, exchange));
+//    }
+//
+//    private Mono<ServerResponse> handleBlockedRequest(ServerWebExchange exchange, Throwable throwable)
+//    {
+//        return GatewayCallbackManager.getBlockHandler().handleRequest(exchange, throwable);
+//    }
+//}

+ 119 - 0
lb-gateway/src/main/java/com/ydd/gateway/service/FilterService.java

@@ -0,0 +1,119 @@
+package com.ydd.gateway.service;
+
+import com.alibaba.fastjson.JSON;
+import com.ydd.gateway.filter.AuthorizeGatewayFilterFactory;
+import com.ydd.gateway.filter.ResponseObject;
+
+import com.ydd.gateway.util.Md5Util;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import reactor.core.publisher.Mono;
+
+import java.nio.charset.StandardCharsets;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.TreeMap;
+
+@Component
+public class FilterService {
+
+	private static final Log logger = LogFactory.getLog(AuthorizeGatewayFilterFactory.class);
+
+	private static final String AUTHORIZE_TOKEN = "clientId";
+
+//	@Autowired
+//	RedisTemplate redisTemplate;
+	public Mono<DataBuffer> validateSign(TreeMap<String, String> params, String signStr, ServerHttpResponse response) {
+		if (StringUtils.isEmpty(signStr)) {
+			ResponseObject data = new ResponseObject();
+			data.setResult("error");
+			data.setMsg("非法请求");
+			byte[] datas = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
+			DataBuffer buffer = response.bufferFactory().wrap(datas);
+			response.setStatusCode(HttpStatus.BAD_REQUEST);
+			return Mono.just(buffer);
+		}
+
+		// logger.info("签名参数" + params.toString());
+		// logger.info("签名值" + signStr);
+		// logger.info("签名后的值" + Md5Util.sign(params));
+
+		// 查看传过来的日期与当前日期比较相差几分钟
+		long min = getMin(params.get("time"));
+		if (min >= 3) {// 暂时定相差三分钟为无效请求
+			logger.info("相差三分钟为无效请求");
+			ResponseObject data = new ResponseObject();
+			data.setResult("error");
+			data.setMsg("非法请求");
+			byte[] datas = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
+			DataBuffer buffer = response.bufferFactory().wrap(datas);
+			response.setStatusCode(HttpStatus.BAD_REQUEST);
+			return Mono.just(buffer);
+		}
+
+		boolean right = Md5Util.verifySign(params, signStr);
+		if (!right) {
+			ResponseObject data = new ResponseObject();
+			data.setResult("error");
+			data.setMsg("签名不合法");
+			byte[] datas = JSON.toJSONString(data).getBytes(StandardCharsets.UTF_8);
+			DataBuffer buffer = response.bufferFactory().wrap(datas);
+			response.setStatusCode(HttpStatus.UNAUTHORIZED);
+
+			return Mono.just(buffer);
+		}
+		return null;
+	}
+
+
+
+	/**
+	 * 比较与当前时间相差几分钟
+	 * 
+	 * @param time
+	 * @return
+	 * @throws Exception
+	 */
+	public long getMin(String time) {
+		long nd = 1000 * 24 * 60 * 60;
+
+		long nh = 1000 * 60 * 60;
+
+		long nm = 1000 * 60;
+
+		// long ns = 1000;
+
+		// 获得两个时间的毫秒时间差异
+		// String time = "20190321141020";
+		Calendar cal = Calendar.getInstance();
+		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+		long diff = 0;
+		try {
+			diff = cal.getTimeInMillis() - sdf.parse(time).getTime();
+		}
+		catch (ParseException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
+		// 计算差多少天
+		long day = diff / nd;
+
+		// 计算差多少小时
+		long hour = diff % nd / nh;
+
+		// 计算差多少分钟
+		long min = diff % nd % nh / nm;
+
+		// 计算差多少秒//输出结果
+		// long sec = diff % nd % nh % nm / ns;
+		return min;
+	}
+}

+ 30 - 0
lb-gateway/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
lb-gateway/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()));
+    }
+}

+ 85 - 0
lb-gateway/src/main/java/com/ydd/gateway/util/CharsetKit.java

@@ -0,0 +1,85 @@
+package com.ydd.gateway.util;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * 字符集工具类
+ * 
+ * @author ruoyi
+ */
+public class CharsetKit
+{
+    /** ISO-8859-1 */
+    public static final String ISO_8859_1 = "ISO-8859-1";
+    /** UTF-8 */
+    public static final String UTF_8 = "UTF-8";
+    /** GBK */
+    public static final String GBK = "GBK";
+
+    /** ISO-8859-1 */
+    public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+    /** UTF-8 */
+    public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+    /** GBK */
+    public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+    /**
+     * 转换为Charset对象
+     * 
+     * @param charset 字符集,为空则返回默认字符集
+     * @return Charset
+     */
+    public static Charset charset(String charset)
+    {
+        return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+    }
+
+    /**
+     * 转换字符串的字符集编码
+     * 
+     * @param source 字符串
+     * @param srcCharset 源字符集,默认ISO-8859-1
+     * @param destCharset 目标字符集,默认UTF-8
+     * @return 转换后的字符集
+     */
+    public static String convert(String source, String srcCharset, String destCharset)
+    {
+        return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+    }
+
+    /**
+     * 转换字符串的字符集编码
+     * 
+     * @param source 字符串
+     * @param srcCharset 源字符集,默认ISO-8859-1
+     * @param destCharset 目标字符集,默认UTF-8
+     * @return 转换后的字符集
+     */
+    public static String convert(String source, Charset srcCharset, Charset destCharset)
+    {
+        if (null == srcCharset)
+        {
+            srcCharset = StandardCharsets.ISO_8859_1;
+        }
+
+        if (null == destCharset)
+        {
+            destCharset = StandardCharsets.UTF_8;
+        }
+
+        if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
+        {
+            return source;
+        }
+        return new String(source.getBytes(srcCharset), destCharset);
+    }
+
+    /**
+     * @return 系统字符集编码
+     */
+    public static String systemCharset()
+    {
+        return Charset.defaultCharset().name();
+    }
+}

File diff suppressed because it is too large
+ 1012 - 0
lb-gateway/src/main/java/com/ydd/gateway/util/Convert.java


+ 107 - 0
lb-gateway/src/main/java/com/ydd/gateway/util/Md5Util.java

@@ -0,0 +1,107 @@
+package com.ydd.gateway.util;
+
+import java.io.UnsupportedEncodingException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+public class Md5Util {
+
+	private static final Log logger = LogFactory.getLog(Md5Util.class);
+
+	private static final String[] STRDIGITS = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
+
+	public static final String APP_KEY = "BE53C102BA2176C77BCC29F8E4B7EEA9";
+
+	public static String md5(String string) {
+		byte[] hash;
+		try {
+			hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
+		}
+		catch (UnsupportedEncodingException e) {
+			throw new RuntimeException("UTF-8 is unsupported", e);
+		}
+		catch (NoSuchAlgorithmException e) {
+			throw new RuntimeException("MessageDigest不支持MD5Util", e);
+		}
+		StringBuilder hex = new StringBuilder(hash.length * 2);
+		for (byte b : hash) {
+			if ((b & 0xFF) < 0x10) {
+				hex.append("0");
+			}
+			hex.append(Integer.toHexString(b & 0xFF));
+		}
+		return hex.toString();
+	}
+
+	/**
+	 * md5签名 按参数名称升序,将参数值进行连接 签名
+	 *
+	 * @param
+	 * @param params
+	 * @return
+	 */
+	public static String sign(TreeMap<String, String> params) {
+		StringBuilder paramValues = new StringBuilder();
+		for (Entry<String, String> entry : params.entrySet()) {
+			paramValues.append(entry.getKey());
+			paramValues.append("=");
+			paramValues.append(entry.getValue());
+		}
+		paramValues.append(APP_KEY);
+		return md5(paramValues.toString()).toUpperCase();
+	}
+
+	/**
+	 * 请求参数签名验证
+	 *
+	 * @param
+	 * @param
+	 * @return true 验证通过 false 验证失败
+	 * @throws Exception
+	 */
+	public static boolean verifySign(TreeMap<String, String> params, String signStr) {
+		return sign(params).equals(signStr);
+	}
+
+	private static String byteToString(byte[] bByte) {
+		StringBuffer sBuffer = new StringBuffer();
+
+		for (int i = 0; i < bByte.length; ++i) {
+			sBuffer.append(byteToArrayString(bByte[i]));
+		}
+
+		return sBuffer.toString();
+	}
+
+	private static String byteToArrayString(byte bByte) {
+		int iRet = bByte;
+		if (bByte < 0) {
+			iRet = bByte + 256;
+		}
+
+		int iD1 = iRet / 16;
+		int iD2 = iRet % 16;
+		return STRDIGITS[iD1] + STRDIGITS[iD2];
+	}
+
+	public static String getMD5Code(String strObj, String charsetname) {
+		String resultString = null;
+
+		try {
+			new String(strObj);
+			MessageDigest md = MessageDigest.getInstance("MD5");
+			resultString = byteToString(md.digest(strObj.getBytes(charsetname)));
+		}
+		catch (Exception var4) {
+			var4.printStackTrace();
+		}
+
+		return resultString;
+	}
+}

+ 90 - 0
lb-gateway/src/main/java/com/ydd/gateway/util/StrFormatter.java

@@ -0,0 +1,90 @@
+package com.ydd.gateway.util;
+
+/**
+ * 字符串格式化
+ *
+ * @author ruoyi
+ */
+public class StrFormatter
+{
+    public static final String EMPTY_JSON = "{}";
+    public static final char C_BACKSLASH = '\\';
+    public static final char C_DELIM_START = '{';
+    public static final char C_DELIM_END = '}';
+
+    /**
+     * 格式化字符串<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     *
+     * @param strPattern 字符串模板
+     * @param argArray 参数列表
+     * @return 结果
+     */
+    public static String format(final String strPattern, final Object... argArray)
+    {
+        if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
+        {
+            return strPattern;
+        }
+        final int strPatternLength = strPattern.length();
+
+        // 初始化定义好的长度以获得更好的性能
+        StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+        int handledPosition = 0;
+        int delimIndex;// 占位符所在位置
+        for (int argIndex = 0; argIndex < argArray.length; argIndex++)
+        {
+            delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+            if (delimIndex == -1)
+            {
+                if (handledPosition == 0)
+                {
+                    return strPattern;
+                }
+                else
+                { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
+                    sbuf.append(strPattern, handledPosition, strPatternLength);
+                    return sbuf.toString();
+                }
+            }
+            else
+            {
+                if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
+                {
+                    if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
+                    {
+                        // 转义符之前还有一个转义符,占位符依旧有效
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                        handledPosition = delimIndex + 2;
+                    }
+                    else
+                    {
+                        // 占位符被转义
+                        argIndex--;
+                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
+                        sbuf.append(C_DELIM_START);
+                        handledPosition = delimIndex + 1;
+                    }
+                }
+                else
+                {
+                    // 正常占位符
+                    sbuf.append(strPattern, handledPosition, delimIndex);
+                    sbuf.append(Convert.utf8Str(argArray[argIndex]));
+                    handledPosition = delimIndex + 2;
+                }
+            }
+        }
+        // 加入最后一个占位符后所有的字符
+        sbuf.append(strPattern, handledPosition, strPattern.length());
+
+        return sbuf.toString();
+    }
+}

+ 480 - 0
lb-gateway/src/main/java/com/ydd/gateway/util/StringUtils.java

@@ -0,0 +1,480 @@
+package com.ydd.gateway.util;
+
+import org.springframework.util.AntPathMatcher;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 字符串工具类
+ *
+ * @author ruoyi
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 空字符串 */
+    private static final String NULLSTR = "";
+
+    /** 下划线 */
+    private static final char SEPARATOR = '_';
+
+    /**
+     * 获取参数不为空值
+     *
+     * @param value defaultValue 要判断的value
+     * @return value 返回值
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 判断一个Collection是否为空, 包含List,Set,Queue
+     *
+     * @param coll 要判断的Collection
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 判断一个Collection是否非空,包含List,Set,Queue
+     *
+     * @param coll 要判断的Collection
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+
+    /**
+     * * 判断一个对象数组是否为空
+     *
+     * @param objects 要判断的对象数组
+     ** @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 判断一个对象数组是否非空
+     *
+     * @param objects 要判断的对象数组
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     *
+     * @param map 要判断的Map
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     *
+     * @param map 要判断的Map
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 判断一个字符串是否为空串
+     *
+     * @param str String
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 判断一个字符串是否为非空串
+     *
+     * @param str String
+     * @return true:非空串 false:空串
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 判断一个对象是否为空
+     *
+     * @param object Object
+     * @return true:为空 false:非空
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 判断一个对象是否非空
+     *
+     * @param object Object
+     * @return true:非空 false:空
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 判断一个对象是否是数组类型(Java基本型别的数组)
+     *
+     * @param object 对象
+     * @return true:是数组 false:不是数组
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 去空格
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 截取字符串
+     *
+     * @param str 字符串
+     * @param start 开始
+     * @return 结果
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 截取字符串
+     *
+     * @param str 字符串
+     * @param start 开始
+     * @param end 结束
+     * @return 结果
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+    /**
+     * 判断是否为空,并且不是空白字符
+     *
+     * @param str 要判断的value
+     * @return 结果
+     */
+    public static boolean hasText(String str)
+    {
+        return (str != null && !str.isEmpty() && containsText(str));
+    }
+
+    private static boolean containsText(CharSequence str)
+    {
+        int strLen = str.length();
+        for (int i = 0; i < strLen; i++)
+        {
+            if (!Character.isWhitespace(str.charAt(i)))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 格式化文本, {} 表示占位符<br>
+     * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
+     * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
+     * 例:<br>
+     * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
+     * 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+     * 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+     *
+     * @param template 文本模板,被替换的部分用 {} 表示
+     * @param params 参数值
+     * @return 格式化后的文本
+     */
+    public static String format(String template, Object... params)
+    {
+        if (isEmpty(params) || isEmpty(template))
+        {
+            return template;
+        }
+        return StrFormatter.format(template, params);
+    }
+
+    /**
+     * 是否为http(s)://开头
+     *
+     * @param link 链接
+     * @return 结果
+     */
+    public static boolean ishttp(String link)
+    {
+        return StringUtils.startsWithAny(link,  "http://", "https://");
+    }
+
+    /**
+     * 驼峰转下划线命名
+     */
+    public static String toUnderScoreCase(String str)
+    {
+        if (str == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        // 前置字符是否大写
+        boolean preCharIsUpperCase = true;
+        // 当前字符是否大写
+        boolean curreCharIsUpperCase = true;
+        // 下一字符是否大写
+        boolean nexteCharIsUpperCase = true;
+        for (int i = 0; i < str.length(); i++)
+        {
+            char c = str.charAt(i);
+            if (i > 0)
+            {
+                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+            }
+            else
+            {
+                preCharIsUpperCase = false;
+            }
+
+            curreCharIsUpperCase = Character.isUpperCase(c);
+
+            if (i < (str.length() - 1))
+            {
+                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+            }
+
+            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+            {
+                sb.append(SEPARATOR);
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 是否包含字符串
+     *
+     * @param str 验证字符串
+     * @param strs 字符串组
+     * @return 包含返回true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+     *
+     * @param name 转换前的下划线大写方式命名的字符串
+     * @return 转换后的驼峰式命名的字符串
+     */
+    public static String convertToCamelCase(String name)
+    {
+        StringBuilder result = new StringBuilder();
+        // 快速检查
+        if (name == null || name.isEmpty())
+        {
+            // 没必要转换
+            return "";
+        }
+        else if (!name.contains("_"))
+        {
+            // 不含下划线,仅将首字母大写
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        // 用下划线将原始字符串分割
+        String[] camels = name.split("_");
+        for (String camel : camels)
+        {
+            // 跳过原始字符串中开头、结尾的下换线或双重下划线
+            if (camel.isEmpty())
+            {
+                continue;
+            }
+            // 首字母大写
+            result.append(camel.substring(0, 1).toUpperCase());
+            result.append(camel.substring(1).toLowerCase());
+        }
+        return result.toString();
+    }
+
+    /**
+     * 驼峰式命名法 例如:user_name->userName
+     */
+    public static String toCamelCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        s = s.toLowerCase();
+        StringBuilder sb = new StringBuilder(s.length());
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            if (c == SEPARATOR)
+            {
+                upperCase = true;
+            }
+            else if (upperCase)
+            {
+                sb.append(Character.toUpperCase(c));
+                upperCase = false;
+            }
+            else
+            {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
+     *
+     * @param str 指定字符串
+     * @param strs 需要检查的字符串数组
+     * @return 是否匹配
+     */
+    public static boolean matches(String str, List<String> strs)
+    {
+        if (isEmpty(str) || isEmpty(strs))
+        {
+            return false;
+        }
+        for (String pattern : strs)
+        {
+            if (isMatch(pattern, str))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 判断url是否与规则配置:
+     * ? 表示单个字符;
+     * * 表示一层路径内的任意字符串,不可跨层级;
+     * ** 表示任意层路径;
+     *
+     * @param pattern 匹配规则
+     * @param url 需要匹配的url
+     * @return
+     */
+    public static boolean isMatch(String pattern, String url)
+    {
+        AntPathMatcher matcher = new AntPathMatcher();
+        return matcher.match(pattern, url);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T cast(Object obj)
+    {
+        return (T) obj;
+    }
+}

+ 26 - 0
lb-gateway/src/main/resources/application.yml

@@ -0,0 +1,26 @@
+spring:
+  cloud:
+    gateway:
+      #default-filters:
+      #- Authorize=true
+      discovery:
+        locator:
+          enabled: false
+      routes:
+        - id: api-beta
+          uri: lb://lb-app
+          # uri: http://www.baidu.com/
+          predicates:
+            #匹配所有请求路径以
+            - Path=/**
+            - Header=citycode,0512
+          filters:
+            - Authorize=true
+        - id: api-release
+          uri: lb://lb-app
+          #  uri:  http://www.2500sz.com/
+          predicates:
+            #匹配所有请求路径以
+            - Path=/**
+          filters:
+            - Authorize=true

+ 10 - 0
lb-gateway/src/main/resources/banner.txt

@@ -0,0 +1,10 @@
+Spring Boot Version: ${spring-boot.version}
+Spring Application Name: ${spring.application.name}
+                            _                        _                                 
+                           (_)                      | |                                
+ _ __  _   _   ___   _   _  _  ______   __ _   __ _ | |_   ___ __      __  __ _  _   _ 
+| '__|| | | | / _ \ | | | || ||______| / _` | / _` || __| / _ \\ \ /\ / / / _` || | | |
+| |   | |_| || (_) || |_| || |        | (_| || (_| || |_ |  __/ \ V  V / | (_| || |_| |
+|_|    \__,_| \___/  \__, ||_|         \__, | \__,_| \__| \___|  \_/\_/   \__,_| \__, |
+                      __/ |             __/ |                                     __/ |
+                     |___/             |___/                                     |___/ 

+ 24 - 0
lb-gateway/src/main/resources/bootstrap.yml

@@ -0,0 +1,24 @@
+# Tomcat
+server:
+  port: 8080
+
+# Spring
+spring:
+  application:
+    name: lb-gateway
+  profiles:
+    active: dev
+  cloud:
+    nacos:
+      discovery:
+      # 服务注册地址
+        server-addr: 153.37.175.42:28848
+      config:
+       # 配置中心地址
+        server-addr: 153.37.175.42:28848
+        file-extension: yaml         # 配置文件格式
+      # 共享配置
+        shared-configs[0]:
+          data-id: lb_application-dev.yaml
+          refresh: false
+

+ 74 - 0
lb-gateway/src/main/resources/logback.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+    <!-- 日志存放路径 -->
+	<property name="log.path" value="logs/lb-gateway" />
+   <!-- 日志输出格式 -->
+	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+    <!-- 控制台输出 -->
+	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+	</appender>
+
+    <!-- 系统日志输出 -->
+	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/info.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+			<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+		</rollingPolicy>
+		<encoder>
+			<pattern>${log.pattern}</pattern>
+		</encoder>
+		<filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>INFO</level>
+            <!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+            <!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+	</appender>
+
+    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/error.log</file>
+        <!-- 循环政策:基于时间创建日志文件 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!-- 日志文件名格式 -->
+            <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<!-- 日志最大的历史 60天 -->
+			<maxHistory>60</maxHistory>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${log.pattern}</pattern>
+        </encoder>
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <!-- 过滤的级别 -->
+            <level>ERROR</level>
+			<!-- 匹配时的操作:接收(记录) -->
+            <onMatch>ACCEPT</onMatch>
+			<!-- 不匹配时的操作:拒绝(不记录) -->
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+    <!-- 系统模块日志级别控制  -->
+	<logger name="com.ruoyi" level="info" />
+	<!-- Spring日志级别控制  -->
+	<logger name="org.springframework" level="warn" />
+
+	<root level="info">
+		<appender-ref ref="console" />
+	</root>
+	
+	<!--系统操作日志-->
+    <root level="info">
+        <appender-ref ref="file_info" />
+        <appender-ref ref="file_error" />
+    </root>
+</configuration>

+ 1 - 1
lb-module/src/main/resources/mapper/system/SysUserRoleMapper.xml

@@ -49,4 +49,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		</foreach>
 	</select>
 
-</mapper> 
+</mapper>

+ 6 - 0
lb-third/lb-third-waimai/src/main/java/com/ydd/third/controller/MeiTuanSgController.java

@@ -82,4 +82,10 @@ public class MeiTuanSgController {
     public ResObject<MeituanSgRemindOrderResultVo> doRemindOrderSg(@RequestParam Map<String, String> params) {
         return callback.doRemindOrder(params);
     }
+
+    @PostMapping(value = "/meituansg/syncRiderPosition")
+    ResObject syncRiderPosition(@RequestBody SyncRiderPositionStatusVo syncRiderPositionVo){
+        return meituanSgClient.syncRiderPosition(syncRiderPositionVo);
+    }
+
 }

+ 37 - 0
lb-third/lb-third-waimai/src/main/java/com/ydd/third/controller/WaimaiController.java

@@ -0,0 +1,37 @@
+package com.ydd.third.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.ydd.third.common.vo.ResObject;
+import com.ydd.third.common.vo.waimai.*;
+import com.ydd.third.print.request.MeituanWmDto;
+import com.ydd.third.waimai.Client;
+import com.ydd.third.waimai.meituan.MeituanCallback;
+import com.ydd.third.waimai.meituan.MeituanClient;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Map;
+
+/**
+ * 美团外卖相关api
+ * @author 叶君翔
+ * @date 2021/11/10 11:59
+ */
+@RestController
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+public class WaimaiController {
+
+
+    private final Client client;
+
+    /**
+     * 同步骑手位置
+     */
+    @PostMapping(value="/waimai/syncRiderPositionStatus")
+    public ResObject syncRiderPositionStatus(@RequestBody SyncRiderPositionStatusVo syncRiderPositionVo) {
+        return client.syncRiderPositionStatus(syncRiderPositionVo);
+    }
+
+
+}

+ 1 - 0
pom.xml

@@ -19,6 +19,7 @@
         <module>lb-framework</module>
 <!--        <module>lb-task</module>-->
         <module>lb-feginclient</module>
+        <module>lb-gateway</module>
     </modules>
 
     <properties>