Add SimpleUrlHandlerMapping
This commit replaces the temporary SimpleUrlHandlerMapping with a full-featured one.
This commit is contained in:
@@ -39,6 +39,17 @@ public interface HandlerMapping {
|
||||
*/
|
||||
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange} attribute that contains the path
|
||||
* within the handler mapping, in case of a pattern match, or the full
|
||||
* relevant URI (typically within the DispatcherServlet's mapping) else.
|
||||
* <p>Note: This attribute is not required to be supported by all
|
||||
* HandlerMapping implementations. URL-based HandlerMappings will
|
||||
* typically support it, but handlers should not necessarily expect
|
||||
* this request attribute to be present in all scenarios.
|
||||
*/
|
||||
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange} attribute that contains the URI
|
||||
* templates map, mapping variable names to values.
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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 org.springframework.web.reactive.handler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* Abstract base class for URL-mapped
|
||||
* {@link org.springframework.web.reactive.HandlerMapping} implementations.
|
||||
*
|
||||
* <p>Supports direct matches, e.g. a registered "/test" matches "/test", and
|
||||
* various Ant-style pattern matches, e.g. a registered "/t*" pattern matches
|
||||
* both "/test" and "/team", "/test/*" matches all paths under "/test",
|
||||
* "/test/**" matches all paths below "/test". For details, see the
|
||||
* {@link org.springframework.util.AntPathMatcher AntPathMatcher} javadoc.
|
||||
*
|
||||
* <p>Will search all path patterns to find the most exact match for the
|
||||
* current request path. The most exact match is defined as the longest
|
||||
* path pattern that matches the current request path.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
|
||||
|
||||
private boolean useTrailingSlashMatch = false;
|
||||
|
||||
private boolean lazyInitHandlers = false;
|
||||
|
||||
private final Map<String, Object> handlerMap = new LinkedHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Whether to match to URLs irrespective of the presence of a trailing slash.
|
||||
* If enabled a URL pattern such as "/users" also matches to "/users/".
|
||||
* <p>The default value is {@code false}.
|
||||
*/
|
||||
public void setUseTrailingSlashMatch(boolean useTrailingSlashMatch) {
|
||||
this.useTrailingSlashMatch = useTrailingSlashMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to match to URLs irrespective of the presence of a trailing slash.
|
||||
*/
|
||||
public boolean useTrailingSlashMatch() {
|
||||
return this.useTrailingSlashMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to lazily initialize handlers. Only applicable to
|
||||
* singleton handlers, as prototypes are always lazily initialized.
|
||||
* Default is "false", as eager initialization allows for more efficiency
|
||||
* through referencing the controller objects directly.
|
||||
* <p>If you want to allow your controllers to be lazily initialized,
|
||||
* make them "lazy-init" and set this flag to true. Just making them
|
||||
* "lazy-init" will not work, as they are initialized through the
|
||||
* references from the handler mapping in this case.
|
||||
*/
|
||||
public void setLazyInitHandlers(boolean lazyInitHandlers) {
|
||||
this.lazyInitHandlers = lazyInitHandlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the registered handlers as an unmodifiable Map, with the registered path
|
||||
* as key and the handler object (or handler bean name in case of a lazy-init handler)
|
||||
* as value.
|
||||
*/
|
||||
public final Map<String, Object> getHandlerMap() {
|
||||
return Collections.unmodifiableMap(this.handlerMap);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Mono<Object> getHandler(ServerWebExchange exchange) {
|
||||
String lookupPath = getPathHelper().getLookupPathForRequest(exchange);
|
||||
Object handler = null;
|
||||
try {
|
||||
handler = lookupHandler(lookupPath, exchange);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return Mono.error(ex);
|
||||
}
|
||||
|
||||
if (handler != null && logger.isDebugEnabled()) {
|
||||
logger.debug("Mapping [" + lookupPath + "] to " + handler);
|
||||
}
|
||||
else if (handler == null && logger.isTraceEnabled()) {
|
||||
logger.trace("No handler mapping found for [" + lookupPath + "]");
|
||||
}
|
||||
|
||||
return Mono.justOrEmpty(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a handler instance for the given URL path.
|
||||
*
|
||||
* <p>Supports direct matches, e.g. a registered "/test" matches "/test",
|
||||
* and various Ant-style pattern matches, e.g. a registered "/t*" matches
|
||||
* both "/test" and "/team". For details, see the AntPathMatcher class.
|
||||
*
|
||||
* <p>Looks for the most exact pattern, where most exact is defined as
|
||||
* the longest path pattern.
|
||||
*
|
||||
* @param urlPath URL the bean is mapped to
|
||||
* @param exchange the current exchange
|
||||
* @return the associated handler instance, or {@code null} if not found
|
||||
* @see org.springframework.util.AntPathMatcher
|
||||
*/
|
||||
protected Object lookupHandler(String urlPath, ServerWebExchange exchange) throws Exception {
|
||||
// Direct match?
|
||||
Object handler = this.handlerMap.get(urlPath);
|
||||
if (handler != null) {
|
||||
return handleMatch(handler, urlPath, urlPath, exchange);
|
||||
}
|
||||
// Pattern match?
|
||||
List<String> matches = new ArrayList<>();
|
||||
for (String pattern : this.handlerMap.keySet()) {
|
||||
if (getPathMatcher().match(pattern, urlPath)) {
|
||||
matches.add(pattern);
|
||||
}
|
||||
else if (useTrailingSlashMatch()) {
|
||||
if (!pattern.endsWith("/") && getPathMatcher().match(pattern + "/", urlPath)) {
|
||||
matches.add(pattern +"/");
|
||||
}
|
||||
}
|
||||
}
|
||||
String bestMatch = null;
|
||||
Comparator<String> comparator = getPathMatcher().getPatternComparator(urlPath);
|
||||
if (!matches.isEmpty()) {
|
||||
Collections.sort(matches, comparator);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Matching patterns for request [" + urlPath + "] are " + matches);
|
||||
}
|
||||
bestMatch = matches.get(0);
|
||||
}
|
||||
if (bestMatch != null) {
|
||||
handler = this.handlerMap.get(bestMatch);
|
||||
if (handler == null) {
|
||||
Assert.isTrue(bestMatch.endsWith("/"));
|
||||
handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));
|
||||
}
|
||||
String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);
|
||||
return handleMatch(handler, bestMatch, pathWithinMapping, exchange);
|
||||
}
|
||||
// No handler found...
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object handleMatch(Object handler, String bestMatch, String pathWithinMapping,
|
||||
ServerWebExchange exchange) throws Exception {
|
||||
|
||||
// Bean name or resolved handler?
|
||||
if (handler instanceof String) {
|
||||
String handlerName = (String) handler;
|
||||
handler = getApplicationContext().getBean(handlerName);
|
||||
}
|
||||
|
||||
validateHandler(handler, exchange);
|
||||
|
||||
exchange.getAttributes().put(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping);
|
||||
exchange.getAttributes().put(BEST_MATCHING_PATTERN_ATTRIBUTE, bestMatch);
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the given handler against the current request.
|
||||
* <p>The default implementation is empty. Can be overridden in subclasses,
|
||||
* for example to enforce specific preconditions expressed in URL mappings.
|
||||
* @param handler the handler object to validate
|
||||
* @param exchange current exchange
|
||||
* @throws Exception if validation failed
|
||||
*/
|
||||
@SuppressWarnings("UnusedParameters")
|
||||
protected void validateHandler(Object handler, ServerWebExchange exchange) throws Exception {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the specified handler for the given URL paths.
|
||||
* @param urlPaths the URLs that the bean should be mapped to
|
||||
* @param beanName the name of the handler bean
|
||||
* @throws BeansException if the handler couldn't be registered
|
||||
* @throws IllegalStateException if there is a conflicting handler registered
|
||||
*/
|
||||
protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {
|
||||
Assert.notNull(urlPaths, "URL path array must not be null");
|
||||
for (String urlPath : urlPaths) {
|
||||
registerHandler(urlPath, beanName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the specified handler for the given URL path.
|
||||
* @param urlPath the URL the bean should be mapped to
|
||||
* @param handler the handler instance or handler bean name String
|
||||
* (a bean name will automatically be resolved into the corresponding handler bean)
|
||||
* @throws BeansException if the handler couldn't be registered
|
||||
* @throws IllegalStateException if there is a conflicting handler registered
|
||||
*/
|
||||
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
|
||||
Assert.notNull(urlPath, "URL path must not be null");
|
||||
Assert.notNull(handler, "Handler object must not be null");
|
||||
Object resolvedHandler = handler;
|
||||
|
||||
// Eagerly resolve handler if referencing singleton via name.
|
||||
if (!this.lazyInitHandlers && handler instanceof String) {
|
||||
String handlerName = (String) handler;
|
||||
if (getApplicationContext().isSingleton(handlerName)) {
|
||||
resolvedHandler = getApplicationContext().getBean(handlerName);
|
||||
}
|
||||
}
|
||||
|
||||
Object mappedHandler = this.handlerMap.get(urlPath);
|
||||
if (mappedHandler != null) {
|
||||
if (mappedHandler != resolvedHandler) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
|
||||
"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.handlerMap.put(urlPath, resolvedHandler);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getHandlerDescription(Object handler) {
|
||||
return "handler " + (handler instanceof String ? "'" + handler + "'" : "of type [" + handler.getClass() + "]");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -16,41 +16,116 @@
|
||||
|
||||
package org.springframework.web.reactive.handler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link org.springframework.web.reactive.HandlerMapping}
|
||||
* interface to map from URLs to request handler beans. Supports both mapping
|
||||
* to bean instances and mapping to bean names; the latter is required for
|
||||
* non-singleton handlers.
|
||||
*
|
||||
* <p>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:
|
||||
*
|
||||
* <pre>
|
||||
* /welcome.html=ticketController
|
||||
* /show.html=ticketController
|
||||
* </pre>
|
||||
*
|
||||
* <p>The syntax is {@code PATH=HANDLER_BEAN_NAME}. If the path doesn't begin
|
||||
* with a slash, one is prepended.
|
||||
*
|
||||
* <p>Supports direct matches, e.g. a registered "/test" matches "/test", and
|
||||
* various Ant-style pattern matches, e.g. a registered "/t*" pattern matches
|
||||
* both "/test" and "/team", "/test/*" matches all paths under "/test",
|
||||
* "/test/**" matches all paths below "/test". For details, see the
|
||||
* {@link org.springframework.util.AntPathMatcher AntPathMatcher} javadoc.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class SimpleUrlHandlerMapping implements HandlerMapping {
|
||||
public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
|
||||
|
||||
private final Map<String, Object> handlerMap = new HashMap<>();
|
||||
private final Map<String, Object> urlMap = new LinkedHashMap<>();
|
||||
|
||||
|
||||
public void setHandlers(Map<String, Object> handlers) {
|
||||
this.handlerMap.clear();
|
||||
if (handlers != null) {
|
||||
this.handlerMap.putAll(handlers);
|
||||
/**
|
||||
* Map URL paths to handler bean names.
|
||||
* This is the typical way of configuring this HandlerMapping.
|
||||
* <p>Supports direct URL matches and Ant-style pattern matches. For syntax
|
||||
* details, see the {@link org.springframework.util.AntPathMatcher} javadoc.
|
||||
* @param mappings properties with URLs as keys and bean names as values
|
||||
* @see #setUrlMap
|
||||
*/
|
||||
public void setMappings(Properties mappings) {
|
||||
CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Map with URL paths as keys and handler beans (or handler bean names)
|
||||
* as values. Convenient for population with bean references.
|
||||
* <p>Supports direct URL matches and Ant-style pattern matches. For syntax
|
||||
* details, see the {@link org.springframework.util.AntPathMatcher} javadoc.
|
||||
* @param urlMap map with URLs as keys and beans as values
|
||||
* @see #setMappings
|
||||
*/
|
||||
public void setUrlMap(Map<String, ?> urlMap) {
|
||||
this.urlMap.putAll(urlMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow Map access to the URL path mappings, with the option to add or
|
||||
* override specific entries.
|
||||
* <p>Useful for specifying entries directly, for example via "urlMap[myKey]".
|
||||
* This is particularly useful for adding or overriding entries in child
|
||||
* bean definitions.
|
||||
*/
|
||||
public Map<String, ?> getUrlMap() {
|
||||
return this.urlMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls the {@link #registerHandlers} method in addition to the
|
||||
* superclass's initialization.
|
||||
*/
|
||||
@Override
|
||||
public void initApplicationContext() throws BeansException {
|
||||
super.initApplicationContext();
|
||||
registerHandlers(this.urlMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all handlers specified in the URL map for the corresponding paths.
|
||||
* @param urlMap Map with URL paths as keys and handler beans or bean names as values
|
||||
* @throws BeansException if a handler couldn't be registered
|
||||
* @throws IllegalStateException if there is a conflicting handler registered
|
||||
*/
|
||||
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
|
||||
if (urlMap.isEmpty()) {
|
||||
logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
|
||||
}
|
||||
else {
|
||||
for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
|
||||
String url = entry.getKey();
|
||||
Object handler = entry.getValue();
|
||||
// Prepend with slash if not already present.
|
||||
if (!url.startsWith("/")) {
|
||||
url = "/" + url;
|
||||
}
|
||||
// Remove whitespace from handler bean name.
|
||||
if (handler instanceof String) {
|
||||
handler = ((String) handler).trim();
|
||||
}
|
||||
registerHandler(url, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Mono<Object> getHandler(ServerWebExchange exchange) {
|
||||
return Flux.create(subscriber -> {
|
||||
String path = exchange.getRequest().getURI().getPath();
|
||||
Object handler = this.handlerMap.get(path);
|
||||
if (handler != null) {
|
||||
subscriber.onNext(handler);
|
||||
}
|
||||
subscriber.onComplete();
|
||||
}).next();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://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 org.springframework.web.reactive.handler;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.server.reactive.MockServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.MockServerHttpResponse;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.web.reactive.HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SimpleUrlHandlerMapping}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class SimpleUrlHandlerMappingTests {
|
||||
|
||||
@Test
|
||||
public void handlerMappingJavaConfig() throws Exception {
|
||||
AnnotationConfigApplicationContext wac = new AnnotationConfigApplicationContext();
|
||||
wac.register(WebConfig.class);
|
||||
wac.refresh();
|
||||
|
||||
HandlerMapping handlerMapping = (HandlerMapping) wac.getBean("handlerMapping");
|
||||
Object mainController = wac.getBean("mainController");
|
||||
Object otherController = wac.getBean("otherController");
|
||||
|
||||
testUrl("/welcome.html", mainController, handlerMapping, "/welcome.html");
|
||||
testUrl("/welcome.x", otherController, handlerMapping, "welcome.x");
|
||||
testUrl("/welcome/", otherController, handlerMapping, "welcome");
|
||||
testUrl("/show.html", mainController, handlerMapping, "/show.html");
|
||||
testUrl("/bookseats.html", mainController, handlerMapping, "/bookseats.html");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handlerMappingXmlConfig() throws Exception {
|
||||
ClassPathXmlApplicationContext wac = new ClassPathXmlApplicationContext("map.xml", getClass());
|
||||
wac.refresh();
|
||||
|
||||
HandlerMapping handlerMapping = wac.getBean("mapping", HandlerMapping.class);
|
||||
Object mainController = wac.getBean("mainController");
|
||||
|
||||
testUrl("/pathmatchingTest.html", mainController, handlerMapping, "pathmatchingTest.html");
|
||||
testUrl("welcome.html", null, handlerMapping, null);
|
||||
testUrl("/pathmatchingAA.html", mainController, handlerMapping, "pathmatchingAA.html");
|
||||
testUrl("/pathmatchingA.html", null, handlerMapping, null);
|
||||
testUrl("/administrator/pathmatching.html", mainController, handlerMapping, "pathmatching.html");
|
||||
testUrl("/administrator/test/pathmatching.html", mainController, handlerMapping, "test/pathmatching.html");
|
||||
testUrl("/administratort/pathmatching.html", null, handlerMapping, null);
|
||||
testUrl("/administrator/another/bla.xml", mainController, handlerMapping, "/administrator/another/bla.xml");
|
||||
testUrl("/administrator/another/bla.gif", null, handlerMapping, null);
|
||||
testUrl("/administrator/test/testlastbit", mainController, handlerMapping, "test/testlastbit");
|
||||
testUrl("/administrator/test/testla", null, handlerMapping, null);
|
||||
testUrl("/administrator/testing/longer/bla", mainController, handlerMapping, "bla");
|
||||
testUrl("/administrator/testing/longer2/notmatching/notmatching", null, handlerMapping, null);
|
||||
testUrl("/shortpattern/testing/toolong", null, handlerMapping, null);
|
||||
testUrl("/XXpathXXmatching.html", mainController, handlerMapping, "XXpathXXmatching.html");
|
||||
testUrl("/pathXXmatching.html", mainController, handlerMapping, "pathXXmatching.html");
|
||||
testUrl("/XpathXXmatching.html", null, handlerMapping, null);
|
||||
testUrl("/XXpathmatching.html", null, handlerMapping, null);
|
||||
testUrl("/show12.html", mainController, handlerMapping, "show12.html");
|
||||
testUrl("/show123.html", mainController, handlerMapping, "/show123.html");
|
||||
testUrl("/show1.html", mainController, handlerMapping, "show1.html");
|
||||
testUrl("/reallyGood-test-is-this.jpeg", mainController, handlerMapping, "reallyGood-test-is-this.jpeg");
|
||||
testUrl("/reallyGood-tst-is-this.jpeg", null, handlerMapping, null);
|
||||
testUrl("/testing/test.jpeg", mainController, handlerMapping, "testing/test.jpeg");
|
||||
testUrl("/testing/test.jpg", null, handlerMapping, null);
|
||||
testUrl("/anotherTest", mainController, handlerMapping, "anotherTest");
|
||||
testUrl("/stillAnotherTest", null, handlerMapping, null);
|
||||
testUrl("outofpattern*ye", null, handlerMapping, null);
|
||||
testUrl("/test%26t%20est/path%26m%20atching.html", null, handlerMapping, null);
|
||||
|
||||
}
|
||||
|
||||
private void testUrl(String url, Object bean, HandlerMapping handlerMapping, String pathWithinMapping)
|
||||
throws URISyntaxException {
|
||||
|
||||
ServerWebExchange exchange = createExchange(url);
|
||||
Object actual = handlerMapping.getHandler(exchange).get();
|
||||
if (bean != null) {
|
||||
assertNotNull(actual);
|
||||
assertSame(bean, actual);
|
||||
//noinspection OptionalGetWithoutIsPresent
|
||||
assertEquals(pathWithinMapping, exchange.getAttribute(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).get());
|
||||
}
|
||||
else {
|
||||
assertNull(actual);
|
||||
}
|
||||
}
|
||||
|
||||
private ServerWebExchange createExchange(String path) throws URISyntaxException {
|
||||
ServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, new URI(path));
|
||||
WebSessionManager sessionManager = mock(WebSessionManager.class);
|
||||
return new DefaultServerWebExchange(request, new MockServerHttpResponse(), sessionManager);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class WebConfig {
|
||||
|
||||
@Bean @SuppressWarnings("unused")
|
||||
public SimpleUrlHandlerMapping handlerMapping() {
|
||||
SimpleUrlHandlerMapping hm = new SimpleUrlHandlerMapping();
|
||||
hm.setUseTrailingSlashMatch(true);
|
||||
hm.registerHandler("/welcome*", otherController());
|
||||
hm.registerHandler("/welcome.html", mainController());
|
||||
hm.registerHandler("/show.html", mainController());
|
||||
hm.registerHandler("/bookseats.html", mainController());
|
||||
return hm;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Object mainController() {
|
||||
return new Object();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Object otherController() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,10 +39,8 @@ import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.DispatcherHandler;
|
||||
import org.springframework.web.reactive.ResponseStatusExceptionHandler;
|
||||
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.reactive.result.SimpleResultHandler;
|
||||
import org.springframework.web.reactive.result.WebHandlerHandlerAdapter;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
@@ -138,7 +136,7 @@ public class WebHandlerIntegrationTests extends AbstractHttpHandlerIntegrationTe
|
||||
map.put("/foo", new FooHandler());
|
||||
map.put("/bar", new BarHandler());
|
||||
map.put("/header", new HeaderSettingHandler());
|
||||
setHandlers(map);
|
||||
setUrlMap(map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="mapping" class="org.springframework.web.reactive.handler.SimpleUrlHandlerMapping">
|
||||
<property name="urlDecode" value="true" />
|
||||
<property name="mappings">
|
||||
<value>
|
||||
welcome.html=mainController
|
||||
/**/pathmatchingTest.html=mainController
|
||||
/**/pathmatching??.html=mainController
|
||||
/**/path??matching.html=mainController
|
||||
/**/??path??matching.html=mainController
|
||||
/**/*.jsp=mainController
|
||||
/administrator/**/pathmatching.html=mainController
|
||||
/administrator/**/testlast*=mainController
|
||||
/administrator/another/bla.xml=mainController
|
||||
/administrator/testing/longer/**/**/**/**/**=mainController
|
||||
/administrator/testing/longer2/**/**/bla/**=mainController
|
||||
/*test*.jpeg=mainController
|
||||
/*/test.jpeg=mainController
|
||||
/outofpattern*yeah=mainController
|
||||
/anotherTest*=mainController
|
||||
/stillAnotherTestYeah=mainController
|
||||
/shortpattern/testing=mainController
|
||||
/show123.html=mainController
|
||||
/sho*=mainController
|
||||
/bookseats.html=mainController
|
||||
/reservation.html=mainController
|
||||
/payment.html=mainController
|
||||
/confirmation.html=mainController
|
||||
/test%26t%20est/path%26m%20atching.html=mainController
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="mainController" class="java.lang.Object"/>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user