Browse Source

Expose path matching settings in MVC Java config

Prior to this commit, one had to provide her own
RequestMappingHandlerMapping instance (i.e extend
WebMvcConfigurationSupport and override the requestMappingHandlerMapping
method) in order to customize path matching properties on that bean.

Since SPR-10163, XML config users can do that using the
<mvc:path-matching/> XML tag. This commit adds the same feature to MVC
Java config with a PathMatchConfigurer.

Issue: SPR-11486
pull/473/merge
Brian Clozel 12 years ago
parent
commit
fc05df0f14
  1. 7
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java
  2. 117
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/PathMatchConfigurer.java
  3. 25
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java
  4. 6
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java
  5. 10
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java
  6. 9
      spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java
  7. 36
      spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java

7
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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.
@ -65,6 +65,11 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport { @@ -65,6 +65,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);

117
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/PathMatchConfigurer.java

@ -0,0 +1,117 @@ @@ -0,0 +1,117 @@
/*
* Copyright 2002-2014 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 {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping}
* path matching options such as trailing slash match, suffix registration or path matcher/helper.
*
* @author Brian Clozel
* @since 4.0.3
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
*/
public class PathMatchConfigurer {
private Boolean useSuffixPatternMatch;
private Boolean useTrailingSlashMatch;
private Boolean useRegisteredSuffixPatternMatch;
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>The default value is {@code true}.
*/
public PathMatchConfigurer setUseSuffixPatternMatch(Boolean useSuffixPatternMatch) {
this.useSuffixPatternMatch = useSuffixPatternMatch;
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 useTrailingSlashMatch) {
this.useTrailingSlashMatch = useTrailingSlashMatch;
return this;
}
/**
* Whether to use suffix pattern match for registered file extensions only
* when matching patterns to requests.
* <p>If enabled, a controller method mapped to "/users" also matches to
* "/users.json" assuming ".json" is a file extension registered with the
* provided {@link org.springframework.web.accept.ContentNegotiationManager}.</p>
* <p>The {@link org.springframework.web.accept.ContentNegotiationManager} can be customized
* using a {@link ContentNegotiationConfigurer}.</p>
* <p>If enabled, this flag also enables
* {@link #setUseSuffixPatternMatch(Boolean) useSuffixPatternMatch}. The
* default value is {@code false}.</p>
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
* @see ContentNegotiationConfigurer
*
*/
public PathMatchConfigurer setUseRegisteredSuffixPatternMatch(Boolean useRegisteredSuffixPatternMatch) {
this.useRegisteredSuffixPatternMatch = useRegisteredSuffixPatternMatch;
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 useSuffixPatternMatch;
}
public Boolean isUseTrailingSlashMatch() {
return useTrailingSlashMatch;
}
public Boolean isUseRegisteredSuffixPatternMatch() {
return useRegisteredSuffixPatternMatch;
}
public UrlPathHelper getUrlPathHelper() {
return urlPathHelper;
}
public PathMatcher getPathMatcher() {
return pathMatcher;
}
}

25
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java

@ -191,10 +191,27 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv @@ -191,10 +191,27 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
*/
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
PathMatchConfigurer configurer = new PathMatchConfigurer();
configurePathMatch(configurer);
RequestMappingHandlerMapping handlerMapping = new RequestMappingHandlerMapping();
handlerMapping.setOrder(0);
handlerMapping.setInterceptors(getInterceptors());
handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager());
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;
}
@ -563,6 +580,14 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv @@ -563,6 +580,14 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
/**
* Override this method to configure path matching options.
* @see PathMatchConfigurer
* @since 4.0.3
*/
public void configurePathMatch(PathMatchConfigurer configurer) {
}
/**
* Return an instance of {@link CompositeUriComponentsContributor} for use with
* {@link org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder}.

6
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurer.java

@ -79,6 +79,12 @@ public interface WebMvcConfigurer { @@ -79,6 +79,12 @@ public interface WebMvcConfigurer {
*/
void configureAsyncSupport(AsyncSupportConfigurer configurer);
/**
* Configure path matching options.
* @since 4.0.3
*/
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

10
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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,14 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer { @@ -76,6 +76,14 @@ public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.
*/
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
}
/**
* {@inheritDoc}
* <p>This implementation is empty.

9
spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurerComposite.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 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.
@ -64,6 +64,13 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer { @@ -64,6 +64,13 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer {
}
}
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
for (WebMvcConfigurer delegate : this.delegates) {
delegate.configurePathMatch(configurer);
}
}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
for (WebMvcConfigurer delegate : this.delegates) {

36
spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfigurationTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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; @@ -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 @@ -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,35 @@ public class DelegatingWebMvcConfigurationTests { @@ -178,4 +181,35 @@ 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);
assertEquals("PathMatchConfigurer should configure RegisteredSuffixPatternMatch",
true, handlerMapping.useRegisteredSuffixPatternMatch());
assertEquals("PathMatchConfigurer should configure SuffixPatternMatch",
true, handlerMapping.useSuffixPatternMatch());
assertEquals("PathMatchConfigurer should configure TrailingSlashMatch",
false, handlerMapping.useTrailingSlashMatch());
assertEquals("PathMatchConfigurer should configure UrlPathHelper",
pathHelper, handlerMapping.getUrlPathHelper());
assertEquals("PathMatchConfigurer should configure PathMatcher",
pathMatcher, handlerMapping.getPathMatcher());
}
}

Loading…
Cancel
Save