diff --git a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java index 584bb9ca593..1065939b41f 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/reactive/MessageMappingMessageHandler.java @@ -88,6 +88,7 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler AnnotatedElementUtils.hasAnnotation(type, Controller.class)); } @@ -150,7 +148,9 @@ public class MessageMappingMessageHandler extends AbstractMethodMessageHandler> decoders; - private final ReactiveAdapterRegistry adapterRegistry; + private final RouteMatcher routeMatcher; + + private final MetadataExtractor metadataExtractor; private final DataBufferFactory bufferFactory; + private final ReactiveAdapterRegistry adapterRegistry; + private DefaultRSocketStrategies(List> encoders, List> decoders, - ReactiveAdapterRegistry adapterRegistry, DataBufferFactory bufferFactory) { + RouteMatcher routeMatcher, MetadataExtractor metadataExtractor, + DataBufferFactory bufferFactory, ReactiveAdapterRegistry adapterRegistry) { this.encoders = Collections.unmodifiableList(encoders); this.decoders = Collections.unmodifiableList(decoders); - this.adapterRegistry = adapterRegistry; + this.routeMatcher = routeMatcher; + this.metadataExtractor = metadataExtractor; this.bufferFactory = bufferFactory; + this.adapterRegistry = adapterRegistry; } @@ -78,8 +89,13 @@ final class DefaultRSocketStrategies implements RSocketStrategies { } @Override - public ReactiveAdapterRegistry reactiveAdapterRegistry() { - return this.adapterRegistry; + public RouteMatcher routeMatcher() { + return this.routeMatcher; + } + + @Override + public MetadataExtractor metadataExtractor() { + return this.metadataExtractor; } @Override @@ -87,6 +103,11 @@ final class DefaultRSocketStrategies implements RSocketStrategies { return this.bufferFactory; } + @Override + public ReactiveAdapterRegistry reactiveAdapterRegistry() { + return this.adapterRegistry; + } + /** * Default RSocketStrategies.Builder implementation. @@ -97,6 +118,12 @@ final class DefaultRSocketStrategies implements RSocketStrategies { private final List> decoders = new ArrayList<>(); + @Nullable + private RouteMatcher routeMatcher; + + @Nullable + private MetadataExtractor metadataExtractor; + private ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); @Nullable @@ -151,6 +178,18 @@ final class DefaultRSocketStrategies implements RSocketStrategies { return this; } + @Override + public Builder routeMatcher(RouteMatcher routeMatcher) { + this.routeMatcher = routeMatcher; + return this; + } + + @Override + public Builder metadataExtractor(MetadataExtractor metadataExtractor) { + this.metadataExtractor = metadataExtractor; + return this; + } + @Override public Builder reactiveAdapterStrategy(ReactiveAdapterRegistry registry) { Assert.notNull(registry, "ReactiveAdapterRegistry is required"); @@ -167,12 +206,27 @@ final class DefaultRSocketStrategies implements RSocketStrategies { @Override public RSocketStrategies build() { return new DefaultRSocketStrategies( - this.encoders, this.decoders, this.adapterRegistry, initBufferFactory()); + this.encoders, this.decoders, + this.routeMatcher != null ? this.routeMatcher : initRouteMatcher(), + this.metadataExtractor != null ? this.metadataExtractor : initMetadataExtractor(), + this.bufferFactory != null ? this.bufferFactory : initBufferFactory(), + this.adapterRegistry); + } + + private RouteMatcher initRouteMatcher() { + AntPathMatcher pathMatcher = new AntPathMatcher(); + pathMatcher.setPathSeparator("."); + return new SimpleRouteMatcher(pathMatcher); + } + + private MetadataExtractor initMetadataExtractor() { + DefaultMetadataExtractor extractor = new DefaultMetadataExtractor(); + extractor.metadataToExtract(MimeTypeUtils.TEXT_PLAIN, String.class, MetadataExtractor.ROUTE_KEY); + return extractor; } private DataBufferFactory initBufferFactory() { - return this.bufferFactory != null ? this.bufferFactory : - new NettyDataBufferFactory(PooledByteBufAllocator.DEFAULT); + return new NettyDataBufferFactory(PooledByteBufAllocator.DEFAULT); } } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketStrategies.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketStrategies.java index 8e6aa27f17c..6c1572aaa8b 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketStrategies.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/RSocketStrategies.java @@ -31,7 +31,10 @@ import org.springframework.core.io.buffer.DataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.NettyDataBufferFactory; import org.springframework.lang.Nullable; +import org.springframework.util.AntPathMatcher; import org.springframework.util.MimeType; +import org.springframework.util.RouteMatcher; +import org.springframework.util.SimpleRouteMatcher; /** * Access to strategies for use by RSocket requester and responder components. @@ -90,10 +93,14 @@ public interface RSocketStrategies { } /** - * Return the configured - * {@link Builder#reactiveAdapterStrategy(ReactiveAdapterRegistry) reactiveAdapterRegistry}. + * Return the configured {@link Builder#routeMatcher(RouteMatcher)}. */ - ReactiveAdapterRegistry reactiveAdapterRegistry(); + RouteMatcher routeMatcher(); + + /** + * Return the configured {@link Builder#metadataExtractor(MetadataExtractor)}. + */ + MetadataExtractor metadataExtractor(); /** * Return the configured @@ -101,6 +108,12 @@ public interface RSocketStrategies { */ DataBufferFactory dataBufferFactory(); + /** + * Return the configured + * {@link Builder#reactiveAdapterStrategy(ReactiveAdapterRegistry) reactiveAdapterRegistry}. + */ + ReactiveAdapterRegistry reactiveAdapterRegistry(); + /** * Return a builder to build a new {@code RSocketStrategies} instance. @@ -149,6 +162,27 @@ public interface RSocketStrategies { */ Builder decoders(Consumer>> consumer); + /** + * Configure a {@code RouteMatcher} for matching routes to message + * handlers based on route patterns. This option is applicable to + * client or server responders. + *

By default, {@link SimpleRouteMatcher} is used, backed by + * {@link AntPathMatcher} with "." as separator. For better + * efficiency consider using the {@code PathPatternRouteMatcher} from + * {@code spring-web} instead. + */ + Builder routeMatcher(RouteMatcher routeMatcher); + + /** + * Configure a {@link MetadataExtractor} to extract the route along with + * other metadata. This option is applicable to client or server + * responders. + *

By default this is {@link DefaultMetadataExtractor} extracting a + * route from {@code "message/x.rsocket.routing.v0"} or + * {@code "text/plain"} metadata entries. + */ + Builder metadataExtractor(MetadataExtractor metadataExtractor); + /** * Configure the registry for reactive type support. This can be used to * to adapt to, and/or determine the semantics of a given diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/AnnotationClientResponderConfigurer.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/AnnotationClientResponderConfigurer.java index b15e35e50ea..aadc3405abc 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/AnnotationClientResponderConfigurer.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/AnnotationClientResponderConfigurer.java @@ -25,10 +25,8 @@ import io.rsocket.RSocketFactory; import org.springframework.beans.BeanUtils; import org.springframework.lang.Nullable; import org.springframework.messaging.rsocket.ClientRSocketFactoryConfigurer; -import org.springframework.messaging.rsocket.MetadataExtractor; import org.springframework.messaging.rsocket.RSocketStrategies; import org.springframework.util.Assert; -import org.springframework.util.RouteMatcher; /** * {@link ClientRSocketFactoryConfigurer} to configure and plug in a responder @@ -44,12 +42,6 @@ public final class AnnotationClientResponderConfigurer implements ClientRSocketF private final List handlers = new ArrayList<>(); - @Nullable - private RouteMatcher routeMatcher; - - @Nullable - private MetadataExtractor extractor; - @Nullable private RSocketStrategies strategies; @@ -61,24 +53,6 @@ public final class AnnotationClientResponderConfigurer implements ClientRSocketF } - /** - * Configure the {@link RouteMatcher} to use. This is used to set - * {@link RSocketMessageHandler#setRouteMatcher(RouteMatcher)}. - */ - public AnnotationClientResponderConfigurer routeMatcher(RouteMatcher routeMatcher) { - this.routeMatcher = routeMatcher; - return this; - } - - /** - * Configure the {@link MetadataExtractor} to use. This is used to set - * {@link RSocketMessageHandler#setMetadataExtractor(MetadataExtractor)}. - */ - public AnnotationClientResponderConfigurer metadataExtractor(MetadataExtractor extractor) { - this.extractor = extractor; - return this; - } - /** * Configure handlers to detect {@code @MessasgeMapping} handler methods on. * This is used to set {@link RSocketMessageHandler#setHandlers(List)}. @@ -101,12 +75,6 @@ public final class AnnotationClientResponderConfigurer implements ClientRSocketF Assert.notEmpty(this.handlers, "No handlers"); RSocketMessageHandler messageHandler = new RSocketMessageHandler(); messageHandler.setHandlers(this.handlers); - if (this.routeMatcher != null) { - messageHandler.setRouteMatcher(this.routeMatcher); - } - if (this.extractor != null) { - messageHandler.setMetadataExtractor(this.extractor); - } messageHandler.setRSocketStrategies(this.strategies); messageHandler.afterPropertiesSet(); factory.acceptor(messageHandler.clientResponder()); diff --git a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java index 7f7ba9d9a1e..a595e735667 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/rsocket/annotation/support/RSocketMessageHandler.java @@ -114,10 +114,16 @@ public class RSocketMessageHandler extends MessageMappingMessageHandler { /** * Provide configuration in the form of {@link RSocketStrategies} instance * which can also be re-used to initialize a client-side - * {@link RSocketRequester}. When this property is set, it also sets - * {@link #setDecoders(List) decoders}, {@link #setEncoders(List) encoders}, - * and {@link #setReactiveAdapterRegistry(ReactiveAdapterRegistry) - * reactiveAdapterRegistry}. + * {@link RSocketRequester}. + *

When this is set, in turn it sets the following: + *

    + *
  • {@link #setDecoders(List)} + *
  • {@link #setEncoders(List)} + *
  • {@link #setRouteMatcher(RouteMatcher)} + *
  • {@link #setMetadataExtractor(MetadataExtractor)} + *
  • {@link #setReactiveAdapterRegistry(ReactiveAdapterRegistry)} + *
+ *

By default if this is not set, it is initialized from the above. */ public void setRSocketStrategies(@Nullable RSocketStrategies rsocketStrategies) { this.rsocketStrategies = rsocketStrategies; @@ -138,12 +144,10 @@ public class RSocketMessageHandler extends MessageMappingMessageHandler { } /** - * Configure a {@link MetadataExtractor} to extract the route and possibly - * other metadata from the first payload of incoming requests. - *

By default this is a {@link DefaultMetadataExtractor} with the - * configured {@link RSocketStrategies} (and decoders), extracting a route - * from {@code "message/x.rsocket.routing.v0"} or {@code "text/plain"} - * metadata entries. + * Configure a {@link MetadataExtractor} to extract the route along with + * other metadata. + *

By default this is {@link DefaultMetadataExtractor} extracting a + * route from {@code "message/x.rsocket.routing.v0"} or {@code "text/plain"}. * @param extractor the extractor to use */ public void setMetadataExtractor(MetadataExtractor extractor) { @@ -200,20 +204,25 @@ public class RSocketMessageHandler extends MessageMappingMessageHandler { @Override public void afterPropertiesSet() { + + getArgumentResolverConfigurer().addCustomResolver(new RSocketRequesterMethodArgumentResolver()); + super.afterPropertiesSet(); + + if (getMetadataExtractor() == null) { + DefaultMetadataExtractor extractor = new DefaultMetadataExtractor(); + extractor.metadataToExtract(MimeTypeUtils.TEXT_PLAIN, String.class, MetadataExtractor.ROUTE_KEY); + setMetadataExtractor(extractor); + } + if (this.rsocketStrategies == null) { this.rsocketStrategies = RSocketStrategies.builder() .decoder(getDecoders().toArray(new Decoder[0])) .encoder(getEncoders().toArray(new Encoder[0])) + .routeMatcher(getRouteMatcher()) + .metadataExtractor(getMetadataExtractor()) .reactiveAdapterStrategy(getReactiveAdapterRegistry()) .build(); } - if (this.metadataExtractor == null) { - DefaultMetadataExtractor extractor = new DefaultMetadataExtractor(); - extractor.metadataToExtract(MimeTypeUtils.TEXT_PLAIN, String.class, MetadataExtractor.ROUTE_KEY); - this.metadataExtractor = extractor; - } - getArgumentResolverConfigurer().addCustomResolver(new RSocketRequesterMethodArgumentResolver()); - super.afterPropertiesSet(); } @Override