Turn off use of path extensions by default
Closes gh-23915
This commit is contained in:
parent
153690e717
commit
147b8fb755
|
@ -50,18 +50,18 @@ import org.springframework.web.context.ServletContextAware;
|
||||||
* <th>Enabled Or Not</th>
|
* <th>Enabled Or Not</th>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td>{@link #setFavorPathExtension favorPathExtension}</td>
|
|
||||||
* <td>true</td>
|
|
||||||
* <td>{@link PathExtensionContentNegotiationStrategy}</td>
|
|
||||||
* <td>Enabled</td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>{@link #setFavorParameter favorParameter}</td>
|
* <td>{@link #setFavorParameter favorParameter}</td>
|
||||||
* <td>false</td>
|
* <td>false</td>
|
||||||
* <td>{@link ParameterContentNegotiationStrategy}</td>
|
* <td>{@link ParameterContentNegotiationStrategy}</td>
|
||||||
* <td>Off</td>
|
* <td>Off</td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
|
* <td>{@link #setFavorPathExtension favorPathExtension}</td>
|
||||||
|
* <td>false (as of 5.3)</td>
|
||||||
|
* <td>{@link PathExtensionContentNegotiationStrategy}</td>
|
||||||
|
* <td>Off</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
* <td>{@link #setIgnoreAcceptHeader ignoreAcceptHeader}</td>
|
* <td>{@link #setIgnoreAcceptHeader ignoreAcceptHeader}</td>
|
||||||
* <td>false</td>
|
* <td>false</td>
|
||||||
* <td>{@link HeaderContentNegotiationStrategy}</td>
|
* <td>{@link HeaderContentNegotiationStrategy}</td>
|
||||||
|
@ -104,11 +104,11 @@ public class ContentNegotiationManagerFactoryBean
|
||||||
private List<ContentNegotiationStrategy> strategies;
|
private List<ContentNegotiationStrategy> strategies;
|
||||||
|
|
||||||
|
|
||||||
private boolean favorPathExtension = true;
|
|
||||||
|
|
||||||
private boolean favorParameter = false;
|
private boolean favorParameter = false;
|
||||||
|
|
||||||
private boolean ignoreAcceptHeader = false;
|
private String parameterName = "format";
|
||||||
|
|
||||||
|
private boolean favorPathExtension = true;
|
||||||
|
|
||||||
private Map<String, MediaType> mediaTypes = new HashMap<>();
|
private Map<String, MediaType> mediaTypes = new HashMap<>();
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ public class ContentNegotiationManagerFactoryBean
|
||||||
@Nullable
|
@Nullable
|
||||||
private Boolean useRegisteredExtensionsOnly;
|
private Boolean useRegisteredExtensionsOnly;
|
||||||
|
|
||||||
private String parameterName = "format";
|
private boolean ignoreAcceptHeader = false;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private ContentNegotiationStrategy defaultNegotiationStrategy;
|
private ContentNegotiationStrategy defaultNegotiationStrategy;
|
||||||
|
@ -141,17 +141,35 @@ public class ContentNegotiationManagerFactoryBean
|
||||||
this.strategies = (strategies != null ? new ArrayList<>(strategies) : null);
|
this.strategies = (strategies != null ? new ArrayList<>(strategies) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 #setMediaTypes media type mappings}.
|
||||||
|
* <p>By default this is set to {@code false}.
|
||||||
|
* @see #setParameterName
|
||||||
|
*/
|
||||||
|
public void setFavorParameter(boolean favorParameter) {
|
||||||
|
this.favorParameter = favorParameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the query parameter name to use when {@link #setFavorParameter} is on.
|
||||||
|
* <p>The default parameter name is {@code "format"}.
|
||||||
|
*/
|
||||||
|
public void setParameterName(String parameterName) {
|
||||||
|
Assert.notNull(parameterName, "parameterName is required");
|
||||||
|
this.parameterName = parameterName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the path extension in the URL path should be used to determine
|
* Whether the path extension in the URL path should be used to determine
|
||||||
* the requested media type.
|
* the requested media type.
|
||||||
* <p>By default this is set to {@code true} in which case a request
|
* <p>By default this is set to {@code false} in which case path extensions
|
||||||
* for {@code /hotels.pdf} will be interpreted as a request for
|
* have no impact on content negotiation.
|
||||||
* {@code "application/pdf"} regardless of the 'Accept' header.
|
|
||||||
* @deprecated as of 5.2.4. See class-level note on the deprecation of path
|
* @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,
|
* 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
|
* in 5.2.x it is necessary to set it to {@code false}. In 5.3 {@code false}
|
||||||
* to {@code false}. In 5.3 when {@code false} becomes the default, use of
|
* becomes the default, and use of this property is longer be necessary.
|
||||||
* this property will no longer be necessary.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setFavorPathExtension(boolean favorPathExtension) {
|
public void setFavorPathExtension(boolean favorPathExtension) {
|
||||||
|
@ -224,8 +242,8 @@ public class ContentNegotiationManagerFactoryBean
|
||||||
/**
|
/**
|
||||||
* Indicate whether to use the Java Activation Framework as a fallback option
|
* Indicate whether to use the Java Activation Framework as a fallback option
|
||||||
* to map from file extensions to media types.
|
* to map from file extensions to media types.
|
||||||
* @deprecated as of 5.0, in favor of {@link #setUseRegisteredExtensionsOnly(boolean)}, which
|
* @deprecated as of 5.0, in favor of {@link #setUseRegisteredExtensionsOnly(boolean)},
|
||||||
* has reverse behavior.
|
* which has reverse behavior.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setUseJaf(boolean useJaf) {
|
public void setUseJaf(boolean useJaf) {
|
||||||
|
@ -247,26 +265,6 @@ public class ContentNegotiationManagerFactoryBean
|
||||||
return (this.useRegisteredExtensionsOnly != null && this.useRegisteredExtensionsOnly);
|
return (this.useRegisteredExtensionsOnly != null && this.useRegisteredExtensionsOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 #setMediaTypes media type mappings}.
|
|
||||||
* <p>By default this is set to {@code false}.
|
|
||||||
* @see #setParameterName
|
|
||||||
*/
|
|
||||||
public void setFavorParameter(boolean favorParameter) {
|
|
||||||
this.favorParameter = favorParameter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the query parameter name to use when {@link #setFavorParameter} is on.
|
|
||||||
* <p>The default parameter name is {@code "format"}.
|
|
||||||
*/
|
|
||||||
public void setParameterName(String parameterName) {
|
|
||||||
Assert.notNull(parameterName, "parameterName is required");
|
|
||||||
this.parameterName = parameterName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to disable checking the 'Accept' request header.
|
* Whether to disable checking the 'Accept' request header.
|
||||||
* <p>By default this value is set to {@code false}.
|
* <p>By default this value is set to {@code false}.
|
||||||
|
|
|
@ -49,19 +49,19 @@ import org.springframework.web.accept.ParameterContentNegotiationStrategy;
|
||||||
* <th>Enabled Or Not</th>
|
* <th>Enabled Or Not</th>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
* <td>{@link #favorPathExtension}</td>
|
|
||||||
* <td>true</td>
|
|
||||||
* <td>{@link org.springframework.web.accept.PathExtensionContentNegotiationStrategy
|
|
||||||
* PathExtensionContentNegotiationStrategy}</td>
|
|
||||||
* <td>Enabled</td>
|
|
||||||
* </tr>
|
|
||||||
* <tr>
|
|
||||||
* <td>{@link #favorParameter}</td>
|
* <td>{@link #favorParameter}</td>
|
||||||
* <td>false</td>
|
* <td>false</td>
|
||||||
* <td>{@link ParameterContentNegotiationStrategy}</td>
|
* <td>{@link ParameterContentNegotiationStrategy}</td>
|
||||||
* <td>Off</td>
|
* <td>Off</td>
|
||||||
* </tr>
|
* </tr>
|
||||||
* <tr>
|
* <tr>
|
||||||
|
* <td>{@link #favorPathExtension}</td>
|
||||||
|
* <td>false (as of 5.3)</td>
|
||||||
|
* <td>{@link org.springframework.web.accept.PathExtensionContentNegotiationStrategy
|
||||||
|
* PathExtensionContentNegotiationStrategy}</td>
|
||||||
|
* <td>Off</td>
|
||||||
|
* </tr>
|
||||||
|
* <tr>
|
||||||
* <td>{@link #ignoreAcceptHeader}</td>
|
* <td>{@link #ignoreAcceptHeader}</td>
|
||||||
* <td>false</td>
|
* <td>false</td>
|
||||||
* <td>{@link HeaderContentNegotiationStrategy}</td>
|
* <td>{@link HeaderContentNegotiationStrategy}</td>
|
||||||
|
@ -123,18 +123,34 @@ public class ContentNegotiationConfigurer {
|
||||||
this.factory.setStrategies(strategies);
|
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}.
|
||||||
|
* <p>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.
|
||||||
|
* <p>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
|
* Whether the path extension in the URL path should be used to determine
|
||||||
* the requested media type.
|
* the requested media type.
|
||||||
* <p>By default this is set to {@code true} in which case a request
|
* <p>By default this is set to {@code false} in which case path extensions
|
||||||
* for {@code /hotels.pdf} will be interpreted as a request for
|
* have no impact on content negotiation.
|
||||||
* {@code "application/pdf"} regardless of the 'Accept' header.
|
* @deprecated as of 5.2.4. See deprecation note on
|
||||||
* @deprecated as of 5.2.4. See class-level note in
|
* {@link ContentNegotiationManagerFactoryBean#setFavorPathExtension(boolean)}.
|
||||||
* {@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.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ContentNegotiationConfigurer favorPathExtension(boolean favorPathExtension) {
|
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
|
* to any media type. Setting this to {@code false} will result in an
|
||||||
* {@code HttpMediaTypeNotAcceptableException} if there is no match.
|
* {@code HttpMediaTypeNotAcceptableException} if there is no match.
|
||||||
* <p>By default this is set to {@code true}.
|
* <p>By default this is set to {@code true}.
|
||||||
* @deprecated as of 5.2.4. See class-level note in
|
* @deprecated as of 5.2.4. See deprecation note on
|
||||||
* {@link ContentNegotiationManagerFactoryBean} on the deprecation of path
|
* {@link ContentNegotiationManagerFactoryBean#setIgnoreUnknownPathExtensions(boolean)}.
|
||||||
* extension config options.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ContentNegotiationConfigurer ignoreUnknownPathExtensions(boolean ignore) {
|
public ContentNegotiationConfigurer ignoreUnknownPathExtensions(boolean ignore) {
|
||||||
|
@ -224,27 +239,6 @@ public class ContentNegotiationConfigurer {
|
||||||
return this;
|
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}.
|
|
||||||
* <p>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.
|
|
||||||
* <p>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.
|
* Whether to disable checking the 'Accept' request header.
|
||||||
* <p>By default this value is set to {@code false}.
|
* <p>By default this value is set to {@code false}.
|
||||||
|
|
|
@ -69,9 +69,9 @@ public class PathMatchConfigurer {
|
||||||
* @see #registeredSuffixPatternMatch
|
* @see #registeredSuffixPatternMatch
|
||||||
* @deprecated as of 5.2.4. See class-level note in
|
* @deprecated as of 5.2.4. See class-level note in
|
||||||
* {@link RequestMappingHandlerMapping} on the deprecation of path extension
|
* {@link RequestMappingHandlerMapping} on the deprecation of path extension
|
||||||
* config options. As there is no replacement for this method, for the time
|
* config options. As there is no replacement for this method, in 5.2.x it is
|
||||||
* being it's necessary to set it to {@code false}. In 5.3 when {@code false}
|
* necessary to set it to {@code false}. In 5.3 {@code false} becomes the
|
||||||
* becomes the default, use of this property will no longer be necessary.
|
* default, and use of this property is longer be necessary.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public PathMatchConfigurer setUseSuffixPatternMatch(Boolean suffixPatternMatch) {
|
public PathMatchConfigurer setUseSuffixPatternMatch(Boolean suffixPatternMatch) {
|
||||||
|
@ -150,9 +150,8 @@ public class PathMatchConfigurer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to use registered suffixes for pattern matching.
|
* Whether to use registered suffixes for pattern matching.
|
||||||
* @deprecated as of 5.2.4. See class-level note in
|
* @deprecated as of 5.2.4, see deprecation note on
|
||||||
* {@link RequestMappingHandlerMapping} on the deprecation of path extension
|
* {@link #setUseSuffixPatternMatch(Boolean)}.
|
||||||
* config options.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -162,9 +161,8 @@ public class PathMatchConfigurer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to use registered suffixes for pattern matching.
|
* Whether to use registered suffixes for pattern matching.
|
||||||
* @deprecated as of 5.2.4. See class-level note in
|
* @deprecated as of 5.2.4, see deprecation note on
|
||||||
* {@link RequestMappingHandlerMapping} on the deprecation of path extension
|
* {@link #setUseRegisteredSuffixPatternMatch(Boolean)}.
|
||||||
* config options.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|
|
@ -543,7 +543,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||||
|
|
||||||
private boolean trailingSlashMatch = true;
|
private boolean trailingSlashMatch = true;
|
||||||
|
|
||||||
private boolean suffixPatternMatch = true;
|
private boolean suffixPatternMatch = false;
|
||||||
|
|
||||||
private boolean registeredSuffixPatternMatch = false;
|
private boolean registeredSuffixPatternMatch = false;
|
||||||
|
|
||||||
|
@ -600,11 +600,10 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether to apply suffix pattern matching in PatternsRequestCondition.
|
* Set whether to apply suffix pattern matching in PatternsRequestCondition.
|
||||||
* <p>By default this is set to 'true'.
|
* <p>By default this is set to 'false'.
|
||||||
* @see #setRegisteredSuffixPatternMatch(boolean)
|
* @see #setRegisteredSuffixPatternMatch(boolean)
|
||||||
* @deprecated as of 5.2.4. See class-level note in
|
* @deprecated as of 5.2.4. See deprecation note on
|
||||||
* {@link RequestMappingHandlerMapping} on the deprecation of path
|
* {@link RequestMappingHandlerMapping#setUseSuffixPatternMatch(boolean)}.
|
||||||
* extension config options.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setSuffixPatternMatch(boolean suffixPatternMatch) {
|
public void setSuffixPatternMatch(boolean suffixPatternMatch) {
|
||||||
|
@ -613,9 +612,8 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether to apply suffix pattern matching in PatternsRequestCondition.
|
* Return whether to apply suffix pattern matching in PatternsRequestCondition.
|
||||||
* @deprecated as of 5.2.4. See class-level note in
|
* @deprecated as of 5.2.4. See deprecation note on
|
||||||
* {@link RequestMappingHandlerMapping} on the deprecation of path
|
* {@link RequestMappingHandlerMapping#setUseSuffixPatternMatch(boolean)}.
|
||||||
* extension config options.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean useSuffixPatternMatch() {
|
public boolean useSuffixPatternMatch() {
|
||||||
|
@ -630,8 +628,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||||
* obtain the registered file extensions.
|
* obtain the registered file extensions.
|
||||||
* @deprecated as of 5.2.4. See class-level note in
|
* @deprecated as of 5.2.4. See class-level note in
|
||||||
* {@link RequestMappingHandlerMapping} on the deprecation of path
|
* {@link RequestMappingHandlerMapping} on the deprecation of path
|
||||||
* extension config options; note also that in 5.3 the default for this
|
* extension config options.
|
||||||
* property switches from {@code false} to {@code true}.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setRegisteredSuffixPatternMatch(boolean registeredSuffixPatternMatch) {
|
public void setRegisteredSuffixPatternMatch(boolean registeredSuffixPatternMatch) {
|
||||||
|
|
|
@ -61,7 +61,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi
|
||||||
* <p><strong>Deprecation Note:</strong></p> In 5.2.4,
|
* <p><strong>Deprecation Note:</strong></p> In 5.2.4,
|
||||||
* {@link #setUseSuffixPatternMatch(boolean) useSuffixPatternMatch} and
|
* {@link #setUseSuffixPatternMatch(boolean) useSuffixPatternMatch} and
|
||||||
* {@link #setUseRegisteredSuffixPatternMatch(boolean) useRegisteredSuffixPatternMatch}
|
* {@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
|
* mapping and for content negotiation (with similar deprecations in
|
||||||
* {@link ContentNegotiationManager}). For further context, please read issue
|
* {@link ContentNegotiationManager}). For further context, please read issue
|
||||||
* <a href="https://github.com/spring-projects/spring-framework/issues/24179">#24719</a>.
|
* <a href="https://github.com/spring-projects/spring-framework/issues/24179">#24719</a>.
|
||||||
|
@ -74,7 +74,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi
|
||||||
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
|
public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping
|
||||||
implements MatchableHandlerMapping, EmbeddedValueResolverAware {
|
implements MatchableHandlerMapping, EmbeddedValueResolverAware {
|
||||||
|
|
||||||
private boolean useSuffixPatternMatch = true;
|
private boolean useSuffixPatternMatch = false;
|
||||||
|
|
||||||
private boolean useRegisteredSuffixPatternMatch = false;
|
private boolean useRegisteredSuffixPatternMatch = false;
|
||||||
|
|
||||||
|
@ -93,14 +93,13 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||||
/**
|
/**
|
||||||
* Whether to use suffix pattern match (".*") when matching patterns to
|
* Whether to use suffix pattern match (".*") when matching patterns to
|
||||||
* requests. If enabled a method mapped to "/users" also matches to "/users.*".
|
* requests. If enabled a method mapped to "/users" also matches to "/users.*".
|
||||||
* <p>The default value is {@code true}.
|
* <p>By default value this is set to {@code false}.
|
||||||
* <p>Also see {@link #setUseRegisteredSuffixPatternMatch(boolean)} for
|
* <p>Also see {@link #setUseRegisteredSuffixPatternMatch(boolean)} for
|
||||||
* more fine-grained control over specific suffixes to allow.
|
* 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,
|
* 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
|
* in 5.2.x it is necessary to set it to {@code false}. In 5.3 {@code false}
|
||||||
* when {@code false} becomes the default, use of this property will no
|
* becomes the default, and use of this property is longer be necessary.
|
||||||
* longer be necessary.
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setUseSuffixPatternMatch(boolean useSuffixPatternMatch) {
|
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
|
* is generally recommended to reduce ambiguity and to avoid issues such as
|
||||||
* when a "." appears in the path for other reasons.
|
* when a "." appears in the path for other reasons.
|
||||||
* <p>By default this is set to "false".
|
* <p>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.
|
* path extension config options.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -191,8 +190,8 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to use registered suffixes for pattern matching.
|
* Whether to use registered suffixes for pattern matching.
|
||||||
* @deprecated as of 5.2.4. See class-level note on the deprecation of path
|
* @deprecated as of 5.2.4. See deprecation notice on
|
||||||
* extension config options.
|
* {@link #setUseSuffixPatternMatch(boolean)}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean useSuffixPatternMatch() {
|
public boolean useSuffixPatternMatch() {
|
||||||
|
@ -201,8 +200,8 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to use registered suffixes for pattern matching.
|
* Whether to use registered suffixes for pattern matching.
|
||||||
* @deprecated as of 5.2.4. See class-level note on the deprecation of path
|
* @deprecated as of 5.2.4. See deprecation notice on
|
||||||
* extension config options.
|
* {@link #setUseRegisteredSuffixPatternMatch(boolean)}.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean useRegisteredSuffixPatternMatch() {
|
public boolean useRegisteredSuffixPatternMatch() {
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.annotation.Target;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -72,7 +71,7 @@ public class RequestMappingHandlerMappingTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void useRegisteredSuffixPatternMatch() {
|
public void useRegisteredSuffixPatternMatch() {
|
||||||
assertThat(this.handlerMapping.useSuffixPatternMatch()).isTrue();
|
assertThat(this.handlerMapping.useSuffixPatternMatch()).isFalse();
|
||||||
assertThat(this.handlerMapping.useRegisteredSuffixPatternMatch()).isFalse();
|
assertThat(this.handlerMapping.useRegisteredSuffixPatternMatch()).isFalse();
|
||||||
|
|
||||||
Map<String, MediaType> fileExtensions = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
|
Map<String, MediaType> fileExtensions = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
|
||||||
|
@ -85,7 +84,7 @@ public class RequestMappingHandlerMappingTests {
|
||||||
|
|
||||||
assertThat(this.handlerMapping.useSuffixPatternMatch()).isTrue();
|
assertThat(this.handlerMapping.useSuffixPatternMatch()).isTrue();
|
||||||
assertThat(this.handlerMapping.useRegisteredSuffixPatternMatch()).isTrue();
|
assertThat(this.handlerMapping.useRegisteredSuffixPatternMatch()).isTrue();
|
||||||
assertThat(this.handlerMapping.getFileExtensions()).isEqualTo(Arrays.asList("json"));
|
assertThat(this.handlerMapping.getFileExtensions()).isEqualTo(Collections.singletonList("json"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -117,9 +116,6 @@ public class RequestMappingHandlerMappingTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void useSuffixPatternMatch() {
|
public void useSuffixPatternMatch() {
|
||||||
assertThat(this.handlerMapping.useSuffixPatternMatch()).isTrue();
|
|
||||||
|
|
||||||
this.handlerMapping.setUseSuffixPatternMatch(false);
|
|
||||||
assertThat(this.handlerMapping.useSuffixPatternMatch()).isFalse();
|
assertThat(this.handlerMapping.useSuffixPatternMatch()).isFalse();
|
||||||
|
|
||||||
this.handlerMapping.setUseRegisteredSuffixPatternMatch(false);
|
this.handlerMapping.setUseRegisteredSuffixPatternMatch(false);
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -469,22 +469,26 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void adaptedHandleMethods() throws Exception {
|
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
|
@Test
|
||||||
public void adaptedHandleMethods2() throws Exception {
|
public void adaptedHandleMethods2() throws Exception {
|
||||||
doTestAdaptedHandleMethods(MyAdaptedController2.class);
|
initServletWithControllers(MyAdaptedController2.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void adaptedHandleMethods3() throws Exception {
|
public void adaptedHandleMethods3() throws Exception {
|
||||||
doTestAdaptedHandleMethods(MyAdaptedController3.class);
|
initServletWithControllers(MyAdaptedController3.class);
|
||||||
|
doTestAdaptedHandleMethods();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doTestAdaptedHandleMethods(final Class<?> controllerClass) throws Exception {
|
private void doTestAdaptedHandleMethods() throws Exception {
|
||||||
initServletWithControllers(controllerClass);
|
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath1.do");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myPath1.do");
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
request.addParameter("param1", "value1");
|
request.addParameter("param1", "value1");
|
||||||
|
@ -727,8 +731,11 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void relativePathDispatchingController() throws Exception {
|
public void relativePathDispatchingController() throws Exception {
|
||||||
initServletWithControllers(MyRelativePathDispatchingController.class);
|
initServlet(wac -> {
|
||||||
getServlet().init(new MockServletConfig());
|
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||||
|
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||||
|
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||||
|
}, MyRelativePathDispatchingController.class);
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
@ -753,8 +760,11 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void relativeMethodPathDispatchingController() throws Exception {
|
public void relativeMethodPathDispatchingController() throws Exception {
|
||||||
initServletWithControllers(MyRelativeMethodPathDispatchingController.class);
|
initServlet(wac -> {
|
||||||
getServlet().init(new MockServletConfig());
|
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||||
|
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||||
|
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||||
|
}, MyRelativeMethodPathDispatchingController.class);
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/myApp/myHandle");
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
@ -1674,8 +1684,13 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||||
@Test
|
@Test
|
||||||
public void responseBodyAsHtml() throws Exception {
|
public void responseBodyAsHtml() throws Exception {
|
||||||
initServlet(wac -> {
|
initServlet(wac -> {
|
||||||
|
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||||
|
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||||
|
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||||
|
|
||||||
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
|
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
|
||||||
factoryBean.afterPropertiesSet();
|
factoryBean.afterPropertiesSet();
|
||||||
|
|
||||||
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
|
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
|
||||||
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
|
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
|
||||||
wac.registerBeanDefinition("handlerAdapter", adapterDef);
|
wac.registerBeanDefinition("handlerAdapter", adapterDef);
|
||||||
|
@ -1720,8 +1735,13 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
|
||||||
@Test
|
@Test
|
||||||
public void responseBodyAsHtmlWithProducesCondition() throws Exception {
|
public void responseBodyAsHtmlWithProducesCondition() throws Exception {
|
||||||
initServlet(wac -> {
|
initServlet(wac -> {
|
||||||
|
RootBeanDefinition mappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);
|
||||||
|
mappingDef.getPropertyValues().add("useSuffixPatternMatch", true);
|
||||||
|
wac.registerBeanDefinition("handlerMapping", mappingDef);
|
||||||
|
|
||||||
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
|
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
|
||||||
factoryBean.afterPropertiesSet();
|
factoryBean.afterPropertiesSet();
|
||||||
|
|
||||||
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
|
RootBeanDefinition adapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
|
||||||
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
|
adapterDef.getPropertyValues().add("contentNegotiationManager", factoryBean.getObject());
|
||||||
wac.registerBeanDefinition("handlerAdapter", adapterDef);
|
wac.registerBeanDefinition("handlerAdapter", adapterDef);
|
||||||
|
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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.factory.support.RootBeanDefinition;
|
||||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||||
import org.springframework.context.ApplicationContextInitializer;
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.web.bind.WebDataBinder;
|
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.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
|
||||||
import org.springframework.web.servlet.View;
|
import org.springframework.web.servlet.View;
|
||||||
import org.springframework.web.servlet.ViewResolver;
|
import org.springframework.web.servlet.ViewResolver;
|
||||||
import org.springframework.web.servlet.view.AbstractView;
|
import org.springframework.web.servlet.view.AbstractView;
|
||||||
|
@ -87,14 +85,10 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||||
pathVars.put("booking", 21);
|
pathVars.put("booking", 21);
|
||||||
pathVars.put("other", "other");
|
pathVars.put("other", "other");
|
||||||
|
|
||||||
WebApplicationContext wac =
|
WebApplicationContext wac = initServlet(context -> {
|
||||||
initServlet(new ApplicationContextInitializer<GenericWebApplicationContext>() {
|
|
||||||
@Override
|
|
||||||
public void initialize(GenericWebApplicationContext context) {
|
|
||||||
RootBeanDefinition beanDef = new RootBeanDefinition(ModelValidatingViewResolver.class);
|
RootBeanDefinition beanDef = new RootBeanDefinition(ModelValidatingViewResolver.class);
|
||||||
beanDef.getConstructorArgumentValues().addGenericArgumentValue(pathVars);
|
beanDef.getConstructorArgumentValues().addGenericArgumentValue(pathVars);
|
||||||
context.registerBeanDefinition("viewResolver", beanDef);
|
context.registerBeanDefinition("viewResolver", beanDef);
|
||||||
}
|
|
||||||
}, ViewRenderingController.class);
|
}, ViewRenderingController.class);
|
||||||
|
|
||||||
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42;q=1,2/bookings/21-other;q=3;r=R");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/hotels/42;q=1,2/bookings/21-other;q=3;r=R");
|
||||||
|
@ -143,22 +137,21 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
getServlet().service(request, response);
|
getServlet().service(request, response);
|
||||||
assertThat(response.getContentAsString()).isEqualTo("test-42-21");
|
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
|
@Test
|
||||||
public void extension() throws Exception {
|
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");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/42;jsessionid=c0o7fszeb1;q=24.xml");
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
getServlet().service(request, response);
|
getServlet().service(request, response);
|
||||||
assertThat(response.getContentAsString()).isEqualTo("test-42-24");
|
assertThat(response.getContentAsString()).isEqualTo("test-42-24");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -264,11 +257,6 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
getServlet().service(request, response);
|
getServlet().service(request, response);
|
||||||
assertThat(response.getContentAsString()).isEqualTo("handle4-page-5");
|
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
|
@Test
|
||||||
|
@ -282,10 +270,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||||
assertThat(response.getContentAsString()).isEqualTo("test-42-;q=1;q=2-[1, 2]");
|
assertThat(response.getContentAsString()).isEqualTo("test-42-;q=1;q=2-[1, 2]");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Test // gh-11306
|
||||||
* See SPR-6640
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void menuTree() throws Exception {
|
public void menuTree() throws Exception {
|
||||||
initServletWithControllers(MenuTreeController.class);
|
initServletWithControllers(MenuTreeController.class);
|
||||||
|
|
||||||
|
@ -295,10 +280,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||||
assertThat(response.getContentAsString()).isEqualTo("M5");
|
assertThat(response.getContentAsString()).isEqualTo("M5");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Test // gh-11542
|
||||||
* See SPR-6876
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void variableNames() throws Exception {
|
public void variableNames() throws Exception {
|
||||||
initServletWithControllers(VariableNamesController.class);
|
initServletWithControllers(VariableNamesController.class);
|
||||||
|
|
||||||
|
@ -313,12 +295,13 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||||
assertThat(response.getContentAsString()).isEqualTo("bar-bar");
|
assertThat(response.getContentAsString()).isEqualTo("bar-bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Test // gh-13187
|
||||||
* See SPR-8543
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void variableNamesWithUrlExtension() throws Exception {
|
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");
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/foo.json");
|
||||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
|
@ -326,10 +309,7 @@ public class UriTemplateServletAnnotationControllerHandlerMethodTests extends Ab
|
||||||
assertThat(response.getContentAsString()).isEqualTo("foo-foo");
|
assertThat(response.getContentAsString()).isEqualTo("foo-foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
@Test // gh-11643
|
||||||
* See SPR-6978
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void doIt() throws Exception {
|
public void doIt() throws Exception {
|
||||||
initServletWithControllers(Spr6978Controller.class);
|
initServletWithControllers(Spr6978Controller.class);
|
||||||
|
|
||||||
|
|
|
@ -1683,11 +1683,11 @@ See <<mvc-config-path-matching>> in the configuration section.
|
||||||
[[mvc-ann-requestmapping-suffix-pattern-match]]
|
[[mvc-ann-requestmapping-suffix-pattern-match]]
|
||||||
==== Suffix Match
|
==== Suffix Match
|
||||||
|
|
||||||
By default, Spring MVC performs `.{asterisk}` suffix pattern matching so that a
|
Starting in 5.3, by default Spring MVC no longer performs `.{asterisk}` suffix pattern
|
||||||
controller mapped to `/person` is also implicitly mapped to `/person.{asterisk}`.
|
matching where a controller mapped to `/person` is also implicitly mapped to
|
||||||
The file extension is then used to interpret the requested content type to use for
|
`/person.{asterisk}`. As a consequence path extensions are no longer used to interpret
|
||||||
the response (that is, instead of the `Accept` header) -- for example, `/person.pdf`,
|
the requested content type for the response -- for example, `/person.pdf`, `/person.xml`,
|
||||||
`/person.xml`, and others.
|
and so on.
|
||||||
|
|
||||||
Using file extensions in this way was necessary when browsers used to send `Accept` headers
|
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
|
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
|
URI encoding. Reasoning about URL-based authorization
|
||||||
and security (see next section for more details) also become more difficult.
|
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 <<mvc-config-path-matching, PathMatchConfigurer>>
|
* `useSuffixPatternMatching(false)`, see <<mvc-config-path-matching, PathMatchConfigurer>>
|
||||||
* `favorPathExtension(false)`, see <<mvc-config-content-negotiation, ContentNegotiationConfigurer>>
|
* `favorPathExtension(false)`, see <<mvc-config-content-negotiation, ContentNegotiationConfigurer>>
|
||||||
|
|
||||||
URL-based content negotiation can still be useful (for example, when typing a URL in a
|
Having a way to request content types other than through the `"Accept"` header can still
|
||||||
browser). To enable that, we recommend a query parameter-based strategy to avoid most of
|
be useful, e.g. when typing a URL in a browser. A safe alternative to path extensions is
|
||||||
the issues that come with file extensions. Alternatively, if you must use file extensions, consider
|
to use the query parameter strategy. If you must use file extensions, consider restricting
|
||||||
restricting them to a list of explicitly registered extensions through the
|
them to a list of explicitly registered extensions through the `mediaTypes` property of
|
||||||
`mediaTypes` property of <<mvc-config-content-negotiation,ContentNegotiationConfigurer>>.
|
<<mvc-config-content-negotiation,ContentNegotiationConfigurer>>.
|
||||||
|
|
||||||
[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.
|
|
||||||
====
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[mvc-ann-requestmapping-rfd]]
|
[[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) {
|
public void configurePathMatch(PathMatchConfigurer configurer) {
|
||||||
configurer
|
configurer
|
||||||
.setUseTrailingSlashMatch(false)
|
.setUseTrailingSlashMatch(false)
|
||||||
.setUseRegisteredSuffixPatternMatch(true)
|
|
||||||
.setPathMatcher(antPathMatcher())
|
.setPathMatcher(antPathMatcher())
|
||||||
.setUrlPathHelper(urlPathHelper())
|
.setUrlPathHelper(urlPathHelper())
|
||||||
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class));
|
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class));
|
||||||
|
@ -5879,7 +5866,6 @@ The following example shows how to customize path matching in Java configuration
|
||||||
configurer
|
configurer
|
||||||
.setUseSuffixPatternMatch(true)
|
.setUseSuffixPatternMatch(true)
|
||||||
.setUseTrailingSlashMatch(false)
|
.setUseTrailingSlashMatch(false)
|
||||||
.setUseRegisteredSuffixPatternMatch(true)
|
|
||||||
.setPathMatcher(antPathMatcher())
|
.setPathMatcher(antPathMatcher())
|
||||||
.setUrlPathHelper(urlPathHelper())
|
.setUrlPathHelper(urlPathHelper())
|
||||||
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
|
.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
|
||||||
|
@ -5904,7 +5890,6 @@ The following example shows how to achieve the same configuration in XML:
|
||||||
<mvc:annotation-driven>
|
<mvc:annotation-driven>
|
||||||
<mvc:path-matching
|
<mvc:path-matching
|
||||||
trailing-slash="false"
|
trailing-slash="false"
|
||||||
registered-suffixes-only="true"
|
|
||||||
path-helper="pathHelper"
|
path-helper="pathHelper"
|
||||||
path-matcher="pathMatcher"/>
|
path-matcher="pathMatcher"/>
|
||||||
</mvc:annotation-driven>
|
</mvc:annotation-driven>
|
||||||
|
|
Loading…
Reference in New Issue