diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
index ed756dfc8c..42c4960fbd 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/AnnotationDrivenBeanDefinitionParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 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.
@@ -163,6 +163,8 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
handlerMappingDef.getPropertyValues().add("removeSemicolonContent", !enableMatrixVariables);
}
+ configurePathMatchingProperties(handlerMappingDef, element, parserContext);
+
RuntimeBeanReference conversionService = getConversionService(element, source, parserContext);
RuntimeBeanReference validator = getValidator(element, source, parserContext);
RuntimeBeanReference messageCodesResolver = getMessageCodesResolver(element);
@@ -309,6 +311,40 @@ class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
return contentNegotiationManagerRef;
}
+ private void configurePathMatchingProperties(RootBeanDefinition handlerMappingDef, Element element,
+ ParserContext parserContext) {
+
+ Element pathMatchingElement = DomUtils.getChildElementByTagName(element, "path-matching");
+ if (pathMatchingElement != null) {
+ Object source = parserContext.extractSource(element);
+ if (pathMatchingElement.hasAttribute("suffix-pattern")) {
+ Boolean useSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("suffix-pattern"));
+ handlerMappingDef.getPropertyValues().add("useSuffixPatternMatch", useSuffixPatternMatch);
+ }
+ if (pathMatchingElement.hasAttribute("trailing-slash")) {
+ Boolean useTrailingSlashMatch = Boolean.valueOf(pathMatchingElement.getAttribute("trailing-slash"));
+ handlerMappingDef.getPropertyValues().add("useTrailingSlashMatch", useTrailingSlashMatch);
+ }
+ if (pathMatchingElement.hasAttribute("registered-suffixes-only")) {
+ Boolean useRegisteredSuffixPatternMatch = Boolean.valueOf(pathMatchingElement.getAttribute("registered-suffixes-only"));
+ handlerMappingDef.getPropertyValues().add("useRegisteredSuffixPatternMatch", useRegisteredSuffixPatternMatch);
+ }
+ RuntimeBeanReference pathHelperRef = null;
+ if (pathMatchingElement.hasAttribute("path-helper")) {
+ pathHelperRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-helper"));
+ }
+ pathHelperRef = MvcNamespaceUtils.registerUrlPathHelper(pathHelperRef, parserContext, source);
+ handlerMappingDef.getPropertyValues().add("urlPathHelper", pathHelperRef);
+
+ RuntimeBeanReference pathMatcherRef = null;
+ if (pathMatchingElement.hasAttribute("path-matcher")) {
+ pathMatcherRef = new RuntimeBeanReference(pathMatchingElement.getAttribute("path-matcher"));
+ }
+ pathMatcherRef = MvcNamespaceUtils.registerPathMatcher(pathMatcherRef, parserContext, source);
+ handlerMappingDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
+ }
+ }
+
private Properties getDefaultMediaTypes() {
Properties props = new Properties();
if (romePresent) {
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java
index abf53b4e2c..4ce612ff79 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 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.
@@ -17,12 +17,16 @@
package org.springframework.web.servlet.config;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.util.PathMatcher;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
+import org.springframework.web.util.UrlPathHelper;
/**
* Convenience methods for use in MVC namespace BeanDefinitionParsers.
@@ -41,12 +45,70 @@ abstract class MvcNamespaceUtils {
private static final String HTTP_REQUEST_HANDLER_ADAPTER_BEAN_NAME =
HttpRequestHandlerAdapter.class.getName();
+ private static final String URL_PATH_HELPER_BEAN_NAME = "mvcUrlPathHelper";
+
+ private static final String PATH_MATCHER_BEAN_NAME = "mvcPathMatcher";
+
+
public static void registerDefaultComponents(ParserContext parserContext, Object source) {
registerBeanNameUrlHandlerMapping(parserContext, source);
registerHttpRequestHandlerAdapter(parserContext, source);
registerSimpleControllerHandlerAdapter(parserContext, source);
}
+
+ /**
+ * Adds an alias to an existing well-known name or registers a new instance of a {@link UrlPathHelper}
+ * under that well-known name, unless already registered.
+ * @return a RuntimeBeanReference to this {@link UrlPathHelper} instance
+ * @since 3.2.17
+ */
+ public static RuntimeBeanReference registerUrlPathHelper(RuntimeBeanReference urlPathHelperRef,
+ ParserContext parserContext, Object source) {
+
+ if (urlPathHelperRef != null) {
+ if (parserContext.getRegistry().isAlias(URL_PATH_HELPER_BEAN_NAME)) {
+ parserContext.getRegistry().removeAlias(URL_PATH_HELPER_BEAN_NAME);
+ }
+ parserContext.getRegistry().registerAlias(urlPathHelperRef.getBeanName(), URL_PATH_HELPER_BEAN_NAME);
+ }
+ else if (!parserContext.getRegistry().isAlias(URL_PATH_HELPER_BEAN_NAME)
+ && !parserContext.getRegistry().containsBeanDefinition(URL_PATH_HELPER_BEAN_NAME)) {
+ RootBeanDefinition urlPathHelperDef = new RootBeanDefinition(UrlPathHelper.class);
+ urlPathHelperDef.setSource(source);
+ urlPathHelperDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+ parserContext.getRegistry().registerBeanDefinition(URL_PATH_HELPER_BEAN_NAME, urlPathHelperDef);
+ parserContext.registerComponent(new BeanComponentDefinition(urlPathHelperDef, URL_PATH_HELPER_BEAN_NAME));
+ }
+ return new RuntimeBeanReference(URL_PATH_HELPER_BEAN_NAME);
+ }
+
+ /**
+ * Adds an alias to an existing well-known name or registers a new instance of a {@link PathMatcher}
+ * under that well-known name, unless already registered.
+ * @return a RuntimeBeanReference to this {@link PathMatcher} instance
+ * @since 3.2.17
+ */
+ public static RuntimeBeanReference registerPathMatcher(RuntimeBeanReference pathMatcherRef,
+ ParserContext parserContext, Object source) {
+
+ if (pathMatcherRef != null) {
+ if (parserContext.getRegistry().isAlias(PATH_MATCHER_BEAN_NAME)) {
+ parserContext.getRegistry().removeAlias(PATH_MATCHER_BEAN_NAME);
+ }
+ parserContext.getRegistry().registerAlias(pathMatcherRef.getBeanName(), PATH_MATCHER_BEAN_NAME);
+ }
+ else if (!parserContext.getRegistry().isAlias(PATH_MATCHER_BEAN_NAME)
+ && !parserContext.getRegistry().containsBeanDefinition(PATH_MATCHER_BEAN_NAME)) {
+ RootBeanDefinition pathMatcherDef = new RootBeanDefinition(AntPathMatcher.class);
+ pathMatcherDef.setSource(source);
+ pathMatcherDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+ parserContext.getRegistry().registerBeanDefinition(PATH_MATCHER_BEAN_NAME, pathMatcherDef);
+ parserContext.registerComponent(new BeanComponentDefinition(pathMatcherDef, PATH_MATCHER_BEAN_NAME));
+ }
+ return new RuntimeBeanReference(PATH_MATCHER_BEAN_NAME);
+ }
+
/**
* Registers an {@link HttpRequestHandlerAdapter} under a well-known
* name unless already registered.
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java
index 6bfdb9c56f..18e81969a0 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ResourcesBeanDefinitionParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 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.
@@ -22,6 +22,7 @@ import java.util.Map;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
@@ -62,10 +63,15 @@ class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
}
urlMap.put(resourceRequestPath, resourceHandlerName);
+ RuntimeBeanReference pathMatcherRef = MvcNamespaceUtils.registerPathMatcher(null, parserContext, source);
+ RuntimeBeanReference pathHelperRef = MvcNamespaceUtils.registerUrlPathHelper(null, parserContext, source);
+
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
handlerMappingDef.setSource(source);
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
handlerMappingDef.getPropertyValues().add("urlMap", urlMap);
+ handlerMappingDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
+ handlerMappingDef.getPropertyValues().add("urlPathHelper", pathHelperRef);
String order = element.getAttribute("order");
// use a default of near-lowest precedence, still allowing for even lower precedence in other mappings
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewControllerBeanDefinitionParser.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewControllerBeanDefinitionParser.java
index e580aea38b..3d077a7102 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewControllerBeanDefinitionParser.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/ViewControllerBeanDefinitionParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 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.
@@ -76,6 +76,10 @@ class ViewControllerBeanDefinitionParser implements BeanDefinitionParser {
RootBeanDefinition handlerMappingDef = new RootBeanDefinition(SimpleUrlHandlerMapping.class);
handlerMappingDef.setSource(source);
handlerMappingDef.getPropertyValues().add("order", "1");
+ handlerMappingDef.getPropertyValues().add("pathMatcher",
+ MvcNamespaceUtils.registerPathMatcher(null, parserContext, source));
+ handlerMappingDef.getPropertyValues().add("urlPathHelper",
+ MvcNamespaceUtils.registerUrlPathHelper(null, parserContext, source));
handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
parserContext.getRegistry().registerBeanDefinition(HANDLER_MAPPING_BEAN_NAME, handlerMappingDef);
parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, HANDLER_MAPPING_BEAN_NAME));
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java
index 579de783eb..46d4a1842f 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java
@@ -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.
@@ -67,6 +67,11 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
this.configurers.configureAsyncSupport(configurer);
}
+ @Override
+ public void configurePathMatch(PathMatchConfigurer configurer) {
+ this.configurers.configurePathMatch(configurer);
+ }
+
@Override
protected void addViewControllers(ViewControllerRegistry registry) {
this.configurers.addViewControllers(registry);
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/PathMatchConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/PathMatchConfigurer.java
new file mode 100644
index 0000000000..54e1160d92
--- /dev/null
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/PathMatchConfigurer.java
@@ -0,0 +1,129 @@
+/*
+ * 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.servlet.config.annotation;
+
+import org.springframework.util.PathMatcher;
+import org.springframework.web.util.UrlPathHelper;
+
+/**
+ * Helps with configuring HandlerMappings path matching options such as trailing
+ * slash match, suffix registration, path matcher and path helper.
+ *
+ *
Configured path matcher and path helper instances are shared for:
+ *
+ * - RequestMappings
+ * - ViewControllerMappings
+ * - ResourcesMappings
+ *
+ *
+ * @author Brian Clozel
+ * @since 3.2.17
+ * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
+ * @see org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
+ */
+public class PathMatchConfigurer {
+
+ private Boolean suffixPatternMatch;
+
+ private Boolean trailingSlashMatch;
+
+ private Boolean registeredSuffixPatternMatch;
+
+ private UrlPathHelper urlPathHelper;
+
+ private PathMatcher pathMatcher;
+
+
+ /**
+ * Whether to use suffix pattern match (".*") when matching patterns to
+ * requests. If enabled a method mapped to "/users" also matches to "/users.*".
+ * By default this is set to {@code true}.
+ * @see #registeredSuffixPatternMatch
+ */
+ public PathMatchConfigurer setUseSuffixPatternMatch(Boolean suffixPatternMatch) {
+ this.suffixPatternMatch = suffixPatternMatch;
+ return this;
+ }
+
+ /**
+ * Whether to match to URLs irrespective of the presence of a trailing slash.
+ * If enabled a method mapped to "/users" also matches to "/users/".
+ *
The default value is {@code true}.
+ */
+ public PathMatchConfigurer setUseTrailingSlashMatch(Boolean trailingSlashMatch) {
+ this.trailingSlashMatch = trailingSlashMatch;
+ return this;
+ }
+
+ /**
+ * Whether suffix pattern matching should work only against path extensions
+ * explicitly registered when you
+ * {@link WebMvcConfigurer#configureContentNegotiation configure content
+ * negotiation}. This is generally recommended to reduce ambiguity and to
+ * avoid issues such as when a "." appears in the path for other reasons.
+ *
By default this is set to "false".
+ * @see WebMvcConfigurer#configureContentNegotiation
+ */
+ public PathMatchConfigurer setUseRegisteredSuffixPatternMatch(
+ Boolean registeredSuffixPatternMatch) {
+
+ this.registeredSuffixPatternMatch = registeredSuffixPatternMatch;
+ return this;
+ }
+
+ /**
+ * Set the UrlPathHelper to use for resolution of lookup paths.
+ *
Use this to override the default UrlPathHelper with a custom subclass,
+ * or to share common UrlPathHelper settings across multiple HandlerMappings
+ * and MethodNameResolvers.
+ */
+ public PathMatchConfigurer setUrlPathHelper(UrlPathHelper urlPathHelper) {
+ this.urlPathHelper = urlPathHelper;
+ return this;
+ }
+
+ /**
+ * Set the PathMatcher implementation to use for matching URL paths
+ * against registered URL patterns. Default is AntPathMatcher.
+ * @see org.springframework.util.AntPathMatcher
+ */
+ public PathMatchConfigurer setPathMatcher(PathMatcher pathMatcher) {
+ this.pathMatcher = pathMatcher;
+ return this;
+ }
+
+ public Boolean isUseSuffixPatternMatch() {
+ return this.suffixPatternMatch;
+ }
+
+ public Boolean isUseTrailingSlashMatch() {
+ return this.trailingSlashMatch;
+ }
+
+ public Boolean isUseRegisteredSuffixPatternMatch() {
+ return this.registeredSuffixPatternMatch;
+ }
+
+ public UrlPathHelper getUrlPathHelper() {
+ return this.urlPathHelper;
+ }
+
+ public PathMatcher getPathMatcher() {
+ return this.pathMatcher;
+ }
+
+}
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
index 7473330449..6742aad8af 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 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.
@@ -47,7 +47,9 @@ import org.springframework.http.converter.json.MappingJacksonHttpMessageConverte
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
+import org.springframework.util.AntPathMatcher;
import org.springframework.util.ClassUtils;
+import org.springframework.util.PathMatcher;
import org.springframework.validation.Errors;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
@@ -75,6 +77,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExc
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
+import org.springframework.web.util.UrlPathHelper;
/**
* This is the main class providing the configuration behind the MVC Java config.
@@ -163,6 +166,8 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
private ContentNegotiationManager contentNegotiationManager;
+ private PathMatchConfigurer pathMatchConfigurer;
+
private List> messageConverters;
@@ -191,6 +196,24 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
handlerMapping.setOrder(0);
handlerMapping.setInterceptors(getInterceptors());
handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager());
+
+ PathMatchConfigurer configurer = getPathMatchConfigurer();
+ if (configurer.isUseSuffixPatternMatch() != null) {
+ handlerMapping.setUseSuffixPatternMatch(configurer.isUseSuffixPatternMatch());
+ }
+ if (configurer.isUseRegisteredSuffixPatternMatch() != null) {
+ handlerMapping.setUseRegisteredSuffixPatternMatch(configurer.isUseRegisteredSuffixPatternMatch());
+ }
+ if (configurer.isUseTrailingSlashMatch() != null) {
+ handlerMapping.setUseTrailingSlashMatch(configurer.isUseTrailingSlashMatch());
+ }
+ if (configurer.getPathMatcher() != null) {
+ handlerMapping.setPathMatcher(configurer.getPathMatcher());
+ }
+ if (configurer.getUrlPathHelper() != null) {
+ handlerMapping.setUrlPathHelper(configurer.getUrlPathHelper());
+ }
+
return handlerMapping;
}
@@ -259,6 +282,61 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
+ /**
+ * Callback for building the {@link PathMatchConfigurer}.
+ * Delegates to {@link #configurePathMatch}.
+ * @since 3.2.17
+ */
+ protected PathMatchConfigurer getPathMatchConfigurer() {
+ if (this.pathMatchConfigurer == null) {
+ this.pathMatchConfigurer = new PathMatchConfigurer();
+ configurePathMatch(this.pathMatchConfigurer);
+ }
+ return this.pathMatchConfigurer;
+ }
+
+ /**
+ * Override this method to configure path matching options.
+ * @see PathMatchConfigurer
+ * @since 3.2.17
+ */
+ public void configurePathMatch(PathMatchConfigurer configurer) {
+ }
+
+ /**
+ * Return a global {@link PathMatcher} instance for path matching
+ * patterns in {@link HandlerMapping}s.
+ * This instance can be configured using the {@link PathMatchConfigurer}
+ * in {@link #configurePathMatch(PathMatchConfigurer)}.
+ * @since 3.2.17
+ */
+ @Bean
+ public PathMatcher mvcPathMatcher() {
+ if (getPathMatchConfigurer().getPathMatcher() != null) {
+ return getPathMatchConfigurer().getPathMatcher();
+ }
+ else {
+ return new AntPathMatcher();
+ }
+ }
+
+ /**
+ * Return a global {@link UrlPathHelper} instance for path matching
+ * patterns in {@link HandlerMapping}s.
+ * This instance can be configured using the {@link PathMatchConfigurer}
+ * in {@link #configurePathMatch(PathMatchConfigurer)}.
+ * @since 3.2.17
+ */
+ @Bean
+ public UrlPathHelper mvcUrlPathHelper() {
+ if (getPathMatchConfigurer().getUrlPathHelper() != null) {
+ return getPathMatchConfigurer().getUrlPathHelper();
+ }
+ else {
+ return new UrlPathHelper();
+ }
+ }
+
/**
* Return a handler mapping ordered at 1 to map URL paths directly to
* view names. To configure view controllers, override
@@ -272,6 +350,8 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
handlerMapping = (handlerMapping != null ? handlerMapping : new EmptyHandlerMapping());
handlerMapping.setInterceptors(getInterceptors());
+ handlerMapping.setPathMatcher(mvcPathMatcher());
+ handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
return handlerMapping;
}
@@ -305,7 +385,13 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
addResourceHandlers(registry);
AbstractHandlerMapping handlerMapping = registry.getHandlerMapping();
- handlerMapping = (handlerMapping != null ? handlerMapping : new EmptyHandlerMapping());
+ if (handlerMapping != null) {
+ handlerMapping.setPathMatcher(mvcPathMatcher());
+ handlerMapping.setUrlPathHelper(mvcUrlPathHelper());
+ }
+ else {
+ handlerMapping = new EmptyHandlerMapping();
+ }
return handlerMapping;
}
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java
index 215d34b7da..36d720f99e 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 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.
@@ -79,6 +79,20 @@ public interface WebMvcConfigurer {
*/
void configureAsyncSupport(AsyncSupportConfigurer configurer);
+
+ /**
+ * Helps with configuring HandlerMappings path matching options such as trailing slash match,
+ * suffix registration, path matcher and path helper.
+ * Configured path matcher and path helper instances are shared for:
+ *
+ * - RequestMappings
+ * - ViewControllerMappings
+ * - ResourcesMappings
+ *
+ * @since 3.2.17
+ */
+ void configurePathMatch(PathMatchConfigurer configurer);
+
/**
* Add resolvers to support custom controller method argument types.
* This does not override the built-in support for resolving handler
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java
index 6f6c82733c..e7fd2a88b9 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 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.
@@ -71,6 +71,13 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
+ /**
+ * {@inheritDoc}
+ *
This implementation is empty.
+ */
+ public void configurePathMatch(PathMatchConfigurer configurer) {
+ }
+
/**
* {@inheritDoc}
*
This implementation is empty.
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java
index e222c3b126..2ec2a4effd 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 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.
@@ -61,6 +61,12 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer {
}
}
+ public void configurePathMatch(PathMatchConfigurer configurer) {
+ for (WebMvcConfigurer delegate : this.delegates) {
+ delegate.configurePathMatch(configurer);
+ }
+ }
+
public void configureMessageConverters(List> converters) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configureMessageConverters(converters);
diff --git a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd
index c5e0c248d9..2fab173ab6 100644
--- a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd
+++ b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-3.2.xsd
@@ -21,6 +21,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
fileExtensions = hm.getContentNegotiationManager().getAllFileExtensions();
+ assertThat(fileExtensions, Matchers.contains("xml"));
+ assertThat(fileExtensions, Matchers.hasSize(1));
+ }
+
@Test
public void testMessageConverters() {
loadBeanDefinitions("mvc-config-message-converters.xml");
@@ -198,3 +219,7 @@ class TestMessageCodesResolver implements MessageCodesResolver {
}
}
+
+class TestPathMatcher extends AntPathMatcher { }
+
+class TestPathHelper extends UrlPathHelper { }
\ No newline at end of file
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java
index 367ab9f700..a3d14b94bc 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/MvcNamespaceTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 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.
@@ -20,9 +20,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.validation.constraints.NotNull;
@@ -47,6 +49,7 @@ import org.springframework.mock.web.test.MockRequestDispatcher;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.stereotype.Controller;
+import org.springframework.util.PathMatcher;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
@@ -79,6 +82,7 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
import org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
+import org.springframework.web.util.UrlPathHelper;
import static org.junit.Assert.*;
@@ -89,6 +93,10 @@ import static org.junit.Assert.*;
*/
public class MvcNamespaceTests {
+ private static final String VIEWCONTROLLER_BEAN_NAME =
+ "org.springframework.web.servlet.config.viewControllerHandlerMapping";
+
+
private GenericWebApplicationContext appContext;
private TestController handler;
@@ -234,7 +242,7 @@ public class MvcNamespaceTests {
@Test
public void testResources() throws Exception {
- loadBeanDefinitions("mvc-config-resources.xml", 5);
+ loadBeanDefinitions("mvc-config-resources.xml", 7);
HttpRequestHandlerAdapter adapter = appContext.getBean(HttpRequestHandlerAdapter.class);
assertNotNull(adapter);
@@ -267,7 +275,7 @@ public class MvcNamespaceTests {
@Test
public void testResourcesWithOptionalAttributes() throws Exception {
- loadBeanDefinitions("mvc-config-resources-optional-attrs.xml", 5);
+ loadBeanDefinitions("mvc-config-resources-optional-attrs.xml", 7);
SimpleUrlHandlerMapping mapping = appContext.getBean(SimpleUrlHandlerMapping.class);
assertNotNull(mapping);
@@ -349,7 +357,7 @@ public class MvcNamespaceTests {
@Test
public void testViewControllers() throws Exception {
- loadBeanDefinitions("mvc-config-view-controllers.xml", 15);
+ loadBeanDefinitions("mvc-config-view-controllers.xml", 17);
RequestMappingHandlerMapping mapping = appContext.getBean(RequestMappingHandlerMapping.class);
assertNotNull(mapping);
@@ -409,7 +417,7 @@ public class MvcNamespaceTests {
/** WebSphere gives trailing servlet path slashes by default!! */
@Test
public void testViewControllersOnWebSphere() throws Exception {
- loadBeanDefinitions("mvc-config-view-controllers.xml", 15);
+ loadBeanDefinitions("mvc-config-view-controllers.xml", 17);
SimpleUrlHandlerMapping mapping2 = appContext.getBean(SimpleUrlHandlerMapping.class);
SimpleControllerHandlerAdapter adapter = appContext.getBean(SimpleControllerHandlerAdapter.class);
@@ -453,7 +461,7 @@ public class MvcNamespaceTests {
@Test
public void testViewControllersDefaultConfig() {
- loadBeanDefinitions("mvc-config-view-controllers-minimal.xml", 4);
+ loadBeanDefinitions("mvc-config-view-controllers-minimal.xml", 6);
BeanNameUrlHandlerMapping beanNameMapping = appContext.getBean(BeanNameUrlHandlerMapping.class);
assertNotNull(beanNameMapping);
@@ -492,6 +500,27 @@ public class MvcNamespaceTests {
assertEquals(1, deferredResultInterceptors.length);
}
+ @Test
+ public void testPathMatchingHandlerMappings() throws Exception {
+ loadBeanDefinitions("mvc-config-path-matching-mappings.xml", 19);
+
+ RequestMappingHandlerMapping requestMapping = appContext.getBean(RequestMappingHandlerMapping.class);
+ assertNotNull(requestMapping);
+ assertEquals(TestPathHelper.class, requestMapping.getUrlPathHelper().getClass());
+ assertEquals(TestPathMatcher.class, requestMapping.getPathMatcher().getClass());
+
+ SimpleUrlHandlerMapping viewController = appContext.getBean(VIEWCONTROLLER_BEAN_NAME, SimpleUrlHandlerMapping.class);
+ assertNotNull(viewController);
+ assertEquals(TestPathHelper.class, viewController.getUrlPathHelper().getClass());
+ assertEquals(TestPathMatcher.class, viewController.getPathMatcher().getClass());
+
+ for (SimpleUrlHandlerMapping handlerMapping : appContext.getBeansOfType(SimpleUrlHandlerMapping.class).values()) {
+ assertNotNull(handlerMapping);
+ assertEquals(TestPathHelper.class, handlerMapping.getUrlPathHelper().getClass());
+ assertEquals(TestPathMatcher.class, handlerMapping.getPathMatcher().getClass());
+ }
+ }
+
private void loadBeanDefinitions(String fileName, int expectedBeanCount) {
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(appContext);
@@ -564,4 +593,45 @@ public class MvcNamespaceTests {
public static class TestDeferredResultProcessingInterceptor extends DeferredResultProcessingInterceptorAdapter { }
+ public static class TestPathMatcher implements PathMatcher {
+
+ @Override
+ public boolean isPattern(String path) {
+ return false;
+ }
+
+ @Override
+ public boolean match(String pattern, String path) {
+ return path.matches(pattern);
+ }
+
+ @Override
+ public boolean matchStart(String pattern, String path) {
+ return false;
+ }
+
+ @Override
+ public String extractPathWithinPattern(String pattern, String path) {
+ return null;
+ }
+
+ @Override
+ public Map extractUriTemplateVariables(String pattern, String path) {
+ return null;
+ }
+
+ @Override
+ public Comparator getPatternComparator(String path) {
+ return null;
+ }
+
+ @Override
+ public String combine(String pattern1, String pattern2) {
+ return null;
+ }
+ }
+
+ public static class TestPathHelper extends UrlPathHelper {
+ }
+
}
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java
index 392cb9b979..890b310de9 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 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.
@@ -30,6 +30,7 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.util.PathMatcher;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
@@ -40,7 +41,9 @@ import org.springframework.web.servlet.handler.HandlerExceptionResolverComposite
import org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
+import org.springframework.web.util.UrlPathHelper;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
@@ -178,4 +181,30 @@ public class DelegatingWebMvcConfigurationTests {
assertEquals("Only one custom converter is expected", 1, composite.getExceptionResolvers().size());
}
+ @Test
+ public void configurePathMatch() throws Exception {
+ final PathMatcher pathMatcher = mock(PathMatcher.class);
+ final UrlPathHelper pathHelper = mock(UrlPathHelper.class);
+
+ List configurers = new ArrayList();
+ configurers.add(new WebMvcConfigurerAdapter() {
+ @Override
+ public void configurePathMatch(PathMatchConfigurer configurer) {
+ configurer.setUseRegisteredSuffixPatternMatch(true)
+ .setUseTrailingSlashMatch(false)
+ .setUrlPathHelper(pathHelper)
+ .setPathMatcher(pathMatcher);
+ }
+ });
+ delegatingConfig.setConfigurers(configurers);
+
+ RequestMappingHandlerMapping handlerMapping = delegatingConfig.requestMappingHandlerMapping();
+ assertNotNull(handlerMapping);
+ assertTrue(handlerMapping.useRegisteredSuffixPatternMatch());
+ assertTrue(handlerMapping.useSuffixPatternMatch());
+ assertFalse(handlerMapping.useTrailingSlashMatch());
+ assertSame(pathHelper, handlerMapping.getUrlPathHelper());
+ assertSame(pathMatcher, handlerMapping.getPathMatcher());
+ }
+
}
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java
index 40f10ea7e6..e5ea4a1706 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportExtensionTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2013 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.
@@ -35,6 +35,7 @@ import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
import org.springframework.stereotype.Controller;
+import org.springframework.util.AntPathMatcher;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.Errors;
@@ -62,6 +63,7 @@ import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+import org.springframework.web.util.UrlPathHelper;
/**
* A test fixture with a sub-class of {@link WebMvcConfigurationSupport} that
@@ -92,6 +94,10 @@ public class WebMvcConfigurationSupportExtensionTests {
RequestMappingHandlerMapping rmHandlerMapping = webConfig.requestMappingHandlerMapping();
rmHandlerMapping.setApplicationContext(webAppContext);
rmHandlerMapping.afterPropertiesSet();
+
+ assertEquals(TestPathHelper.class, rmHandlerMapping.getUrlPathHelper().getClass());
+ assertEquals(TestPathMatcher.class, rmHandlerMapping.getPathMatcher().getClass());
+
HandlerExecutionChain chain = rmHandlerMapping.getHandler(new MockHttpServletRequest("GET", "/"));
assertNotNull(chain.getInterceptors());
assertEquals(2, chain.getInterceptors().length);
@@ -102,6 +108,8 @@ public class WebMvcConfigurationSupportExtensionTests {
handlerMapping.setApplicationContext(webAppContext);
assertNotNull(handlerMapping);
assertEquals(1, handlerMapping.getOrder());
+ assertEquals(TestPathHelper.class, handlerMapping.getUrlPathHelper().getClass());
+ assertEquals(TestPathMatcher.class, handlerMapping.getPathMatcher().getClass());
HandlerExecutionChain handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/path"));
assertNotNull(handler.getHandler());
@@ -109,6 +117,8 @@ public class WebMvcConfigurationSupportExtensionTests {
handlerMapping.setApplicationContext(webAppContext);
assertNotNull(handlerMapping);
assertEquals(Integer.MAX_VALUE-1, handlerMapping.getOrder());
+ assertEquals(TestPathHelper.class, handlerMapping.getUrlPathHelper().getClass());
+ assertEquals(TestPathMatcher.class, handlerMapping.getPathMatcher().getClass());
handler = handlerMapping.getHandler(new MockHttpServletRequest("GET", "/resources/foo.gif"));
assertNotNull(handler.getHandler());
@@ -280,6 +290,12 @@ public class WebMvcConfigurationSupportExtensionTests {
registry.addInterceptor(new LocaleChangeInterceptor());
}
+ @Override
+ public void configurePathMatch(PathMatchConfigurer configurer) {
+ configurer.setPathMatcher(new TestPathMatcher());
+ configurer.setUrlPathHelper(new TestPathHelper());
+ }
+
@SuppressWarnings("serial")
@Override
public MessageCodesResolver getMessageCodesResolver() {
@@ -308,4 +324,8 @@ public class WebMvcConfigurationSupportExtensionTests {
}
+ private class TestPathHelper extends UrlPathHelper {}
+
+ private class TestPathMatcher extends AntPathMatcher {}
+
}
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
index 68c4460b58..bf02c6318f 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupportTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2012 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.
@@ -27,16 +27,23 @@ import javax.servlet.http.HttpServletRequest;
import org.junit.Before;
import org.junit.Test;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.stereotype.Controller;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.util.PathMatcher;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
+import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.HandlerExecutionChain;
@@ -49,6 +56,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExc
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
+import org.springframework.web.util.UrlPathHelper;
/**
* A test fixture with an {@link WebMvcConfigurationSupport} instance.
@@ -163,6 +171,32 @@ public class WebMvcConfigurationSupportTests {
assertNotNull(eher.getApplicationContext());
}
+ @Test
+ public void defaultPathMatchConfiguration() throws Exception {
+ AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
+ context.setServletContext(new MockServletContext());
+ context.register(WebConfig.class);
+ context.refresh();
+
+ UrlPathHelper urlPathHelper = context.getBean(UrlPathHelper.class);
+ PathMatcher pathMatcher = context.getBean(PathMatcher.class);
+
+ assertNotNull(urlPathHelper);
+ assertNotNull(pathMatcher);
+ assertEquals(AntPathMatcher.class, pathMatcher.getClass());
+ }
+
+
+ @EnableWebMvc
+ @Configuration
+ @SuppressWarnings("unused")
+ static class WebConfig {
+
+ @Bean
+ public TestController testController() {
+ return new TestController();
+ }
+ }
@Controller
private static class TestController {
diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching-mappings.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching-mappings.xml
new file mode 100644
index 0000000000..875672b2f4
--- /dev/null
+++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching-mappings.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching.xml b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching.xml
new file mode 100644
index 0000000000..8b27fa26f5
--- /dev/null
+++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/config/mvc-config-path-matching.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ xml=application/rss+xml
+
+
+
+
\ No newline at end of file