diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java index f606ebd5..d4c7856c 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/bean/SopConstants.java @@ -20,6 +20,8 @@ public class SopConstants { public static final String REDIRECT_VERSION_KEY = "r-version"; + public static final String REDIRECT_PATH_KEY = "r-path"; + /** * 在拦截器中调用获取参数: * String cachedBody = (String)exchange.getAttribute(SopConstants.CACHE_REQUEST_BODY_OBJECT_KEY); diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LoadBalancerClientExtFilter.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LoadBalancerClientExtFilter.java index cb447ba0..8cd9ad21 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LoadBalancerClientExtFilter.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/filter/LoadBalancerClientExtFilter.java @@ -1,5 +1,6 @@ package com.gitee.sop.gatewaycommon.gateway.filter; +import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.util.RouteUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilterChain; @@ -33,7 +34,7 @@ public class LoadBalancerClientExtFilter implements GlobalFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR); - String path = this.findPath(route); + String path = this.findPath(exchange, route); if (StringUtils.hasLength(path)) { URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR); UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromUri(url); @@ -44,7 +45,11 @@ public class LoadBalancerClientExtFilter implements GlobalFilter, Ordered { return chain.filter(exchange); } - protected String findPath(Route route) { + protected String findPath(ServerWebExchange exchange, Route route) { + String path = exchange.getAttribute(SopConstants.REDIRECT_PATH_KEY); + if (path != null) { + return path; + } URI routeUri = route.getUri(); String uriStr = routeUri.toString(); return RouteUtil.findPath(uriStr); 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 522cd8f7..2a54578c 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 @@ -5,15 +5,13 @@ import com.gitee.sop.gatewaycommon.bean.TargetRoute; import com.gitee.sop.gatewaycommon.manager.RouteRepository; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.springframework.cloud.gateway.event.PredicateArgsEvent; import org.springframework.cloud.gateway.route.RouteDefinitionRepository; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.util.Collection; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -29,6 +27,8 @@ import static java.util.Collections.synchronizedMap; @Slf4j public class GatewayRouteRepository implements RouteDefinitionRepository, RouteRepository { + private PathMatcher pathMatcher = new AntPathMatcher(); + private final Map routes = synchronizedMap(new LinkedHashMap<>()); @Override @@ -57,9 +57,21 @@ public class GatewayRouteRepository implements RouteDefinitionRepository, RouteR if (id == null) { return null; } - return routes.get(id); + GatewayTargetRoute gatewayTargetRoute = routes.get(id); + if (gatewayTargetRoute != null) { + return gatewayTargetRoute; + } + for (Map.Entry entry : routes.entrySet()) { + // /food/get/?id? + String pattern = entry.getKey(); + if (StringUtils.containsAny(pattern, "{") && this.pathMatcher.match(pattern, id)) { + return entry.getValue(); + } + } + return null; } + @Override public Collection getAll() { return routes.values(); diff --git a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java index bd0f9b0c..a3a61203 100644 --- a/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java +++ b/sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/gateway/route/NameVersionRoutePredicateFactory.java @@ -1,10 +1,13 @@ package com.gitee.sop.gatewaycommon.gateway.route; +import com.gitee.sop.gatewaycommon.bean.SopConstants; import com.gitee.sop.gatewaycommon.gateway.ServerWebExchangeUtil; import com.gitee.sop.gatewaycommon.param.ParamNames; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; +import org.springframework.util.AntPathMatcher; import org.springframework.util.CollectionUtils; +import org.springframework.util.PathMatcher; import org.springframework.validation.annotation.Validated; import org.springframework.web.server.ServerWebExchange; @@ -28,6 +31,8 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact private static final String PARAM_KEY = "param"; private static final String REGEXP_KEY = "regexp"; + private PathMatcher pathMatcher = new AntPathMatcher(); + public NameVersionRoutePredicateFactory() { super(Config.class); } @@ -57,7 +62,18 @@ public class NameVersionRoutePredicateFactory extends AbstractRoutePredicateFact if (name == null || version == null) { return false; } - return (name.toString() + version).equals(nameVersion); + String key = name.toString() + version.toString(); + // 如果是通配符 + if (nameVersion.contains("{")) { + boolean match = pathMatcher.match(nameVersion, key); + if (match) { + Map attributes = exchange.getAttributes(); + attributes.put(SopConstants.REDIRECT_PATH_KEY, key); + } + return match; + } else { + return key.equals(nameVersion); + } }; } diff --git a/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RestWebFlux.java b/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RestWebFlux.java new file mode 100644 index 00000000..b6854f29 --- /dev/null +++ b/sop-gateway/src/main/java/com/gitee/sop/gateway/controller/RestWebFlux.java @@ -0,0 +1,52 @@ +package com.gitee.sop.gateway.controller; + +import com.gitee.sop.gatewaycommon.param.ParamNames; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.server.RequestPredicates; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; + +import java.net.URI; + +/** + * @author tanghc + */ +@Configuration +public class RestWebFlux { + + @Value("${sop.restful.path:/rest}") + private String restPath; + + /** + * 307 Temporary Redirect(临时重定向): + *

+ * 在这种情况下,请求应该与另一个URI重复,但后续的请求应仍使用原始的URI。 + * 与302相反,当重新发出原始请求时,不允许更改请求方法。 例如,应该使用另一个POST请求来重复POST请求 + *

+ * 308 Permanent Redirect (永久重定向): + *

+ * 请求和所有将来的请求应该使用另一个URI重复。 + * 307和308重复302和301的行为,但不允许HTTP方法更改。 例如,将表单提交给永久重定向的资源可能会顺利进行。 + *

+ * https://www.cnblogs.com/wuguanglin/p/redirect.html + * + * @return + */ + @Bean + RouterFunction routerFunction() { + return RouterFunctions.route(RequestPredicates.GET(restPath + "/**"), (serverRequest) -> { + String url = serverRequest.path(); + int index = url.indexOf(restPath); + // 取/rest的后面部分 + String path = url.substring(index + restPath.length()); + String query = ParamNames.API_NAME + "=" + path + "&" + ParamNames.VERSION_NAME + "="; + return ServerResponse + .temporaryRedirect(URI.create("/?" + query)) + .build(); + }); + } + +}