From f53cdb8bd23429fde82a7f0912199484dadd19c9 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Sun, 28 Jul 2019 17:50:44 +0200 Subject: [PATCH] Introduce common SimpleUrlHandlerMapping constructors Prior to this commit, the SimpleUrlHandlerMapping classes in Spring MVC and Spring Webflux only had default constructors. This lead to the fact that users often had to explicitly invoke setUrlMap() and setOrder() on the newly instantiated SimpleUrlHandlerMapping. In order to simplify the programmatic setup of a SimpleUrlHandlerMapping in common scenarios, this commit introduces the following constructors. - SimpleUrlHandlerMapping() - SimpleUrlHandlerMapping(Map urlMap) - SimpleUrlHandlerMapping(Map urlMap, int order) Closes gh-23362 --- .../config/ResourceHandlerRegistry.java | 5 +- .../handler/SimpleUrlHandlerMapping.java | 43 ++++++++++++++-- .../resource/ResourceUrlProviderTests.java | 7 +-- ...mpleUrlHandlerMappingIntegrationTests.java | 24 ++++----- .../socket/WebSocketIntegrationTests.java | 6 +-- .../DefaultServletHandlerConfigurer.java | 17 +++---- .../annotation/ResourceHandlerRegistry.java | 7 +-- .../annotation/ViewControllerRegistry.java | 5 +- .../handler/SimpleUrlHandlerMapping.java | 49 ++++++++++++++++--- .../handler/SimpleUrlHandlerMappingTests.java | 11 ++--- .../resource/ResourceUrlProviderTests.java | 9 ++-- src/docs/asciidoc/web/webflux-websocket.adoc | 6 +-- 12 files changed, 113 insertions(+), 76 deletions(-) diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/config/ResourceHandlerRegistry.java b/spring-webflux/src/main/java/org/springframework/web/reactive/config/ResourceHandlerRegistry.java index cd9dc05a239..bcdff7fa8af 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/config/ResourceHandlerRegistry.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/config/ResourceHandlerRegistry.java @@ -152,10 +152,7 @@ public class ResourceHandlerRegistry { urlMap.put(pathPattern, handler); } } - SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); - handlerMapping.setOrder(this.order); - handlerMapping.setUrlMap(urlMap); - return handlerMapping; + return new SimpleUrlHandlerMapping(urlMap, this.order); } } diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMapping.java b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMapping.java index 131c4f99e2f..3e6e5c0f59d 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMapping.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/handler/SimpleUrlHandlerMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,12 +32,11 @@ import org.springframework.util.CollectionUtils; *

The "urlMap" property is suitable for populating the handler map with * bean instances. Mappings to bean names can be set via the "mappings" * property, in a form accepted by the {@code java.util.Properties} class, - * like as follows: + * as follows: * - *

+ * 
  * /welcome.html=ticketController
- * /show.html=ticketController
- * 
+ * /show.html=ticketController
* *

The syntax is {@code PATH=HANDLER_BEAN_NAME}. If the path doesn't begin * with a slash, one is prepended. @@ -49,6 +48,7 @@ import org.springframework.util.CollectionUtils; * {@link org.springframework.web.util.pattern.PathPattern} javadoc. * * @author Rossen Stoyanchev + * @author Sam Brannen * @since 5.0 */ public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping { @@ -56,6 +56,39 @@ public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping { private final Map urlMap = new LinkedHashMap<>(); + /** + * Create a {@code SimpleUrlHandlerMapping} with default settings. + * @since 5.2 + */ + public SimpleUrlHandlerMapping() { + } + + /** + * Create a {@code SimpleUrlHandlerMapping} using the supplied URL map. + * @param urlMap map with URL paths as keys and handler beans (or handler + * bean names) as values + * @since 5.2 + * @see #setUrlMap(Map) + */ + public SimpleUrlHandlerMapping(Map urlMap) { + setUrlMap(urlMap); + } + + /** + * Create a {@code SimpleUrlHandlerMapping} using the supplied URL map and order. + * @param urlMap map with URL paths as keys and handler beans (or handler + * bean names) as values + * @param order the order value for this {@code SimpleUrlHandlerMapping} + * @since 5.2 + * @see #setUrlMap(Map) + * @see #setOrder(int) + */ + public SimpleUrlHandlerMapping(Map urlMap, int order) { + setUrlMap(urlMap); + setOrder(order); + } + + /** * Map URL paths to handler bean names. * This is the typical way of configuring this HandlerMapping. diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceUrlProviderTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceUrlProviderTests.java index 0ac197beb8d..b6caad2d2bc 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceUrlProviderTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/resource/ResourceUrlProviderTests.java @@ -152,12 +152,7 @@ public class ResourceUrlProviderTests { @Bean public SimpleUrlHandlerMapping simpleUrlHandlerMapping() { - ResourceWebHandler handler = new ResourceWebHandler(); - HashMap handlerMap = new HashMap<>(); - handlerMap.put("/resources/**", handler); - SimpleUrlHandlerMapping hm = new SimpleUrlHandlerMapping(); - hm.setUrlMap(handlerMap); - return hm; + return new SimpleUrlHandlerMapping(Collections.singletonMap("/resources/**", new ResourceWebHandler())); } @Bean diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/result/SimpleUrlHandlerMappingIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/result/SimpleUrlHandlerMappingIntegrationTests.java index 422e8725e2f..539dde8da7e 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/result/SimpleUrlHandlerMappingIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/result/SimpleUrlHandlerMappingIntegrationTests.java @@ -119,20 +119,16 @@ public class SimpleUrlHandlerMappingIntegrationTests extends AbstractHttpHandler @Bean public SimpleUrlHandlerMapping handlerMapping() { - return new SimpleUrlHandlerMapping() { - { - Map map = new HashMap<>(); - map.put("/foo", (WebHandler) exchange -> - exchange.getResponse().writeWith(Flux.just(asDataBuffer("foo")))); - map.put("/bar", (WebHandler) exchange -> - exchange.getResponse().writeWith(Flux.just(asDataBuffer("bar")))); - map.put("/header", (WebHandler) exchange -> { - exchange.getResponse().getHeaders().add("foo", "bar"); - return Mono.empty(); - }); - setUrlMap(map); - } - }; + Map map = new HashMap<>(); + map.put("/foo", (WebHandler) exchange -> + exchange.getResponse().writeWith(Flux.just(asDataBuffer("foo")))); + map.put("/bar", (WebHandler) exchange -> + exchange.getResponse().writeWith(Flux.just(asDataBuffer("bar")))); + map.put("/header", (WebHandler) exchange -> { + exchange.getResponse().getHeaders().add("foo", "bar"); + return Mono.empty(); + }); + return new SimpleUrlHandlerMapping(map); } @Bean diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/socket/WebSocketIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/socket/WebSocketIntegrationTests.java index f40381d2400..a77567542ff 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/socket/WebSocketIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/socket/WebSocketIntegrationTests.java @@ -145,12 +145,8 @@ public class WebSocketIntegrationTests extends AbstractWebSocketIntegrationTests map.put("/sub-protocol", new SubProtocolWebSocketHandler()); map.put("/custom-header", new CustomHeaderHandler()); map.put("/close", new SessionClosingHandler()); - - SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); - mapping.setUrlMap(map); - return mapping; + return new SimpleUrlHandlerMapping(map); } - } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DefaultServletHandlerConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DefaultServletHandlerConfigurer.java index f73064220f5..993e952d011 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DefaultServletHandlerConfigurer.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DefaultServletHandlerConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package org.springframework.web.servlet.config.annotation; import java.util.Collections; import javax.servlet.ServletContext; +import org.springframework.core.Ordered; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.web.servlet.DispatcherServlet; @@ -85,9 +86,10 @@ public class DefaultServletHandlerConfigurer { /** - * Return a handler mapping instance ordered at {@link Integer#MAX_VALUE} containing the - * {@link DefaultServletHttpRequestHandler} instance mapped to {@code "/**"}; - * or {@code null} if default servlet handling was not been enabled. + * Return a handler mapping instance ordered at {@link Ordered#LOWEST_PRECEDENCE} + * containing the {@link DefaultServletHttpRequestHandler} instance mapped + * to {@code "/**"}; or {@code null} if default servlet handling was not + * been enabled. * @since 4.3.12 */ @Nullable @@ -95,11 +97,8 @@ public class DefaultServletHandlerConfigurer { if (this.handler == null) { return null; } - - SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); - handlerMapping.setUrlMap(Collections.singletonMap("/**", this.handler)); - handlerMapping.setOrder(Integer.MAX_VALUE); - return handlerMapping; + return new SimpleUrlHandlerMapping(Collections.singletonMap("/**", this.handler), + Ordered.LOWEST_PRECEDENCE); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistry.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistry.java index 3c33770df3b..2c71f9aba6f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistry.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -177,10 +177,7 @@ public class ResourceHandlerRegistry { } } - SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); - handlerMapping.setOrder(this.order); - handlerMapping.setUrlMap(urlMap); - return handlerMapping; + return new SimpleUrlHandlerMapping(urlMap, this.order); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistry.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistry.java index 673682b15db..cf940cca2af 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistry.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ViewControllerRegistry.java @@ -125,10 +125,7 @@ public class ViewControllerRegistry { urlMap.put(registration.getUrlPath(), registration.getViewController()); } - SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); - handlerMapping.setUrlMap(urlMap); - handlerMapping.setOrder(this.order); - return handlerMapping; + return new SimpleUrlHandlerMapping(urlMap, this.order); } } diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java index fc169ae2924..a16c07b4217 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMapping.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,13 +34,14 @@ import org.springframework.util.CollectionUtils; * bean references, e.g. via the map element in XML bean definitions. * *

Mappings to bean names can be set via the "mappings" property, in a form - * accepted by the {@code java.util.Properties} class, like as follows:
- * {@code + * accepted by the {@code java.util.Properties} class, as follows: + * + *

  * /welcome.html=ticketController
- * /show.html=ticketController
- * }
- * The syntax is {@code PATH=HANDLER_BEAN_NAME}. - * If the path doesn't begin with a slash, one is prepended. + * /show.html=ticketController
+ * + *

The syntax is {@code PATH=HANDLER_BEAN_NAME}. If the path doesn't begin + * with a slash, one is prepended. * *

Supports direct matches (given "/test" -> registered "/test") and "*" * pattern matches (given "/test" -> registered "/t*"). Note that the default @@ -50,6 +51,7 @@ import org.springframework.util.CollectionUtils; * @author Rod Johnson * @author Juergen Hoeller + * @author Sam Brannen * @see #setMappings * @see #setUrlMap * @see BeanNameUrlHandlerMapping @@ -59,6 +61,39 @@ public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping { private final Map urlMap = new LinkedHashMap<>(); + /** + * Create a {@code SimpleUrlHandlerMapping} with default settings. + * @since 5.2 + */ + public SimpleUrlHandlerMapping() { + } + + /** + * Create a {@code SimpleUrlHandlerMapping} using the supplied URL map. + * @param urlMap map with URL paths as keys and handler beans (or handler + * bean names) as values + * @since 5.2 + * @see #setUrlMap(Map) + */ + public SimpleUrlHandlerMapping(Map urlMap) { + setUrlMap(urlMap); + } + + /** + * Create a {@code SimpleUrlHandlerMapping} using the supplied URL map and order. + * @param urlMap map with URL paths as keys and handler beans (or handler + * bean names) as values + * @param order the order value for this {@code SimpleUrlHandlerMapping} + * @since 5.2 + * @see #setUrlMap(Map) + * @see #setOrder(int) + */ + public SimpleUrlHandlerMapping(Map urlMap, int order) { + setUrlMap(urlMap); + setOrder(order); + } + + /** * Map URL paths to handler bean names. * This is the typical way of configuring this HandlerMapping. diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java index a5c25777640..73976804d3e 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/handler/SimpleUrlHandlerMappingTests.java @@ -16,8 +16,7 @@ package org.springframework.web.servlet.handler; -import java.util.LinkedHashMap; -import java.util.Map; +import java.util.Collections; import org.junit.Test; @@ -72,12 +71,10 @@ public class SimpleUrlHandlerMappingTests { @Test public void testNewlineInRequest() throws Exception { - SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping(); - handlerMapping.setUrlDecode(false); Object controller = new Object(); - Map urlMap = new LinkedHashMap<>(); - urlMap.put("/*/baz", controller); - handlerMapping.setUrlMap(urlMap); + SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping( + Collections.singletonMap("/*/baz", controller)); + handlerMapping.setUrlDecode(false); handlerMapping.setApplicationContext(new StaticApplicationContext()); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo%0a%0dbar/baz"); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlProviderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlProviderTests.java index ef240d17de2..9ada1eca34a 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlProviderTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceUrlProviderTests.java @@ -17,6 +17,7 @@ package org.springframework.web.servlet.resource; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -174,12 +175,8 @@ public class ResourceUrlProviderTests { @Bean public SimpleUrlHandlerMapping simpleUrlHandlerMapping() { - ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); - HashMap handlerMap = new HashMap<>(); - handlerMap.put("/resources/**", handler); - SimpleUrlHandlerMapping hm = new SimpleUrlHandlerMapping(); - hm.setUrlMap(handlerMap); - return hm; + return new SimpleUrlHandlerMapping( + Collections.singletonMap("/resources/**", new ResourceHttpRequestHandler())); } @Bean diff --git a/src/docs/asciidoc/web/webflux-websocket.adoc b/src/docs/asciidoc/web/webflux-websocket.adoc index 8dbeb01d1be..4585333b31a 100644 --- a/src/docs/asciidoc/web/webflux-websocket.adoc +++ b/src/docs/asciidoc/web/webflux-websocket.adoc @@ -53,11 +53,9 @@ Then you can map it to a URL and add a `WebSocketHandlerAdapter`, as the followi public HandlerMapping handlerMapping() { Map map = new HashMap<>(); map.put("/path", new MyWebSocketHandler()); + int order = -1; // before annotated controllers - SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); - mapping.setUrlMap(map); - mapping.setOrder(-1); // before annotated controllers - return mapping; + return new SimpleUrlHandlerMapping(map, order); } @Bean