diff --git a/spring-web/src/main/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBean.java b/spring-web/src/main/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBean.java
index 0d4a1f7dd8..f39d1b4a2d 100644
--- a/spring-web/src/main/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBean.java
+++ b/spring-web/src/main/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBean.java
@@ -50,18 +50,18 @@ import org.springframework.web.context.ServletContextAware;
*
* {@link #ignoreAcceptHeader} |
* false |
* {@link HeaderContentNegotiationStrategy} |
@@ -123,18 +123,34 @@ public class ContentNegotiationConfigurer {
this.factory.setStrategies(strategies);
}
+ /**
+ * Whether a request parameter ("format" by default) should be used to
+ * determine the requested media type. For this option to work you must
+ * register {@link #mediaType(String, MediaType) media type mappings}.
+ * By default this is set to {@code false}.
+ * @see #parameterName(String)
+ */
+ public ContentNegotiationConfigurer favorParameter(boolean favorParameter) {
+ this.factory.setFavorParameter(favorParameter);
+ return this;
+ }
+
+ /**
+ * Set the query parameter name to use when {@link #favorParameter} is on.
+ *
The default parameter name is {@code "format"}.
+ */
+ public ContentNegotiationConfigurer parameterName(String parameterName) {
+ this.factory.setParameterName(parameterName);
+ return this;
+ }
+
/**
* Whether the path extension in the URL path should be used to determine
* the requested media type.
- *
By default this is set to {@code true} in which case a request
- * for {@code /hotels.pdf} will be interpreted as a request for
- * {@code "application/pdf"} regardless of the 'Accept' header.
- * @deprecated as of 5.2.4. See class-level note in
- * {@link ContentNegotiationManagerFactoryBean} on the deprecation of path
- * extension config options. As there is no replacement for this method,
- * for the time being it's necessary to continue using it in order to set it
- * to {@code false}. In 5.3 when {@code false} becomes the default, use of
- * this property will no longer be necessary.
+ *
By default this is set to {@code false} in which case path extensions
+ * have no impact on content negotiation.
+ * @deprecated as of 5.2.4. See deprecation note on
+ * {@link ContentNegotiationManagerFactoryBean#setFavorPathExtension(boolean)}.
*/
@Deprecated
public ContentNegotiationConfigurer favorPathExtension(boolean favorPathExtension) {
@@ -190,9 +206,8 @@ public class ContentNegotiationConfigurer {
* to any media type. Setting this to {@code false} will result in an
* {@code HttpMediaTypeNotAcceptableException} if there is no match.
*
By default this is set to {@code true}.
- * @deprecated as of 5.2.4. See class-level note in
- * {@link ContentNegotiationManagerFactoryBean} on the deprecation of path
- * extension config options.
+ * @deprecated as of 5.2.4. See deprecation note on
+ * {@link ContentNegotiationManagerFactoryBean#setIgnoreUnknownPathExtensions(boolean)}.
*/
@Deprecated
public ContentNegotiationConfigurer ignoreUnknownPathExtensions(boolean ignore) {
@@ -224,27 +239,6 @@ public class ContentNegotiationConfigurer {
return this;
}
- /**
- * Whether a request parameter ("format" by default) should be used to
- * determine the requested media type. For this option to work you must
- * register {@link #mediaType(String, MediaType) media type mappings}.
- *
By default this is set to {@code false}.
- * @see #parameterName(String)
- */
- public ContentNegotiationConfigurer favorParameter(boolean favorParameter) {
- this.factory.setFavorParameter(favorParameter);
- return this;
- }
-
- /**
- * Set the query parameter name to use when {@link #favorParameter} is on.
- *
The default parameter name is {@code "format"}.
- */
- public ContentNegotiationConfigurer parameterName(String parameterName) {
- this.factory.setParameterName(parameterName);
- return this;
- }
-
/**
* Whether to disable checking the 'Accept' request header.
*
By default this value is set to {@code false}.
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
index 0cb6889960..d07e7731f4 100644
--- 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
@@ -69,9 +69,9 @@ public class PathMatchConfigurer {
* @see #registeredSuffixPatternMatch
* @deprecated as of 5.2.4. See class-level note in
* {@link RequestMappingHandlerMapping} on the deprecation of path extension
- * config options. As there is no replacement for this method, for the time
- * being it's necessary to set it to {@code false}. In 5.3 when {@code false}
- * becomes the default, use of this property will no longer be necessary.
+ * config options. As there is no replacement for this method, in 5.2.x it is
+ * necessary to set it to {@code false}. In 5.3 {@code false} becomes the
+ * default, and use of this property is longer be necessary.
*/
@Deprecated
public PathMatchConfigurer setUseSuffixPatternMatch(Boolean suffixPatternMatch) {
@@ -150,9 +150,8 @@ public class PathMatchConfigurer {
/**
* Whether to use registered suffixes for pattern matching.
- * @deprecated as of 5.2.4. See class-level note in
- * {@link RequestMappingHandlerMapping} on the deprecation of path extension
- * config options.
+ * @deprecated as of 5.2.4, see deprecation note on
+ * {@link #setUseSuffixPatternMatch(Boolean)}.
*/
@Nullable
@Deprecated
@@ -162,9 +161,8 @@ public class PathMatchConfigurer {
/**
* Whether to use registered suffixes for pattern matching.
- * @deprecated as of 5.2.4. See class-level note in
- * {@link RequestMappingHandlerMapping} on the deprecation of path extension
- * config options.
+ * @deprecated as of 5.2.4, see deprecation note on
+ * {@link #setUseRegisteredSuffixPatternMatch(Boolean)}.
*/
@Nullable
@Deprecated
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java
index 7d72839996..58a33ed8c8 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfo.java
@@ -543,7 +543,7 @@ public final class RequestMappingInfo implements RequestConditionBy default this is set to 'true'.
+ * By default this is set to 'false'.
* @see #setRegisteredSuffixPatternMatch(boolean)
- * @deprecated as of 5.2.4. See class-level note in
- * {@link RequestMappingHandlerMapping} on the deprecation of path
- * extension config options.
+ * @deprecated as of 5.2.4. See deprecation note on
+ * {@link RequestMappingHandlerMapping#setUseSuffixPatternMatch(boolean)}.
*/
@Deprecated
public void setSuffixPatternMatch(boolean suffixPatternMatch) {
@@ -613,9 +612,8 @@ public final class RequestMappingInfo implements RequestConditionDeprecation Note:
In 5.2.4,
* {@link #setUseSuffixPatternMatch(boolean) useSuffixPatternMatch} and
* {@link #setUseRegisteredSuffixPatternMatch(boolean) useRegisteredSuffixPatternMatch}
- * are deprecated in order to discourage use of path extensions for request
+ * were deprecated in order to discourage use of path extensions for request
* mapping and for content negotiation (with similar deprecations in
* {@link ContentNegotiationManager}). For further context, please read issue
* #24719.
@@ -74,7 +74,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
implements MatchableHandlerMapping, EmbeddedValueResolverAware {
- private boolean useSuffixPatternMatch = true;
+ private boolean useSuffixPatternMatch = false;
private boolean useRegisteredSuffixPatternMatch = false;
@@ -93,14 +93,13 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
/**
* 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 {@code true}.
+ *
By default value this is set to {@code false}.
*
Also see {@link #setUseRegisteredSuffixPatternMatch(boolean)} for
* more fine-grained control over specific suffixes to allow.
- * @deprecated as of 5.2.4. See class level comment about deprecation of
+ * @deprecated as of 5.2.4. See class level note on the deprecation of
* path extension config options. As there is no replacement for this method,
- * for the time being it's necessary to set it to {@code false}. In 5.3
- * when {@code false} becomes the default, use of this property will no
- * longer be necessary.
+ * in 5.2.x it is necessary to set it to {@code false}. In 5.3 {@code false}
+ * becomes the default, and use of this property is longer be necessary.
*/
@Deprecated
public void setUseSuffixPatternMatch(boolean useSuffixPatternMatch) {
@@ -113,7 +112,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
* 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".
- * @deprecated as of 5.2.4. See class level comment about deprecation of
+ * @deprecated as of 5.2.4. See class level note on the deprecation of
* path extension config options.
*/
@Deprecated
@@ -191,8 +190,8 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
/**
* Whether to use registered suffixes for pattern matching.
- * @deprecated as of 5.2.4. See class-level note on the deprecation of path
- * extension config options.
+ * @deprecated as of 5.2.4. See deprecation notice on
+ * {@link #setUseSuffixPatternMatch(boolean)}.
*/
@Deprecated
public boolean useSuffixPatternMatch() {
@@ -201,8 +200,8 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
/**
* Whether to use registered suffixes for pattern matching.
- * @deprecated as of 5.2.4. See class-level note on the deprecation of path
- * extension config options.
+ * @deprecated as of 5.2.4. See deprecation notice on
+ * {@link #setUseRegisteredSuffixPatternMatch(boolean)}.
*/
@Deprecated
public boolean useRegisteredSuffixPatternMatch() {
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMappingTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMappingTests.java
index 3a5b7a2fce..356828e0b0 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMappingTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMappingTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 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,7 +22,6 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.security.Principal;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
@@ -72,7 +71,7 @@ public class RequestMappingHandlerMappingTests {
@Test
public void useRegisteredSuffixPatternMatch() {
- assertThat(this.handlerMapping.useSuffixPatternMatch()).isTrue();
+ assertThat(this.handlerMapping.useSuffixPatternMatch()).isFalse();
assertThat(this.handlerMapping.useRegisteredSuffixPatternMatch()).isFalse();
Map fileExtensions = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
@@ -85,7 +84,7 @@ public class RequestMappingHandlerMappingTests {
assertThat(this.handlerMapping.useSuffixPatternMatch()).isTrue();
assertThat(this.handlerMapping.useRegisteredSuffixPatternMatch()).isTrue();
- assertThat(this.handlerMapping.getFileExtensions()).isEqualTo(Arrays.asList("json"));
+ assertThat(this.handlerMapping.getFileExtensions()).isEqualTo(Collections.singletonList("json"));
}
@Test
@@ -117,9 +116,6 @@ public class RequestMappingHandlerMappingTests {
@Test
public void useSuffixPatternMatch() {
- assertThat(this.handlerMapping.useSuffixPatternMatch()).isTrue();
-
- this.handlerMapping.setUseSuffixPatternMatch(false);
assertThat(this.handlerMapping.useSuffixPatternMatch()).isFalse();
this.handlerMapping.setUseRegisteredSuffixPatternMatch(false);
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java
index cf9397a5a6..cdbdc47037 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ServletAnnotationControllerHandlerMethodTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 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.
@@ -469,22 +469,26 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test
public void adaptedHandleMethods() throws Exception {
- doTestAdaptedHandleMethods(MyAdaptedController.class);
+ initServlet(wac -> {
+ RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
+ mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
+ wac.registerBeanDefinition("handlerMapping", mappingDef);
+ }, MyAdaptedController.class);
+ doTestAdaptedHandleMethods();
}
@Test
public void adaptedHandleMethods2() throws Exception {
- doTestAdaptedHandleMethods(MyAdaptedController2.class);
+ initServletWithControllers(MyAdaptedController2.class);
}
@Test
public void adaptedHandleMethods3() throws Exception {
- doTestAdaptedHandleMethods(MyAdaptedController3.class);
+ initServletWithControllers(MyAdaptedController3.class);
+ doTestAdaptedHandleMethods();
}
- private void doTestAdaptedHandleMethods(final Class> controllerClass) throws Exception {
- initServletWithControllers(controllerClass);
-
+ private void doTestAdaptedHandleMethods() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath1.do");
MockHttpServletResponse response = new MockHttpServletResponse();
request.addParameter("param1", "value1");
@@ -727,8 +731,11 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test
public void relativePathDispatchingController() throws Exception {
- initServletWithControllers(MyRelativePathDispatchingController.class);
- getServlet().init(new MockServletConfig());
+ initServlet(wac -> {
+ RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
+ mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
+ wac.registerBeanDefinition("handlerMapping", mappingDef);
+ }, MyRelativePathDispatchingController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -753,8 +760,11 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test
public void relativeMethodPathDispatchingController() throws Exception {
- initServletWithControllers(MyRelativeMethodPathDispatchingController.class);
- getServlet().init(new MockServletConfig());
+ initServlet(wac -> {
+ RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
+ mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
+ wac.registerBeanDefinition("handlerMapping", mappingDef);
+ }, MyRelativeMethodPathDispatchingController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -1674,8 +1684,13 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test
public void responseBodyAsHtml() throws Exception {
initServlet(wac -> {
+ RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
+ mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
+ wac.registerBeanDefinition("handlerMapping", mappingDef);
+
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
factoryBean.afterPropertiesSet();
+
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
wac.registerBeanDefinition("handlerAdapter", adapterDef);
@@ -1720,8 +1735,13 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
@Test
public void responseBodyAsHtmlWithProducesCondition() throws Exception {
initServlet(wac -> {
+ RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
+ mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
+ wac.registerBeanDefinition("handlerMapping", mappingDef);
+
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
factoryBean.afterPropertiesSet();
+
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
wac.registerBeanDefinition("handlerAdapter", adapterDef);
diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletAnnotationControllerHandlerMethodTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletAnnotationControllerHandlerMethodTests.java
index ceaf509939..ca6bdcf44e 100644
--- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletAnnotationControllerHandlerMethodTests.java
+++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/UriTemplateServletAnnotationControllerHandlerMethodTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,7 +34,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.propertyeditors.CustomDateEditor;
-import org.springframework.context.ApplicationContextInitializer;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.WebDataBinder;
@@ -44,7 +43,6 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
-import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.AbstractView;
@@ -87,15 +85,11 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
pathVars.put("booking", 21);
pathVars.put("other", "other");
- WebApplicationContext wac =
- initServlet(new ApplicationContextInitializer() {
- @Override
- public void initialize(GenericWebApplicationContext context) {
- RootBeanDefinition beanDef = new RootBeanDefinition(ModelValidatingViewResolver.class);
- beanDef.getConstructorArgumentValues().addGenericArgumentValue(pathVars);
- context.registerBeanDefinition("viewResolver", beanDef);
- }
- }, ViewRenderingController.class);
+ WebApplicationContext wac = initServlet(context -> {
+ RootBeanDefinition beanDef = new RootBeanDefinition(ModelValidatingViewResolver.class);
+ beanDef.getConstructorArgumentValues().addGenericArgumentValue(pathVars);
+ context.registerBeanDefinition("viewResolver", beanDef);
+ }, ViewRenderingController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42;q=1,2/bookings/21-other;q=3;r=R");
getServlet().service(request, new MockHttpServletResponse());
@@ -143,22 +137,21 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertThat(response.getContentAsString()).isEqualTo("test-42-21");
-
- request = new MockHttpServletRequest("GET", "/hotels/42/bookings/21.html");
- response = new MockHttpServletResponse();
- getServlet().service(request, response);
- assertThat(response.getContentAsString()).isEqualTo("test-42-21");
}
@Test
public void extension() throws Exception {
- initServletWithControllers(SimpleUriTemplateController.class);
+ initServlet(wac -> {
+ RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
+ mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
+ mappingDef.getPropertyValues().add("removeSemicolonContent", "false");
+ wac.registerBeanDefinition("handlerMapping", mappingDef);
+ }, SimpleUriTemplateController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42;jsessionid=c0o7fszeb1;q=24.xml");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertThat(response.getContentAsString()).isEqualTo("test-42-24");
-
}
@Test
@@ -264,11 +257,6 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertThat(response.getContentAsString()).isEqualTo("handle4-page-5");
-
- request = new MockHttpServletRequest("GET", "/category/page/5.html");
- response = new MockHttpServletResponse();
- getServlet().service(request, response);
- assertThat(response.getContentAsString()).isEqualTo("handle4-page-5");
}
@Test
@@ -282,10 +270,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
assertThat(response.getContentAsString()).isEqualTo("test-42-;q=1;q=2-[1, 2]");
}
- /*
- * See SPR-6640
- */
- @Test
+ @Test // gh-11306
public void menuTree() throws Exception {
initServletWithControllers(MenuTreeController.class);
@@ -295,10 +280,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
assertThat(response.getContentAsString()).isEqualTo("M5");
}
- /*
- * See SPR-6876
- */
- @Test
+ @Test // gh-11542
public void variableNames() throws Exception {
initServletWithControllers(VariableNamesController.class);
@@ -313,12 +295,13 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
assertThat(response.getContentAsString()).isEqualTo("bar-bar");
}
- /*
- * See SPR-8543
- */
- @Test
+ @Test // gh-13187
public void variableNamesWithUrlExtension() throws Exception {
- initServletWithControllers(VariableNamesController.class);
+ initServlet(wac -> {
+ RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
+ mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
+ wac.registerBeanDefinition("handlerMapping", mappingDef);
+ }, VariableNamesController.class);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo.json");
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -326,10 +309,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
assertThat(response.getContentAsString()).isEqualTo("foo-foo");
}
- /*
- * See SPR-6978
- */
- @Test
+ @Test // gh-11643
public void doIt() throws Exception {
initServletWithControllers(Spr6978Controller.class);
diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc
index 0a75908144..155fe55074 100644
--- a/src/docs/asciidoc/web/webmvc.adoc
+++ b/src/docs/asciidoc/web/webmvc.adoc
@@ -1683,11 +1683,11 @@ See <> in the configuration section.
[[mvc-ann-requestmapping-suffix-pattern-match]]
==== Suffix Match
-By default, Spring MVC performs `.{asterisk}` suffix pattern matching so that a
-controller mapped to `/person` is also implicitly mapped to `/person.{asterisk}`.
-The file extension is then used to interpret the requested content type to use for
-the response (that is, instead of the `Accept` header) -- for example, `/person.pdf`,
-`/person.xml`, and others.
+Starting in 5.3, by default Spring MVC no longer performs `.{asterisk}` suffix pattern
+matching where a controller mapped to `/person` is also implicitly mapped to
+`/person.{asterisk}`. As a consequence path extensions are no longer used to interpret
+the requested content type for the response -- for example, `/person.pdf`, `/person.xml`,
+and so on.
Using file extensions in this way was necessary when browsers used to send `Accept` headers
that were hard to interpret consistently. At present, that is no longer a necessity and
@@ -1698,28 +1698,16 @@ It can cause ambiguity when overlain with the use of URI variables, path paramet
URI encoding. Reasoning about URL-based authorization
and security (see next section for more details) also become more difficult.
-To completely disable the use of file extensions, you must set both of the following:
+To completely disable the use of path extensions in versions prior to 5.3, set the following:
* `useSuffixPatternMatching(false)`, see <>
* `favorPathExtension(false)`, see <>
-URL-based content negotiation can still be useful (for example, when typing a URL in a
-browser). To enable that, we recommend a query parameter-based strategy to avoid most of
-the issues that come with file extensions. Alternatively, if you must use file extensions, consider
-restricting them to a list of explicitly registered extensions through the
-`mediaTypes` property of <>.
-
-[NOTE]
-====
-Starting in 5.2.4, path extension related options for request mapping in
-{api-spring-framework}/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java[RequestMappingHandlerMapping]
-and for content negotiation in
-{api-spring-framework}/org.springframework.web.accept/ContentNegotiationManagerFactoryBean.java[ContentNegotiationManagerFactoryBean]
-are deprecated. See Spring Framework issue
-https://github.com/spring-projects/spring-framework/issues/24179[#24179] and related
-issues for further plans.
-====
-
+Having a way to request content types other than through the `"Accept"` header can still
+be useful, e.g. when typing a URL in a browser. A safe alternative to path extensions is
+to use the query parameter strategy. If you must use file extensions, consider restricting
+them to a list of explicitly registered extensions through the `mediaTypes` property of
+<>.
[[mvc-ann-requestmapping-rfd]]
@@ -5851,7 +5839,6 @@ The following example shows how to customize path matching in Java configuration
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer
.setUseTrailingSlashMatch(false)
- .setUseRegisteredSuffixPatternMatch(true)
.setPathMatcher(antPathMatcher())
.setUrlPathHelper(urlPathHelper())
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class));
@@ -5879,7 +5866,6 @@ The following example shows how to customize path matching in Java configuration
configurer
.setUseSuffixPatternMatch(true)
.setUseTrailingSlashMatch(false)
- .setUseRegisteredSuffixPatternMatch(true)
.setPathMatcher(antPathMatcher())
.setUrlPathHelper(urlPathHelper())
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
@@ -5904,7 +5890,6 @@ The following example shows how to achieve the same configuration in XML: