Backport MVC Java config path-related config options
Issue: SPR-14186
This commit is contained in:
parent
3d6b0ca5be
commit
cf39078fbb
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <p>Configured path matcher and path helper instances are shared for:
|
||||
* <ul>
|
||||
* <li>RequestMappings</li>
|
||||
* <li>ViewControllerMappings</li>
|
||||
* <li>ResourcesMappings</li>
|
||||
* </ul>
|
||||
*
|
||||
* @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.*".
|
||||
* <p>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/".
|
||||
* <p>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.
|
||||
* <p>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.
|
||||
* <p>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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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<HttpMessageConverter<?>> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
* <ul>
|
||||
* <li>RequestMappings</li>
|
||||
* <li>ViewControllerMappings</li>
|
||||
* <li>ResourcesMappings</li>
|
||||
* </ul>
|
||||
* @since 3.2.17
|
||||
*/
|
||||
void configurePathMatch(PathMatchConfigurer configurer);
|
||||
|
||||
/**
|
||||
* Add resolvers to support custom controller method argument types.
|
||||
* <p>This does not override the built-in support for resolving handler
|
||||
|
|
|
@ -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}
|
||||
* <p>This implementation is empty.
|
||||
*/
|
||||
public void configurePathMatch(PathMatchConfigurer configurer) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation is empty.
|
||||
|
|
|
@ -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<HttpMessageConverter<?>> converters) {
|
||||
for (WebMvcConfigurer delegate : this.delegates) {
|
||||
delegate.configureMessageConverters(converters);
|
||||
|
|
|
@ -21,6 +21,62 @@
|
|||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:all minOccurs="0">
|
||||
<xsd:element name="path-matching" minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Configures the path matching part of the Spring MVC Controller programming model.
|
||||
Like annotation-driven, code-based alternatives are also documented in EnableWebMvc javadoc.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="suffix-pattern" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Whether to use suffix pattern match (".*") when matching patterns to requests. If enabled
|
||||
a method mapped to "/users" also matches to "/users.*".
|
||||
The default value is true.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="trailing-slash" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
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 true.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="registered-suffixes-only" type="xsd:boolean">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Whether suffix pattern matching should work only against path extensions
|
||||
explicitly registered when you 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.
|
||||
The default value is false.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="path-helper" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The bean name of 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.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="path-matcher" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The bean name of the PathMatcher implementation to use for matching URL paths against registered URL patterns.
|
||||
Default is AntPathMatcher.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="message-converters" minOccurs="0">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
|
|
|
@ -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.
|
||||
|
@ -16,11 +16,14 @@
|
|||
package org.springframework.web.servlet.config;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
|
@ -30,6 +33,7 @@ import org.springframework.core.io.ClassPathResource;
|
|||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.ResourceHttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.validation.MessageCodesResolver;
|
||||
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
|
||||
import org.springframework.web.bind.support.WebArgumentResolver;
|
||||
|
@ -42,7 +46,9 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
|||
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ServletWebArgumentResolverAdapter;
|
||||
import org.springframework.web.util.UrlPathHelper;
|
||||
|
||||
/**
|
||||
* Test fixture for the configuration in mvc-config-annotation-driven.xml.
|
||||
|
@ -70,6 +76,21 @@ public class AnnotationDrivenBeanDefinitionParserTests {
|
|||
assertEquals(false, new DirectFieldAccessor(adapter).getPropertyValue("ignoreDefaultModelOnRedirect"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathMatchingConfiguration() {
|
||||
loadBeanDefinitions("mvc-config-path-matching.xml");
|
||||
RequestMappingHandlerMapping hm = this.appContext.getBean(RequestMappingHandlerMapping.class);
|
||||
assertNotNull(hm);
|
||||
assertTrue(hm.useSuffixPatternMatch());
|
||||
assertFalse(hm.useTrailingSlashMatch());
|
||||
assertTrue(hm.useRegisteredSuffixPatternMatch());
|
||||
assertThat(hm.getUrlPathHelper(), Matchers.instanceOf(TestPathHelper.class));
|
||||
assertThat(hm.getPathMatcher(), Matchers.instanceOf(TestPathMatcher.class));
|
||||
List<String> 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 { }
|
|
@ -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<String, String> extractUriTemplateVariables(String pattern, String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator<String> getPatternComparator(String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String combine(String pattern1, String pattern2) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestPathHelper extends UrlPathHelper {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<WebMvcConfigurer> configurers = new ArrayList<WebMvcConfigurer>();
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
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
|
||||
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/" />
|
||||
|
||||
<mvc:annotation-driven>
|
||||
<mvc:path-matching
|
||||
path-helper="pathHelper"
|
||||
path-matcher="pathMatcher" />
|
||||
</mvc:annotation-driven>
|
||||
|
||||
<mvc:view-controller path="/" view-name="home"/>
|
||||
<mvc:view-controller path="/test" view-name="test"/>
|
||||
|
||||
<bean id="pathMatcher" class="org.springframework.web.servlet.config.MvcNamespaceTests$TestPathMatcher" />
|
||||
<bean id="pathHelper" class="org.springframework.web.servlet.config.MvcNamespaceTests$TestPathHelper" />
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
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
|
||||
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
|
||||
<mvc:path-matching
|
||||
suffix-pattern="true"
|
||||
trailing-slash="false"
|
||||
registered-suffixes-only="true"
|
||||
path-helper="pathHelper"
|
||||
path-matcher="pathMatcher" />
|
||||
</mvc:annotation-driven>
|
||||
|
||||
<bean id="pathMatcher" class="org.springframework.web.servlet.config.TestPathMatcher" />
|
||||
<bean id="pathHelper" class="org.springframework.web.servlet.config.TestPathHelper" />
|
||||
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
|
||||
<property name="mediaTypes">
|
||||
<value>
|
||||
xml=application/rss+xml
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
</beans>
|
Loading…
Reference in New Issue