diff --git a/changelog.md b/changelog.md index a9df5053..a93fda6e 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,9 @@ # changelog +## 4.2.7 + +- 修复两个微服务相同path问题 + ## 4.2.6 - 优化网关超时处理 diff --git a/pom.xml b/pom.xml index 123dab3b..25a95e36 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ - 4.2.6-SNAPSHOT + 4.2.7-SNAPSHOT 1.8 UTF-8 diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/TargetRoute.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/TargetRoute.java index 32ea5569..a2dfa393 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/TargetRoute.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/TargetRoute.java @@ -19,4 +19,6 @@ public interface TargetRoute { */ RouteDefinition getRouteDefinition(); + String getFullPath(); + } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java index 93c76f88..49de630a 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/ServerWebExchangeUtil.java @@ -61,7 +61,7 @@ public class ServerWebExchangeUtil { .mutate(); ServerHttpRequest newRequest = builder .header(ParamNames.HEADER_VERSION_NAME, forwardInfo.getVersion()) - .path(forwardInfo.getPath()).build(); + .path(forwardInfo.getFullPath()).build(); return exchange.mutate().request(newRequest).build(); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java index 7ff6c428..0ef53350 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayRouteRepository.java @@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.event.RefreshRoutesEvent; +import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory; import org.springframework.cloud.gateway.route.Route; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; @@ -48,15 +49,20 @@ public class GatewayRouteRepository implements RouteRepository routeDefinitionList = routes.values() - .stream() - .map(GatewayTargetRoute::getRouteDefinition) - .collect(Collectors.toList()); - routeDefinitionList.forEach(routeDefinition -> builder.route(routeDefinition.getId(), - r -> r.path(routeDefinition.getPath()) - .uri(routeDefinition.getUri()))); + routes.values().forEach(gatewayTargetRoute -> { + RouteDefinition routeDefinition = gatewayTargetRoute.getRouteDefinition(); + RewritePathGatewayFilterFactory rewritePathGatewayFilterFactory = new RewritePathGatewayFilterFactory(); + RewritePathGatewayFilterFactory.Config config = new RewritePathGatewayFilterFactory.Config(); + config.setRegexp(gatewayTargetRoute.getFullPath()); + config.setReplacement(routeDefinition.getPath()); + builder.route(routeDefinition.getId(), + r -> r.path(routeDefinition.getPath()) + // path匹配 + .filters(gatewayFilterSpec -> gatewayFilterSpec.filter(rewritePathGatewayFilterFactory.apply(config))) + .uri(routeDefinition.getUri()) + ); + }); this.routeLocator = builder.build(); - // 触发 applicationContext.publishEvent(new RefreshRoutesEvent(new Object())); } diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayTargetRoute.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayTargetRoute.java index 8249da2a..6f33b835 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayTargetRoute.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/GatewayTargetRoute.java @@ -3,6 +3,7 @@ package com.gitee.sop.gatewaycommon.gateway.route; import com.gitee.sop.gatewaycommon.bean.RouteDefinition; import com.gitee.sop.gatewaycommon.bean.ServiceDefinition; import com.gitee.sop.gatewaycommon.bean.TargetRoute; +import org.springframework.util.StringUtils; /** * @author tanghc @@ -18,6 +19,13 @@ public class GatewayTargetRoute implements TargetRoute { this.routeDefinition = routeDefinition; } + @Override + public String getFullPath() { + String serviceId = serviceDefinition.getServiceId(); + String path = StringUtils.trimLeadingCharacter(routeDefinition.getPath(), '/'); + return "/" + serviceId + "/" + path; + } + @Override public ServiceDefinition getServiceDefinition() { return serviceDefinition; diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java index e822712e..f08c089e 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/route/ForwardInfo.java @@ -19,6 +19,10 @@ public class ForwardInfo { this.targetRoute = targetRoute; } + public String getFullPath() { + return targetRoute.getFullPath(); + } + public String getPath() { return targetRoute.getRouteDefinition().getPath(); } @@ -41,6 +45,11 @@ public class ForwardInfo { super(targetRoute); } + @Override + public String getFullPath() { + return getPath(); + } + @Override public String getPath() { return VALIDATE_ERROR_PATH; diff --git a/sop-example/sop-springmvc/src/main/java/com/gitee/app/controller/HomeController.java b/sop-example/sop-springmvc/src/main/java/com/gitee/app/controller/HomeController.java index 2500930b..8141a359 100644 --- a/sop-example/sop-springmvc/src/main/java/com/gitee/app/controller/HomeController.java +++ b/sop-example/sop-springmvc/src/main/java/com/gitee/app/controller/HomeController.java @@ -1,6 +1,7 @@ package com.gitee.app.controller; import com.gitee.app.model.Goods; +import com.gitee.app.model.StoryParam; import com.gitee.sop.servercommon.annotation.Open; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -56,4 +57,12 @@ public class HomeController { return goods; } + @Open("springmvc.path.same") + @RequestMapping("iam_same_path") + @ResponseBody + public Object iam_same_path(StoryParam param) { + param.setName(param.getName() + " mvc.."); + return param; + } + } diff --git a/sop-example/sop-springmvc/src/main/java/com/gitee/app/model/StoryParam.java b/sop-example/sop-springmvc/src/main/java/com/gitee/app/model/StoryParam.java new file mode 100644 index 00000000..5fcebfff --- /dev/null +++ b/sop-example/sop-springmvc/src/main/java/com/gitee/app/model/StoryParam.java @@ -0,0 +1,23 @@ +package com.gitee.app.model; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.Max; +import javax.validation.constraints.NotBlank; + +@Data +public class StoryParam { + @ApiModelProperty(value = "故事ID", example = "111") + private int id; + + @NotBlank(message = "name不能为空") + @Length(max = 20, message = "name长度不能超过20") + @ApiModelProperty(value = "故事名称", required = true, example = "白雪公主", position = 3) + private String name; + + @ApiModelProperty(value = "备注 (第二)", example = "xx", position = 2) + @Length(max = 64, message = "长度不能超过64") + private String remark; +} \ No newline at end of file diff --git a/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1010_SamePathController.java b/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1010_SamePathController.java new file mode 100644 index 00000000..11c1fc8c --- /dev/null +++ b/sop-example/sop-story/src/main/java/com/gitee/sop/storyweb/controller/Example1010_SamePathController.java @@ -0,0 +1,22 @@ +package com.gitee.sop.storyweb.controller; + +import com.gitee.sop.servercommon.annotation.Open; +import com.gitee.sop.storyweb.controller.param.StoryParam; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 模拟超时设置 + * + * @author tanghc + */ +@RestController +public class Example1010_SamePathController { + + @Open("story.path.same") + @RequestMapping("iam_same_path") + public Object iam_same_path(StoryParam param) { + param.setName(param.getName() + " story.."); + return param; + } +} diff --git a/sop-test/src/test/java/com/gitee/sop/test/SamePathTest.java b/sop-test/src/test/java/com/gitee/sop/test/SamePathTest.java new file mode 100644 index 00000000..4dcde403 --- /dev/null +++ b/sop-test/src/test/java/com/gitee/sop/test/SamePathTest.java @@ -0,0 +1,96 @@ +package com.gitee.sop.test; + +import com.alibaba.fastjson.JSON; +import com.gitee.sop.test.alipay.AlipaySignature; +import org.junit.Assert; +import org.junit.Test; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 超时测试 + */ +public class SamePathTest extends TestBase { + + String url = "http://localhost:8081"; + String appId = "2019032617262200001"; + // 平台提供的私钥 + String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXJv1pQFqWNA/++OYEV7WYXwexZK/J8LY1OWlP9X0T6wHFOvxNKRvMkJ5544SbgsJpVcvRDPrcxmhPbi/sAhdO4x2PiPKIz9Yni2OtYCCeaiE056B+e1O2jXoLeXbfi9fPivJZkxH/tb4xfLkH3bA8ZAQnQsoXA0SguykMRZntF0TndUfvDrLqwhlR8r5iRdZLB6F8o8qXH6UPDfNEnf/K8wX5T4EB1b8x8QJ7Ua4GcIUqeUxGHdQpzNbJdaQvoi06lgccmL+PHzminkFYON7alj1CjDN833j7QMHdPtS9l7B67fOU/p2LAAkPMtoVBfxQt9aFj7B8rEhGCz02iJIBAgMBAAECggEARqOuIpY0v6WtJBfmR3lGIOOokLrhfJrGTLF8CiZMQha+SRJ7/wOLPlsH9SbjPlopyViTXCuYwbzn2tdABigkBHYXxpDV6CJZjzmRZ+FY3S/0POlTFElGojYUJ3CooWiVfyUMhdg5vSuOq0oCny53woFrf32zPHYGiKdvU5Djku1onbDU0Lw8w+5tguuEZ76kZ/lUcccGy5978FFmYpzY/65RHCpvLiLqYyWTtaNT1aQ/9pw4jX9HO9NfdJ9gYFK8r/2f36ZE4hxluAfeOXQfRC/WhPmiw/ReUhxPznG/WgKaa/OaRtAx3inbQ+JuCND7uuKeRe4osP2jLPHPP6AUwQKBgQDUNu3BkLoKaimjGOjCTAwtp71g1oo+k5/uEInAo7lyEwpV0EuUMwLA/HCqUgR4K9pyYV+Oyb8d6f0+Hz0BMD92I2pqlXrD7xV2WzDvyXM3s63NvorRooKcyfd9i6ccMjAyTR2qfLkxv0hlbBbsPHz4BbU63xhTJp3Ghi0/ey/1HQKBgQC2VsgqC6ykfSidZUNLmQZe3J0p/Qf9VLkfrQ+xaHapOs6AzDU2H2osuysqXTLJHsGfrwVaTs00ER2z8ljTJPBUtNtOLrwNRlvgdnzyVAKHfOgDBGwJgiwpeE9voB1oAV/mXqSaUWNnuwlOIhvQEBwekqNyWvhLqC7nCAIhj3yvNQKBgQCqYbeec56LAhWP903Zwcj9VvG7sESqXUhIkUqoOkuIBTWFFIm54QLTA1tJxDQGb98heoCIWf5x/A3xNI98RsqNBX5JON6qNWjb7/dobitti3t99v/ptDp9u8JTMC7penoryLKK0Ty3bkan95Kn9SC42YxaSghzqkt+uvfVQgiNGQKBgGxU6P2aDAt6VNwWosHSe+d2WWXt8IZBhO9d6dn0f7ORvcjmCqNKTNGgrkewMZEuVcliueJquR47IROdY8qmwqcBAN7Vg2K7r7CPlTKAWTRYMJxCT1Hi5gwJb+CZF3+IeYqsJk2NF2s0w5WJTE70k1BSvQsfIzAIDz2yE1oPHvwVAoGAA6e+xQkVH4fMEph55RJIZ5goI4Y76BSvt2N5OKZKd4HtaV+eIhM3SDsVYRLIm9ZquJHMiZQGyUGnsvrKL6AAVNK7eQZCRDk9KQz+0GKOGqku0nOZjUbAu6A2/vtXAaAuFSFx1rUQVVjFulLexkXR3KcztL1Qu2k5pB6Si0K/uwQ="; + + @Test + public void testGet() throws Exception { + + // 公共请求参数 + Map params = new HashMap(); + params.put("app_id", appId); + params.put("method", "story.path.same"); + params.put("format", "json"); + params.put("charset", "utf-8"); + params.put("sign_type", "RSA2"); + params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + params.put("version", "1.0"); + + // 业务参数 + Map bizContent = new HashMap<>(); + bizContent.put("id", "1"); + bizContent.put("name", "葫芦娃"); + + params.put("biz_content", JSON.toJSONString(bizContent)); + String content = AlipaySignature.getSignContent(params); + String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8"); + params.put("sign", sign); + + System.out.println("----------- 请求信息 -----------"); + System.out.println("请求参数:" + buildParamQuery(params)); + System.out.println("商户秘钥:" + privateKey); + System.out.println("待签名内容:" + content); + System.out.println("签名(sign):" + sign); + System.out.println("URL参数:" + buildUrlQuery(params)); + + System.out.println("----------- 返回结果 -----------"); + String responseData = get(url, params);// 发送请求 + System.out.println(responseData); + Assert.assertTrue(responseData.contains("葫芦娃 story..")); + } + + @Test + public void testGet2() throws Exception { + + // 公共请求参数 + Map params = new HashMap(); + params.put("app_id", appId); + params.put("method", "springmvc.path.same"); + params.put("format", "json"); + params.put("charset", "utf-8"); + params.put("sign_type", "RSA2"); + params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); + params.put("version", "1.0"); + + // 业务参数 + Map bizContent = new HashMap<>(); + bizContent.put("id", "1"); + bizContent.put("name", "葫芦娃"); + + params.put("biz_content", JSON.toJSONString(bizContent)); + String content = AlipaySignature.getSignContent(params); + String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8"); + params.put("sign", sign); + + System.out.println("----------- 请求信息 -----------"); + System.out.println("请求参数:" + buildParamQuery(params)); + System.out.println("商户秘钥:" + privateKey); + System.out.println("待签名内容:" + content); + System.out.println("签名(sign):" + sign); + System.out.println("URL参数:" + buildUrlQuery(params)); + + System.out.println("----------- 返回结果 -----------"); + String responseData = get(url, params);// 发送请求 + System.out.println(responseData); + Assert.assertTrue(responseData.contains("葫芦娃 mvc..")); + } + + +}