From ac69fff3a297d0ccb1b44d107b5c68a002ad3abb Mon Sep 17 00:00:00 2001 From: icodening Date: Wed, 30 Mar 2022 00:48:16 +0800 Subject: [PATCH 1/4] Spring WebFlux Adapter Support "BEST_MATCHING_PATTERN_ATTRIBUTE" --- .../sentinel-spring-webflux-adapter/pom.xml | 6 + .../spring/webflux/SentinelWebFluxFilter.java | 16 +- .../DefaultBestMatchingPatternExtractor.java | 60 ++++ ...erMappingBestMatchingPatternExtractor.java | 46 +++ ...erMappingBestMatchingPatternExtractor.java | 47 +++ .../support/RequestPredicateRegistrar.java | 51 ++++ ...rFunctionBestMatchingPatternExtractor.java | 62 ++++ ...ctionRequestPredicateRegistrarVisitor.java | 61 ++++ ...terFunctionRequestPredicateRepository.java | 44 +++ .../support/SentinelServerRequest.java | 284 ++++++++++++++++++ 10 files changed, 676 insertions(+), 1 deletion(-) create mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/DefaultBestMatchingPatternExtractor.java create mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/HandlerMappingBestMatchingPatternExtractor.java create mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestMappingHandlerMappingBestMatchingPatternExtractor.java create mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestPredicateRegistrar.java create mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java create mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionRequestPredicateRegistrarVisitor.java create mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionRequestPredicateRepository.java create mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/SentinelServerRequest.java diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/pom.xml b/sentinel-adapter/sentinel-spring-webflux-adapter/pom.xml index b653a50ca7..c40c86e483 100644 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/pom.xml +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/pom.xml @@ -33,6 +33,12 @@ ${spring.version} provided + + org.springframework + spring-context + ${spring.version} + provided + junit diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxFilter.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxFilter.java index f704f78b21..4142b6053e 100644 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxFilter.java +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/SentinelWebFluxFilter.java @@ -16,6 +16,7 @@ package com.alibaba.csp.sentinel.adapter.spring.webflux; import java.util.Optional; +import java.util.function.Function; import com.alibaba.csp.sentinel.EntryType; import com.alibaba.csp.sentinel.ResourceTypeConstants; @@ -38,11 +39,24 @@ public class SentinelWebFluxFilter implements WebFilter { public static final String SENTINEL_SPRING_WEBFLUX_CONTEXT_NAME = "sentinel_spring_webflux_context"; + private static final Function DEFAULT_EXTRACTOR = (exchange) -> null; + + private final Function bestMatchingPatternExtractor; + + public SentinelWebFluxFilter() { + this(DEFAULT_EXTRACTOR); + } + + public SentinelWebFluxFilter(Function bestMatchingPatternExtractor) { + this.bestMatchingPatternExtractor = bestMatchingPatternExtractor; + } + @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { // Maybe we can get the URL pattern elsewhere via: // exchange.getAttributeOrDefault(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE, path) - String path = exchange.getRequest().getPath().value(); + String bestMatchingPattern = bestMatchingPatternExtractor.apply(exchange); + String path = bestMatchingPattern != null ? bestMatchingPattern : exchange.getRequest().getPath().value(); String finalPath = WebFluxCallbackManager.getUrlCleaner().apply(exchange, path); if (StringUtil.isEmpty(finalPath)) { diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/DefaultBestMatchingPatternExtractor.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/DefaultBestMatchingPatternExtractor.java new file mode 100644 index 0000000000..2d986cd536 --- /dev/null +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/DefaultBestMatchingPatternExtractor.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.adapter.spring.webflux.support; + +import com.alibaba.csp.sentinel.util.AssertUtil; +import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.server.ServerWebExchange; + +import java.util.List; +import java.util.function.Function; + +/** + * default extractor for "BEST_MATCHING_HANDLER_ATTRIBUTE" + * + * @author icodening + * @date 2022.03.29 + */ +public class DefaultBestMatchingPatternExtractor implements Function { + + private final List handlerMappings; + + private final List handlerMappingBestMatchingPatternExtractors; + + public DefaultBestMatchingPatternExtractor(List handlerMappings, + List handlerMappingBestMatchingPatternExtractors) { + AssertUtil.notNull(handlerMappings, "handlerMappings cannot be null"); + AssertUtil.notNull(handlerMappingBestMatchingPatternExtractors, "handlerMappingBestMatchingPatternExtractors cannot be null"); + this.handlerMappings = handlerMappings; + this.handlerMappingBestMatchingPatternExtractors = handlerMappingBestMatchingPatternExtractors; + } + + @Override + public String apply(ServerWebExchange exchange) { + for (HandlerMapping handlerMapping : handlerMappings) { + for (HandlerMappingBestMatchingPatternExtractor handlerMappingBestMatchingPatternExtractor : handlerMappingBestMatchingPatternExtractors) { + if (!handlerMappingBestMatchingPatternExtractor.supportExtract(handlerMapping)) { + continue; + } + String bestMatchingPath = handlerMappingBestMatchingPatternExtractor.extract(handlerMapping, exchange); + if (bestMatchingPath != null) { + return bestMatchingPath; + } + } + } + return null; + } +} diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/HandlerMappingBestMatchingPatternExtractor.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/HandlerMappingBestMatchingPatternExtractor.java new file mode 100644 index 0000000000..9ef0be2225 --- /dev/null +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/HandlerMappingBestMatchingPatternExtractor.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.adapter.spring.webflux.support; + +import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.server.ServerWebExchange; + +/** + * "BEST_MATCHING_HANDLER_ATTRIBUTE" extractor + * + * @author icodening + * @date 2022.03.29 + * @see HandlerMapping#BEST_MATCHING_HANDLER_ATTRIBUTE + */ +public interface HandlerMappingBestMatchingPatternExtractor { + + /** + * whether to process the given HandlerMapping + * + * @param handlerMapping Spring HandlerMapping + * @return "true" is support extract + */ + boolean supportExtract(HandlerMapping handlerMapping); + + /** + * extract BEST_MATCHING_HANDLER_ATTRIBUTE for current given ServerWebExchange + * + * @param handlerMapping current HandlerMapping, eg. RouterFunctionMapping, RequestMappingHandlerMapping, SimpleUrlHandlerMapping + * @param exchange current request and response + * @return best matching pattern, return null when if not found , eg. /users/{id} + */ + String extract(HandlerMapping handlerMapping, ServerWebExchange exchange); +} diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestMappingHandlerMappingBestMatchingPatternExtractor.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestMappingHandlerMappingBestMatchingPatternExtractor.java new file mode 100644 index 0000000000..3eecfe0dc7 --- /dev/null +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestMappingHandlerMappingBestMatchingPatternExtractor.java @@ -0,0 +1,47 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.adapter.spring.webflux.support; + +import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.util.pattern.PathPattern; + +/** + * best matching pattern extractor for RequestMappingHandlerMapping + * + * @author icodening + * @date 2022.03.29 + * @see RequestMappingHandlerMapping + */ +public class RequestMappingHandlerMappingBestMatchingPatternExtractor implements HandlerMappingBestMatchingPatternExtractor { + + @Override + public String extract(HandlerMapping handlerMapping, ServerWebExchange exchange) { + RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) handlerMapping; + requestMappingHandlerMapping.getHandlerInternal(exchange); + Object attribute = exchange.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); + if (attribute instanceof PathPattern) { + return ((PathPattern) attribute).getPatternString(); + } + return null; + } + + @Override + public boolean supportExtract(HandlerMapping handlerMapping) { + return handlerMapping instanceof RequestMappingHandlerMapping; + } +} diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestPredicateRegistrar.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestPredicateRegistrar.java new file mode 100644 index 0000000000..f8fb85f857 --- /dev/null +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestPredicateRegistrar.java @@ -0,0 +1,51 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.adapter.spring.webflux.support; + +import com.alibaba.csp.sentinel.util.AssertUtil; +import org.springframework.beans.factory.SmartInitializingSingleton; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.support.RouterFunctionMapping; + +/** + * RequestPredicate registrar for RouterFunction, existing RouterFunction can be record + * + * @author icodening + * @date 2022.03.29 + */ +public class RequestPredicateRegistrar implements SmartInitializingSingleton { + + private final RouterFunctionRequestPredicateRepository routerFunctionRequestPredicateRepository = new RouterFunctionRequestPredicateRepository(); + + private final RouterFunctionMapping routerFunctionMapping; + + public RequestPredicateRegistrar(RouterFunctionMapping routerFunctionMapping) { + AssertUtil.notNull(routerFunctionMapping, "routerFunctionMapping cannot be null"); + this.routerFunctionMapping = routerFunctionMapping; + } + + @Override + public void afterSingletonsInstantiated() { + RouterFunction routerFunction = this.routerFunctionMapping.getRouterFunction(); + if (routerFunction != null) { + routerFunction.accept(new RouterFunctionRequestPredicateRegistrarVisitor(routerFunctionRequestPredicateRepository)); + } + } + + public RouterFunctionRequestPredicateRepository getRouterFunctionRequestPredicateRepository() { + return routerFunctionRequestPredicateRepository; + } +} diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java new file mode 100644 index 0000000000..ad277ae777 --- /dev/null +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.adapter.spring.webflux.support; + +import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.reactive.function.server.RequestPredicate; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.support.RouterFunctionMapping; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.util.pattern.PathPattern; + +import java.util.List; + +/** + * best matching pattern extractor for RouterFunctionMapping + * + * @author icodening + * @date 2022.03.29 + * @see RouterFunctionMapping + */ +public class RouterFunctionBestMatchingPatternExtractor implements HandlerMappingBestMatchingPatternExtractor { + + private final RouterFunctionRequestPredicateRepository routerFunctionRequestPredicateRepository; + + public RouterFunctionBestMatchingPatternExtractor(RouterFunctionRequestPredicateRepository routerFunctionRequestPredicateRepository) { + this.routerFunctionRequestPredicateRepository = routerFunctionRequestPredicateRepository; + } + + @Override + public boolean supportExtract(HandlerMapping handlerMapping) { + return handlerMapping instanceof RouterFunctionMapping; + } + + @Override + public String extract(HandlerMapping handlerMapping, ServerWebExchange exchange) { + SentinelServerRequest sentinelServerRequest = new SentinelServerRequest(exchange); + List requestPredicates = routerFunctionRequestPredicateRepository.getRequestPredicates(); + for (RequestPredicate requestPredicate : requestPredicates) { + if (requestPredicate.test(sentinelServerRequest)) { + Object attribute = exchange.getAttribute(RouterFunctions.MATCHING_PATTERN_ATTRIBUTE); + if (attribute instanceof PathPattern) { + exchange.getAttributes().remove(RouterFunctions.MATCHING_PATTERN_ATTRIBUTE); + return ((PathPattern) attribute).getPatternString(); + } + } + } + return null; + } +} diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionRequestPredicateRegistrarVisitor.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionRequestPredicateRegistrarVisitor.java new file mode 100644 index 0000000000..5eaef7e677 --- /dev/null +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionRequestPredicateRegistrarVisitor.java @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.adapter.spring.webflux.support; + +import org.springframework.core.io.Resource; +import org.springframework.web.reactive.function.server.*; +import reactor.core.publisher.Mono; + +import java.util.function.Function; + +/** + * @author icodening + * @date 2022.03.29 + */ +class RouterFunctionRequestPredicateRegistrarVisitor implements RouterFunctions.Visitor { + + private final RouterFunctionRequestPredicateRepository routerFunctionRequestPredicateRepository; + + RouterFunctionRequestPredicateRegistrarVisitor(RouterFunctionRequestPredicateRepository routerFunctionRequestPredicateRepository) { + this.routerFunctionRequestPredicateRepository = routerFunctionRequestPredicateRepository; + } + + @Override + public void startNested(RequestPredicate predicate) { + //ignore + } + + @Override + public void endNested(RequestPredicate predicate) { + //ignore + } + + @Override + public void route(RequestPredicate predicate, HandlerFunction handlerFunction) { + //cache the predicate + this.routerFunctionRequestPredicateRepository.addRequestPredicate(predicate); + } + + @Override + public void resources(Function> lookupFunction) { + //ignore + } + + @Override + public void unknown(RouterFunction routerFunction) { + //ignore + } +} diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionRequestPredicateRepository.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionRequestPredicateRepository.java new file mode 100644 index 0000000000..39c6d17a32 --- /dev/null +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionRequestPredicateRepository.java @@ -0,0 +1,44 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.adapter.spring.webflux.support; + +import org.springframework.web.reactive.function.server.RequestPredicate; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * RequestPredicate cache for RouterFunction + * + * @author icodening + * @date 2022.03.29 + */ +public class RouterFunctionRequestPredicateRepository { + + private final List requestPredicates = Collections.synchronizedList(new ArrayList<>()); + + public RouterFunctionRequestPredicateRepository() { + } + + public void addRequestPredicate(RequestPredicate requestPredicate) { + this.requestPredicates.add(requestPredicate); + } + + public List getRequestPredicates() { + return requestPredicates; + } +} diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/SentinelServerRequest.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/SentinelServerRequest.java new file mode 100644 index 0000000000..91e88ced05 --- /dev/null +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/SentinelServerRequest.java @@ -0,0 +1,284 @@ +package com.alibaba.csp.sentinel.adapter.spring.webflux.support; + +import com.alibaba.csp.sentinel.util.AssertUtil; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.*; +import org.springframework.http.codec.HttpMessageReader; +import org.springframework.http.codec.multipart.Part; +import org.springframework.http.server.PathContainer; +import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.BodyExtractor; +import org.springframework.web.reactive.function.BodyExtractors; +import org.springframework.web.reactive.function.UnsupportedMediaTypeException; +import org.springframework.web.reactive.function.server.HandlerStrategies; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.UnsupportedMediaTypeStatusException; +import org.springframework.web.server.WebSession; +import org.springframework.web.util.UriBuilder; +import org.springframework.web.util.UriComponentsBuilder; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.charset.Charset; +import java.security.Principal; +import java.util.*; +import java.util.function.Function; + +/** + * wrap ServerWebExchange as ServerRequest + * + * @author icodening + * @date 2022.03.29 + */ +public class SentinelServerRequest implements ServerRequest { + + private static final Function ERROR_MAPPER = ex -> (ex + .getContentType() != null + ? new UnsupportedMediaTypeStatusException(ex.getContentType(), + ex.getSupportedMediaTypes()) + : new UnsupportedMediaTypeStatusException(ex.getMessage())); + + private final ServerWebExchange exchange; + + private final Headers headers; + + private final List> messageReaders; + + public SentinelServerRequest(ServerWebExchange exchange) { + this(exchange, HandlerStrategies.withDefaults().messageReaders()); + } + + public SentinelServerRequest(ServerWebExchange exchange, + List> messageReaders) { + AssertUtil.notNull(exchange, "exchange cannot be null"); + AssertUtil.notNull(messageReaders, "messageReaders cannot be null"); + this.exchange = exchange; + this.messageReaders = Collections + .unmodifiableList(new ArrayList<>(messageReaders)); + this.headers = new DefaultHeaders(); + } + + @Override + public String methodName() { + return request().getMethodValue(); + } + + @Override + public URI uri() { + return request().getURI(); + } + + @Override + public UriBuilder uriBuilder() { + return UriComponentsBuilder.fromHttpRequest(new ServerRequestAdapter()); + } + + @Override + public PathContainer pathContainer() { + return request().getPath(); + } + + @Override + public Headers headers() { + return this.headers; + } + + @Override + public MultiValueMap cookies() { + return request().getCookies(); + } + + @Override + public T body(BodyExtractor extractor) { + return body(extractor, Collections.emptyMap()); + } + + @Override + public Optional remoteAddress() { + return Optional.of(request().getRemoteAddress()); + } + + @Override + public List> messageReaders() { + return this.messageReaders; + } + + @Override + public T body(BodyExtractor extractor, + Map hints) { + return extractor.extract(request(), new BodyExtractor.Context() { + @Override + public List> messageReaders() { + return messageReaders; + } + + @Override + public Optional serverResponse() { + return Optional.of(exchange().getResponse()); + } + + @Override + public Map hints() { + return hints; + } + }); + } + + @Override + public Mono bodyToMono(Class elementClass) { + Mono mono = body(BodyExtractors.toMono(elementClass)); + return mono.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER); + } + + @Override + public Mono bodyToMono(ParameterizedTypeReference typeReference) { + Mono mono = body(BodyExtractors.toMono(typeReference)); + return mono.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER); + } + + @Override + public Flux bodyToFlux(Class elementClass) { + Flux flux = body(BodyExtractors.toFlux(elementClass)); + return flux.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER); + } + + @Override + public Flux bodyToFlux(ParameterizedTypeReference typeReference) { + Flux flux = body(BodyExtractors.toFlux(typeReference)); + return flux.onErrorMap(UnsupportedMediaTypeException.class, ERROR_MAPPER); + } + + @Override + public Map attributes() { + return this.exchange.getAttributes(); + } + + @Override + public MultiValueMap queryParams() { + return request().getQueryParams(); + } + + @Override + public Map pathVariables() { + return this.exchange.getAttributeOrDefault( + RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, Collections.emptyMap()); + } + + @Override + public Mono session() { + return this.exchange.getSession(); + } + + @Override + public Mono principal() { + return this.exchange.getPrincipal(); + } + + @Override + public Mono> formData() { + return this.exchange.getFormData(); + } + + @Override + public Mono> multipartData() { + return this.exchange.getMultipartData(); + } + + private ServerHttpRequest request() { + return this.exchange.getRequest(); + } + + public ServerWebExchange exchange() { + return this.exchange; + } + + @Override + public String toString() { + return String.format("%s %s", method(), path()); + } + + private class DefaultHeaders implements Headers { + + private HttpHeaders delegate() { + return request().getHeaders(); + } + + @Override + public List accept() { + return delegate().getAccept(); + } + + @Override + public List acceptCharset() { + return delegate().getAcceptCharset(); + } + + @Override + public List acceptLanguage() { + return delegate().getAcceptLanguage(); + } + + @Override + public OptionalLong contentLength() { + long value = delegate().getContentLength(); + return (value != -1 ? OptionalLong.of(value) : OptionalLong.empty()); + } + + @Override + public Optional contentType() { + return Optional.ofNullable(delegate().getContentType()); + } + + @Override + public InetSocketAddress host() { + return delegate().getHost(); + } + + @Override + public List range() { + return delegate().getRange(); + } + + @Override + public List header(String headerName) { + List headerValues = delegate().get(headerName); + return (headerValues != null ? headerValues : Collections.emptyList()); + } + + @Override + public HttpHeaders asHttpHeaders() { + return HttpHeaders.readOnlyHttpHeaders(delegate()); + } + + @Override + public String toString() { + return delegate().toString(); + } + + } + + private final class ServerRequestAdapter implements HttpRequest { + + @Override + public String getMethodValue() { + return methodName(); + } + + @Override + public URI getURI() { + return uri(); + } + + @Override + public HttpHeaders getHeaders() { + return request().getHeaders(); + } + + } +} From 172b899373c4de34ade32856e87279ff134871a7 Mon Sep 17 00:00:00 2001 From: icodening Date: Wed, 30 Mar 2022 23:10:32 +0800 Subject: [PATCH 2/4] add test case --- .../match/BestMatchingPatternExtractTest.java | 220 ++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/match/BestMatchingPatternExtractTest.java diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/match/BestMatchingPatternExtractTest.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/match/BestMatchingPatternExtractTest.java new file mode 100644 index 0000000000..1b11dbbca5 --- /dev/null +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/match/BestMatchingPatternExtractTest.java @@ -0,0 +1,220 @@ +/* + * Copyright 1999-2022 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.adapter.spring.webflux.match; + +import com.alibaba.csp.sentinel.adapter.spring.webflux.support.*; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.codec.ServerCodecConfigurer; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.http.server.reactive.MockServerHttpResponse; +import org.springframework.util.ReflectionUtils; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.reactive.HandlerMapping; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.server.HandlerFunction; +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 org.springframework.web.reactive.function.server.support.RouterFunctionMapping; +import org.springframework.web.reactive.result.method.RequestMappingInfo; +import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.adapter.DefaultServerWebExchange; +import org.springframework.web.server.i18n.AcceptHeaderLocaleContextResolver; +import org.springframework.web.server.i18n.LocaleContextResolver; +import org.springframework.web.server.session.DefaultWebSessionManager; +import org.springframework.web.server.session.WebSessionManager; + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +/** + * @author icodening + * @date 2022.03.30 + */ +public class BestMatchingPatternExtractTest { + + /** + * some request path + */ + private static final String BASE_PATH = "/users"; + private static final String PATH_123 = BASE_PATH + "/123"; + private static final String PATH_456 = BASE_PATH + "/456"; + + + /** + * some "HandlerMapping" + */ + private RequestMappingHandlerMapping requestMappingHandlerMapping; + private RouterFunctionMapping routerFunctionMapping; + + + /** + * some base constructor params for DefaultServerWebExchange + */ + private final WebSessionManager defaultWebSessionManager = new DefaultWebSessionManager(); + private final ServerCodecConfigurer serverCodecConfigurer = ServerCodecConfigurer.create(); + private final LocaleContextResolver acceptHeaderLocaleContextResolver = new AcceptHeaderLocaleContextResolver(); + + + /** + * some ServerWebExchange, can be verify HandlerMappingBestMatchingPatternExtractor + */ + private ServerWebExchange getUserByIdExchange1; + private ServerWebExchange getUserByIdExchange2; + private ServerWebExchange postGetUserByIdExchange2; + + + @Before + public void setup() throws Exception { + initRequestMappingHandlerMapping(); + initRouterFunctionMapping(); + buildMockServerWebExchange(); + } + + @Test + public void testBestMatchingByRequestMappingHandlerMapping() { + //1.get HandlerMappingBestMatchingPatternExtractor instance + HandlerMappingBestMatchingPatternExtractor handlerMappingBestMatchingPatternExtractor = getRequestMappingHandlerMappingBestMatchingExtractor(); + //2.extract HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE + String bestMatchingPattern1 = handlerMappingBestMatchingPatternExtractor.extract(requestMappingHandlerMapping, getUserByIdExchange1); + String bestMatchingPattern2 = handlerMappingBestMatchingPatternExtractor.extract(requestMappingHandlerMapping, getUserByIdExchange2); + String bestMatchingPattern3 = handlerMappingBestMatchingPatternExtractor.extract(requestMappingHandlerMapping, postGetUserByIdExchange2); + System.out.println("bestMatchingPattern1 = " + bestMatchingPattern1); + System.out.println("bestMatchingPattern2 = " + bestMatchingPattern2); + System.out.println("bestMatchingPattern3 = " + bestMatchingPattern3); + //3.assert + assertEquals("/users/{id}", bestMatchingPattern1); + assertEquals("/users/{id}", bestMatchingPattern2); + assertNotEquals("/users/{id}", bestMatchingPattern3); + assertEquals(bestMatchingPattern1, bestMatchingPattern2); + } + + @Test + public void testBestMatchingByRouterFunctionMapping() { + //1.get HandlerMappingBestMatchingPatternExtractor instance + HandlerMappingBestMatchingPatternExtractor handlerMappingBestMatchingPatternExtractor = getRouterFunctionBestMatchingPatternExtractor(); + //2.extract HandlerMapping.BEST_MATCHING_HANDLER_ATTRIBUTE + String bestMatchingPattern1 = handlerMappingBestMatchingPatternExtractor.extract(routerFunctionMapping, getUserByIdExchange1); + String bestMatchingPattern2 = handlerMappingBestMatchingPatternExtractor.extract(routerFunctionMapping, getUserByIdExchange2); + String bestMatchingPattern3 = handlerMappingBestMatchingPatternExtractor.extract(routerFunctionMapping, postGetUserByIdExchange2); + System.out.println("bestMatchingPattern1 = " + bestMatchingPattern1); + System.out.println("bestMatchingPattern2 = " + bestMatchingPattern2); + System.out.println("bestMatchingPattern3 = " + bestMatchingPattern3); + //3.assert + assertEquals("/users/{id}", bestMatchingPattern1); + assertEquals("/users/{id}", bestMatchingPattern2); + assertNotEquals("/users/{id}", bestMatchingPattern3); + assertEquals(bestMatchingPattern1, bestMatchingPattern2); + } + + @Test + public void testInvokeHandler() { + ServerWebExchange selectedServerWebExchange = getUserByIdExchange2; + + //test invoke with RequestMappingHandlerMapping + requestMappingHandlerMapping.getHandler(selectedServerWebExchange) + .filter(HandlerMethod.class::isInstance) + .doOnNext(handler -> { + Map pathVariables = selectedServerWebExchange.getAttributeOrDefault( + HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, Collections.emptyMap()); + Method method = ((HandlerMethod) handler).getMethod(); + method.setAccessible(true); + ReflectionUtils.invokeMethod(method, ((HandlerMethod) handler).getBean(), Long.valueOf(pathVariables.get("id"))); + }) + .subscribe(); + + //test invoke with RouterFunctionMapping + routerFunctionMapping.getHandler(selectedServerWebExchange) + .filter(HandlerFunction.class::isInstance) + .doOnNext(handler -> ((HandlerFunction) handler).handle(new SentinelServerRequest(selectedServerWebExchange))) + .subscribe(); + } + + private void initRequestMappingHandlerMapping() throws Exception { + requestMappingHandlerMapping = new RequestMappingHandlerMapping(); + UserController userController = new UserController(); + Method getUserById = UserController.class.getDeclaredMethod("getUserById", Long.class); + requestMappingHandlerMapping.registerMapping(RequestMappingInfo.paths(BASE_PATH + "/{id}").methods(RequestMethod.GET).build(), + userController, + getUserById); + } + + private void initRouterFunctionMapping() { + RouterFunction routerFunction = RouterFunctions.route() + .GET(BASE_PATH + "/{id}", serverRequest -> { + String id = serverRequest.pathVariable("id"); + String ret = "user id = " + id + ", from RouterFunction"; + System.out.println(ret); + return ServerResponse.ok().body(BodyInserters.fromObject(ret)); + }) + .build(); + routerFunctionMapping = new RouterFunctionMapping(routerFunction); + } + + private void buildMockServerWebExchange() { + //GET /users/123 + getUserByIdExchange1 = new DefaultServerWebExchange(MockServerHttpRequest.get(PATH_123).build(), + new MockServerHttpResponse(), + defaultWebSessionManager, + serverCodecConfigurer, + acceptHeaderLocaleContextResolver); + + //GET /users/456 + getUserByIdExchange2 = new DefaultServerWebExchange(MockServerHttpRequest.get(PATH_456).build(), + new MockServerHttpResponse(), + defaultWebSessionManager, + serverCodecConfigurer, + acceptHeaderLocaleContextResolver); + + //POST /users/456 + postGetUserByIdExchange2 = new DefaultServerWebExchange(MockServerHttpRequest.post(PATH_456).build(), + new MockServerHttpResponse(), + defaultWebSessionManager, + serverCodecConfigurer, + acceptHeaderLocaleContextResolver); + } + + + private HandlerMappingBestMatchingPatternExtractor getRequestMappingHandlerMappingBestMatchingExtractor() { + return new RequestMappingHandlerMappingBestMatchingPatternExtractor(); + } + + private HandlerMappingBestMatchingPatternExtractor getRouterFunctionBestMatchingPatternExtractor() { + RequestPredicateRegistrar requestPredicateRegistrar = new RequestPredicateRegistrar(routerFunctionMapping); + requestPredicateRegistrar.afterSingletonsInstantiated(); + return new RouterFunctionBestMatchingPatternExtractor(requestPredicateRegistrar.getRouterFunctionRequestPredicateRepository()); + } + + /** + * mock controller + */ + private static class UserController { + + public String getUserById(@PathVariable Long id) { + String ret = "user id = " + id + ", from RequestMappingHandlerMapping"; + System.out.println(ret); + return ret; + } + } +} From 1be17256bf3f3cddacfea4b9a9273270aed6cef1 Mon Sep 17 00:00:00 2001 From: icodening Date: Thu, 31 Mar 2022 21:59:23 +0800 Subject: [PATCH 3/4] modify RouterFunctionBestMatchingPatternExtractor to optimize usage --- .../support/RequestPredicateRegistrar.java | 51 ------------------- ...rFunctionBestMatchingPatternExtractor.java | 31 ++++++++--- .../BestMatchingPatternExtractTest.java | 6 +-- 3 files changed, 27 insertions(+), 61 deletions(-) delete mode 100644 sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestPredicateRegistrar.java rename sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/{match => test}/BestMatchingPatternExtractTest.java (96%) diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestPredicateRegistrar.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestPredicateRegistrar.java deleted file mode 100644 index f8fb85f857..0000000000 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RequestPredicateRegistrar.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 1999-2022 Alibaba Group Holding Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.alibaba.csp.sentinel.adapter.spring.webflux.support; - -import com.alibaba.csp.sentinel.util.AssertUtil; -import org.springframework.beans.factory.SmartInitializingSingleton; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.support.RouterFunctionMapping; - -/** - * RequestPredicate registrar for RouterFunction, existing RouterFunction can be record - * - * @author icodening - * @date 2022.03.29 - */ -public class RequestPredicateRegistrar implements SmartInitializingSingleton { - - private final RouterFunctionRequestPredicateRepository routerFunctionRequestPredicateRepository = new RouterFunctionRequestPredicateRepository(); - - private final RouterFunctionMapping routerFunctionMapping; - - public RequestPredicateRegistrar(RouterFunctionMapping routerFunctionMapping) { - AssertUtil.notNull(routerFunctionMapping, "routerFunctionMapping cannot be null"); - this.routerFunctionMapping = routerFunctionMapping; - } - - @Override - public void afterSingletonsInstantiated() { - RouterFunction routerFunction = this.routerFunctionMapping.getRouterFunction(); - if (routerFunction != null) { - routerFunction.accept(new RouterFunctionRequestPredicateRegistrarVisitor(routerFunctionRequestPredicateRepository)); - } - } - - public RouterFunctionRequestPredicateRepository getRouterFunctionRequestPredicateRepository() { - return routerFunctionRequestPredicateRepository; - } -} diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java index ad277ae777..8c9ebec667 100644 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java @@ -17,11 +17,13 @@ import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.reactive.function.server.RequestPredicate; +import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.support.RouterFunctionMapping; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.pattern.PathPattern; +import java.util.Collections; import java.util.List; /** @@ -33,22 +35,26 @@ */ public class RouterFunctionBestMatchingPatternExtractor implements HandlerMappingBestMatchingPatternExtractor { - private final RouterFunctionRequestPredicateRepository routerFunctionRequestPredicateRepository; + private List registeredRequestPredicates = Collections.emptyList(); - public RouterFunctionBestMatchingPatternExtractor(RouterFunctionRequestPredicateRepository routerFunctionRequestPredicateRepository) { - this.routerFunctionRequestPredicateRepository = routerFunctionRequestPredicateRepository; - } + private volatile boolean initialized = false; @Override public boolean supportExtract(HandlerMapping handlerMapping) { return handlerMapping instanceof RouterFunctionMapping; } + public void setRegisteredRequestPredicates(List registeredRequestPredicates) { + if (registeredRequestPredicates != null) { + this.registeredRequestPredicates = registeredRequestPredicates; + } + } + @Override public String extract(HandlerMapping handlerMapping, ServerWebExchange exchange) { + initRequestPredicatesIfNecessary(handlerMapping); SentinelServerRequest sentinelServerRequest = new SentinelServerRequest(exchange); - List requestPredicates = routerFunctionRequestPredicateRepository.getRequestPredicates(); - for (RequestPredicate requestPredicate : requestPredicates) { + for (RequestPredicate requestPredicate : registeredRequestPredicates) { if (requestPredicate.test(sentinelServerRequest)) { Object attribute = exchange.getAttribute(RouterFunctions.MATCHING_PATTERN_ATTRIBUTE); if (attribute instanceof PathPattern) { @@ -59,4 +65,17 @@ public String extract(HandlerMapping handlerMapping, ServerWebExchange exchange) } return null; } + + private void initRequestPredicatesIfNecessary(HandlerMapping handlerMapping){ + if (!this.initialized) { + RouterFunctionMapping routerFunctionMapping = (RouterFunctionMapping) handlerMapping; + RouterFunction routerFunction = routerFunctionMapping.getRouterFunction(); + RouterFunctionRequestPredicateRepository routerFunctionRequestPredicateRepository = new RouterFunctionRequestPredicateRepository(); + if (routerFunction != null) { + routerFunction.accept(new RouterFunctionRequestPredicateRegistrarVisitor(routerFunctionRequestPredicateRepository)); + } + setRegisteredRequestPredicates(routerFunctionRequestPredicateRepository.getRequestPredicates()); + this.initialized = true; + } + } } diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/match/BestMatchingPatternExtractTest.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/test/BestMatchingPatternExtractTest.java similarity index 96% rename from sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/match/BestMatchingPatternExtractTest.java rename to sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/test/BestMatchingPatternExtractTest.java index 1b11dbbca5..9c750750eb 100644 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/match/BestMatchingPatternExtractTest.java +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/test/BestMatchingPatternExtractTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.csp.sentinel.adapter.spring.webflux.match; +package com.alibaba.csp.sentinel.adapter.spring.webflux.test; import com.alibaba.csp.sentinel.adapter.spring.webflux.support.*; import org.junit.Before; @@ -201,9 +201,7 @@ private HandlerMappingBestMatchingPatternExtractor getRequestMappingHandlerMappi } private HandlerMappingBestMatchingPatternExtractor getRouterFunctionBestMatchingPatternExtractor() { - RequestPredicateRegistrar requestPredicateRegistrar = new RequestPredicateRegistrar(routerFunctionMapping); - requestPredicateRegistrar.afterSingletonsInstantiated(); - return new RouterFunctionBestMatchingPatternExtractor(requestPredicateRegistrar.getRouterFunctionRequestPredicateRepository()); + return new RouterFunctionBestMatchingPatternExtractor(); } /** From 35976d97b715997921cf4fd9b52d0ae0a6efd3b2 Mon Sep 17 00:00:00 2001 From: icodening Date: Thu, 31 Mar 2022 22:04:07 +0800 Subject: [PATCH 4/4] modify class name RouterFunctionMappingBestMatchingPatternExtractor --- ...a => RouterFunctionMappingBestMatchingPatternExtractor.java} | 2 +- .../spring/webflux/test/BestMatchingPatternExtractTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/{RouterFunctionBestMatchingPatternExtractor.java => RouterFunctionMappingBestMatchingPatternExtractor.java} (96%) diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionMappingBestMatchingPatternExtractor.java similarity index 96% rename from sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java rename to sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionMappingBestMatchingPatternExtractor.java index 8c9ebec667..668f8f6f75 100644 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionBestMatchingPatternExtractor.java +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/spring/webflux/support/RouterFunctionMappingBestMatchingPatternExtractor.java @@ -33,7 +33,7 @@ * @date 2022.03.29 * @see RouterFunctionMapping */ -public class RouterFunctionBestMatchingPatternExtractor implements HandlerMappingBestMatchingPatternExtractor { +public class RouterFunctionMappingBestMatchingPatternExtractor implements HandlerMappingBestMatchingPatternExtractor { private List registeredRequestPredicates = Collections.emptyList(); diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/test/BestMatchingPatternExtractTest.java b/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/test/BestMatchingPatternExtractTest.java index 9c750750eb..b100527f2d 100644 --- a/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/test/BestMatchingPatternExtractTest.java +++ b/sentinel-adapter/sentinel-spring-webflux-adapter/src/test/java/com/alibaba/csp/sentinel/adapter/spring/webflux/test/BestMatchingPatternExtractTest.java @@ -201,7 +201,7 @@ private HandlerMappingBestMatchingPatternExtractor getRequestMappingHandlerMappi } private HandlerMappingBestMatchingPatternExtractor getRouterFunctionBestMatchingPatternExtractor() { - return new RouterFunctionBestMatchingPatternExtractor(); + return new RouterFunctionMappingBestMatchingPatternExtractor(); } /**