mediaTypes) {
if (mediaTypes != null) {
@@ -119,37 +158,31 @@ public class ContentNegotiationManagerFactoryBean
}
/**
- * Whether to ignore requests that have a file extension that does not match
- * any mapped media types. Setting this to {@code false} will result in a
- * {@code HttpMediaTypeNotAcceptableException} when there is no match.
- *
+ * Whether to ignore requests with path extension that cannot be resolved
+ * 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}.
*/
- public void setIgnoreUnknownPathExtensions(boolean ignoreUnknownPathExtensions) {
- this.ignoreUnknownPathExtensions = ignoreUnknownPathExtensions;
+ public void setIgnoreUnknownPathExtensions(boolean ignore) {
+ this.ignoreUnknownPathExtensions = ignore;
}
/**
- * Whether to use the Java Activation Framework as a fallback option
- * to map from file extensions to media types. This is used only when
- * {@link #setFavorPathExtension(boolean)} is set to {@code true}.
- *
The default value is {@code true}.
- * @see #setParameterName
- * @see #setMediaTypes
+ * When {@link #setFavorPathExtension favorPathExtension} is set, this
+ * property determines whether to allow use of JAF (Java Activation Framework)
+ * to resolve a path extension to a specific MediaType.
+ *
By default this is not set in which case
+ * {@code PathExtensionContentNegotiationStrategy} will use JAF if available.
*/
public void setUseJaf(boolean useJaf) {
this.useJaf = useJaf;
}
/**
- * Indicate whether a request parameter should be used to determine the
- * requested media type with the 2nd highest priority, i.e.
- * after path extensions but before the {@code Accept} header.
- *
The default value is {@code false}. If set to to {@code true}, a request
- * for {@code /hotels?format=pdf} will be interpreted as a request for
- * {@code "application/pdf"} regardless of the {@code Accept} header.
- *
To use this option effectively you must also configure the MediaType
- * type mappings via {@link #setMediaTypes(Properties)}.
+ * 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}.
+ *
By default this is set to {@code false}.
* @see #setParameterName
*/
public void setFavorParameter(boolean favorParameter) {
@@ -157,8 +190,7 @@ public class ContentNegotiationManagerFactoryBean
}
/**
- * Set the parameter name that can be used to determine the requested media type
- * if the {@link #setFavorParameter} property is {@code true}.
+ * Set the query parameter name to use when {@link #setFavorParameter} is on.
*
The default parameter name is {@code "format"}.
*/
public void setParameterName(String parameterName) {
@@ -167,10 +199,7 @@ public class ContentNegotiationManagerFactoryBean
}
/**
- * Indicate whether the HTTP {@code Accept} header should be ignored altogether.
- * If set the {@code Accept} header is checked at the
- * 3rd highest priority, i.e. after the request path extension and
- * possibly a request parameter if configured.
+ * Whether to disable checking the 'Accept' request header.
*
By default this value is set to {@code false}.
*/
public void setIgnoreAcceptHeader(boolean ignoreAcceptHeader) {
@@ -178,27 +207,27 @@ public class ContentNegotiationManagerFactoryBean
}
/**
- * Set the default content type to use when no content type was requested.
- *
Note that internally this method creates and adds a
- * {@link org.springframework.web.accept.FixedContentNegotiationStrategy
- * FixedContentNegotiationStrategy}. Alternatively you can also provide a
- * custom strategy via {@link #setDefaultContentTypeStrategy}.
+ * Set the default content type to use when no content type is requested.
+ *
By default this is not set.
+ * @see #setDefaultContentTypeStrategy
*/
public void setDefaultContentType(MediaType contentType) {
this.defaultNegotiationStrategy = new FixedContentNegotiationStrategy(contentType);
}
/**
- * Configure a custom {@link ContentNegotiationStrategy} to use to determine
- * the default content type to use when no content type was requested.
- *
However also consider using {@link #setDefaultContentType} which
- * provides a simpler alternative to doing the same.
+ * Set a custom {@link ContentNegotiationStrategy} to use to determine
+ * the content type to use when no content type is requested.
+ * @see #setDefaultContentType
* @since 4.1.2
*/
public void setDefaultContentTypeStrategy(ContentNegotiationStrategy strategy) {
this.defaultNegotiationStrategy = strategy;
}
+ /**
+ * Invoked by Spring to inject the ServletContext.
+ */
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
@@ -237,7 +266,7 @@ public class ContentNegotiationManagerFactoryBean
}
if (this.defaultNegotiationStrategy != null) {
- strategies.add(defaultNegotiationStrategy);
+ strategies.add(this.defaultNegotiationStrategy);
}
this.contentNegotiationManager = new ContentNegotiationManager(strategies);
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ContentNegotiationConfigurer.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ContentNegotiationConfigurer.java
index 35a928e2b9f..1c55a3eb2b1 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ContentNegotiationConfigurer.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/ContentNegotiationConfigurer.java
@@ -23,21 +23,64 @@ import org.springframework.http.MediaType;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.accept.ContentNegotiationManagerFactoryBean;
import org.springframework.web.accept.ContentNegotiationStrategy;
+import org.springframework.web.accept.FixedContentNegotiationStrategy;
+import org.springframework.web.accept.HeaderContentNegotiationStrategy;
+import org.springframework.web.accept.ParameterContentNegotiationStrategy;
+import org.springframework.web.accept.PathExtensionContentNegotiationStrategy;
/**
- * Help to create and configure a {@link ContentNegotiationManager}.
+ * Creates a {@code ContentNegotiationManager} and configures it with
+ * one or more {@link ContentNegotiationStrategy} instances. The following shows
+ * the resulting strategy instances, the methods used to configured them, and
+ * whether enabled by default:
*
- *
By default strategies for checking the extension of the request path and
- * the {@code Accept} header are registered. The path extension check will perform
- * lookups through the {@link ServletContext} and the Java Activation Framework
- * (if present) unless {@linkplain #mediaTypes(Map) media types} are configured.
+ *
+ *
+ * | {@link #favorPathExtension} |
+ * {@link PathExtensionContentNegotiationStrategy} |
+ * Yes |
+ *
+ *
+ * | {@link #favorParameter} |
+ * {@link ParameterContentNegotiationStrategy} |
+ * - |
+ *
+ *
+ * | {@link #ignoreAcceptHeader} |
+ * {@link HeaderContentNegotiationStrategy} |
+ * Yes |
+ *
+ *
+ * | {@link #defaultContentType} |
+ * {@link FixedContentNegotiationStrategy} |
+ * - |
+ *
+ *
+ * | {@link #defaultContentTypeStrategy} |
+ * {@link ContentNegotiationStrategy} |
+ * - |
+ *
+ *
+ *
+ * The order in which strategies are configured is fixed. You can only turn
+ * them on or off.
+ *
+ *
For the path extension and parameter strategies you may explicitly add
+ * {@link #mediaType MediaType mappings}. Those will be used to resolve path
+ * extensions and/or a query parameter value such as "json" to a concrete media
+ * type such as "application/json".
+ *
+ *
The path extension strategy will also use {@link ServletContext#getMimeType}
+ * and the Java Activation framework (JAF), if available, to resolve a path
+ * extension to a MediaType. You may however {@link #useJaf suppress} the use
+ * of JAF.
*
* @author Rossen Stoyanchev
* @since 3.2
*/
public class ContentNegotiationConfigurer {
- private final ContentNegotiationManagerFactoryBean factoryBean =
+ private final ContentNegotiationManagerFactoryBean factory =
new ContentNegotiationManagerFactoryBean();
private final Map mediaTypes = new HashMap();
@@ -47,25 +90,32 @@ public class ContentNegotiationConfigurer {
* Class constructor with {@link javax.servlet.ServletContext}.
*/
public ContentNegotiationConfigurer(ServletContext servletContext) {
- this.factoryBean.setServletContext(servletContext);
+ this.factory.setServletContext(servletContext);
}
+
/**
- * Indicate whether the extension of the request path should be used to determine
- * the requested media type with the highest priority.
- * By default this value is set to {@code true} in which case a request
+ * 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 {@code Accept} header.
+ * {@code "application/pdf"} regardless of the 'Accept' header.
*/
public ContentNegotiationConfigurer favorPathExtension(boolean favorPathExtension) {
- this.factoryBean.setFavorPathExtension(favorPathExtension);
+ this.factory.setFavorPathExtension(favorPathExtension);
return this;
}
/**
- * Add mappings from file extensions to media types.
- *
If this property is not set, the Java Action Framework, if available, may
- * still be used in conjunction with {@link #favorPathExtension(boolean)}.
+ * Add a mapping from a key, extracted from a path extension or a query
+ * parameter, to a MediaType. This is required in order for the parameter
+ * strategy to work. The path extension strategy will also try
+ * {@link ServletContext#getMimeType} and JAF if it is present and is not
+ * suppressed via {@link #useJaf}.
+ * @param extension the key to look up
+ * @param mediaType the media type
+ * @see #mediaTypes(Map)
+ * @see #replaceMediaTypes(Map)
*/
public ContentNegotiationConfigurer mediaType(String extension, MediaType mediaType) {
this.mediaTypes.put(extension, mediaType);
@@ -73,9 +123,9 @@ public class ContentNegotiationConfigurer {
}
/**
- * Add mappings from file extensions to media types.
- *
If this property is not set, the Java Action Framework, if available, may
- * still be used in conjunction with {@link #favorPathExtension(boolean)}.
+ * An alternative to {@link #mediaType}.
+ * @see #mediaType(String, MediaType)
+ * @see #replaceMediaTypes(Map)
*/
public ContentNegotiationConfigurer mediaTypes(Map mediaTypes) {
if (mediaTypes != null) {
@@ -85,9 +135,9 @@ public class ContentNegotiationConfigurer {
}
/**
- * Add mappings from file extensions to media types replacing any previous mappings.
- * If this property is not set, the Java Action Framework, if available, may
- * still be used in conjunction with {@link #favorPathExtension(boolean)}.
+ * Similar to {@link #mediaType} but for replacing existing mappings.
+ * @see #mediaType(String, MediaType)
+ * @see #mediaTypes(Map)
*/
public ContentNegotiationConfigurer replaceMediaTypes(Map mediaTypes) {
this.mediaTypes.clear();
@@ -96,101 +146,83 @@ public class ContentNegotiationConfigurer {
}
/**
- * Whether to ignore requests that have a file extension that does not match
- * any mapped media types. Setting this to {@code false} will result in a
- * {@code HttpMediaTypeNotAcceptableException} when there is no match.
- *
+ * Whether to ignore requests with path extension that cannot be resolved
+ * 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}.
*/
public ContentNegotiationConfigurer ignoreUnknownPathExtensions(boolean ignore) {
- this.factoryBean.setIgnoreUnknownPathExtensions(ignore);
+ this.factory.setIgnoreUnknownPathExtensions(ignore);
return this;
}
/**
- * Indicate whether to use the Java Activation Framework as a fallback option
- * to map from file extensions to media types. This is used only when
- * {@link #favorPathExtension(boolean)} is set to {@code true}.
- *
The default value is {@code true}.
- * @see #parameterName
- * @see #mediaTypes(Map)
+ * When {@link #favorPathExtension} is set, this property determines whether
+ * to allow use of JAF (Java Activation Framework) to resolve a path
+ * extension to a specific MediaType.
+ *
By default this is not set in which case
+ * {@code PathExtensionContentNegotiationStrategy} will use JAF if available.
*/
public ContentNegotiationConfigurer useJaf(boolean useJaf) {
- this.factoryBean.setUseJaf(useJaf);
+ this.factory.setUseJaf(useJaf);
return this;
}
/**
- * Indicate whether a request parameter should be used to determine the
- * requested media type with the 2nd highest priority, i.e.
- * after path extensions but before the {@code Accept} header.
- *
The default value is {@code false}. If set to to {@code true}, a request
- * for {@code /hotels?format=pdf} will be interpreted as a request for
- * {@code "application/pdf"} regardless of the {@code Accept} header.
- *
To use this option effectively you must also configure the MediaType
- * type mappings via {@link #mediaTypes(Map)}.
+ * 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.factoryBean.setFavorParameter(favorParameter);
+ this.factory.setFavorParameter(favorParameter);
return this;
}
/**
- * Set the parameter name that can be used to determine the requested media type
- * if the {@link #favorParameter(boolean)} property is {@code true}.
+ * 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.factoryBean.setParameterName(parameterName);
+ this.factory.setParameterName(parameterName);
return this;
}
/**
- * Indicate whether the HTTP {@code Accept} header should be ignored altogether.
- * If set the {@code Accept} header is checked at the
- * 3rd highest priority, i.e. after the request path extension and
- * possibly a request parameter if configured.
+ * Whether to disable checking the 'Accept' request header.
*
By default this value is set to {@code false}.
*/
public ContentNegotiationConfigurer ignoreAcceptHeader(boolean ignoreAcceptHeader) {
- this.factoryBean.setIgnoreAcceptHeader(ignoreAcceptHeader);
+ this.factory.setIgnoreAcceptHeader(ignoreAcceptHeader);
return this;
}
/**
- * Set the default content type to use when no content type was requested.
- *
Note that internally this method creates and adds a
- * {@link org.springframework.web.accept.FixedContentNegotiationStrategy
- * FixedContentNegotiationStrategy}. Alternatively you can also provide a
- * custom strategy via {@link #defaultContentTypeStrategy}.
+ * Set the default content type to use when no content type is requested.
+ *
By default this is not set.
+ * @see #defaultContentTypeStrategy
*/
public ContentNegotiationConfigurer defaultContentType(MediaType defaultContentType) {
- this.factoryBean.setDefaultContentType(defaultContentType);
+ this.factory.setDefaultContentType(defaultContentType);
return this;
}
/**
- * Configure a custom {@link ContentNegotiationStrategy} to use to determine
- * the default content type to use when no content type was requested.
- *
However also consider using {@link #defaultContentType} which provides
- * a simpler alternative to doing the same.
+ * Set a custom {@link ContentNegotiationStrategy} to use to determine
+ * the content type to use when no content type is requested.
+ * @see #defaultContentType
* @since 4.1.2
*/
public ContentNegotiationConfigurer defaultContentTypeStrategy(ContentNegotiationStrategy defaultStrategy) {
- this.factoryBean.setDefaultContentTypeStrategy(defaultStrategy);
+ this.factory.setDefaultContentTypeStrategy(defaultStrategy);
return this;
}
- /**
- * Return the configured {@link ContentNegotiationManager} instance
- */
protected ContentNegotiationManager getContentNegotiationManager() throws Exception {
- if (!this.mediaTypes.isEmpty()) {
- this.factoryBean.addMediaTypes(mediaTypes);
- }
- this.factoryBean.afterPropertiesSet();
- return this.factoryBean.getObject();
+ this.factory.addMediaTypes(this.mediaTypes);
+ this.factory.afterPropertiesSet();
+ return this.factory.getObject();
}
}
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 8203ea201ca..35fa13e3172 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,8 +20,8 @@ import org.springframework.util.PathMatcher;
import org.springframework.web.util.UrlPathHelper;
/**
- * Helps with configuring HandlerMappings path matching options such as trailing slash match,
- * suffix registration, path matcher and path helper.
+ * Helps with configuring HandlerMappings path matching options such as trailing
+ * slash match, suffix registration, path matcher and path helper.
*
*
Configured path matcher and path helper instances are shared for:
*
@@ -37,11 +37,11 @@ import org.springframework.web.util.UrlPathHelper;
*/
public class PathMatchConfigurer {
- private Boolean useSuffixPatternMatch;
+ private Boolean suffixPatternMatch;
- private Boolean useTrailingSlashMatch;
+ private Boolean trailingSlashMatch;
- private Boolean useRegisteredSuffixPatternMatch;
+ private Boolean registeredSuffixPatternMatch;
private UrlPathHelper urlPathHelper;
@@ -51,10 +51,11 @@ public class PathMatchConfigurer {
/**
* 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 this is set to {@code true}.
+ * @see #registeredSuffixPatternMatch
*/
- public PathMatchConfigurer setUseSuffixPatternMatch(Boolean useSuffixPatternMatch) {
- this.useSuffixPatternMatch = useSuffixPatternMatch;
+ public PathMatchConfigurer setUseSuffixPatternMatch(Boolean suffixPatternMatch) {
+ this.suffixPatternMatch = suffixPatternMatch;
return this;
}
@@ -63,28 +64,24 @@ public class PathMatchConfigurer {
* If enabled a method mapped to "/users" also matches to "/users/".
*
The default value is {@code true}.
*/
- public PathMatchConfigurer setUseTrailingSlashMatch(Boolean useTrailingSlashMatch) {
- this.useTrailingSlashMatch = useTrailingSlashMatch;
+ public PathMatchConfigurer setUseTrailingSlashMatch(Boolean trailingSlashMatch) {
+ this.trailingSlashMatch = trailingSlashMatch;
return this;
}
/**
- * Whether to use suffix pattern match for registered file extensions only
- * when matching patterns to requests.
- *
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}.
- * The {@link org.springframework.web.accept.ContentNegotiationManager} can be customized
- * using a {@link ContentNegotiationConfigurer}.
- * If enabled, this flag also enables
- * {@link #setUseSuffixPatternMatch(Boolean) useSuffixPatternMatch}. The
- * default value is {@code false}.
- * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
- * @see ContentNegotiationConfigurer
- *
+ * Whether suffix pattern matching should work only against path extensions
+ * explicitly registered when you
+ * {@link WebMvcConfigurer#configureContentNegotiation configure content
+ * negotiation}. This is generally recommended to reduce ambiguity and to
+ * avoid issues such as when a "." appears in the path for other reasons.
+ * By default this is set to "false".
+ * @see WebMvcConfigurer#configureContentNegotiation
*/
- public PathMatchConfigurer setUseRegisteredSuffixPatternMatch(Boolean useRegisteredSuffixPatternMatch) {
- this.useRegisteredSuffixPatternMatch = useRegisteredSuffixPatternMatch;
+ public PathMatchConfigurer setUseRegisteredSuffixPatternMatch(
+ Boolean registeredSuffixPatternMatch) {
+
+ this.registeredSuffixPatternMatch = registeredSuffixPatternMatch;
return this;
}
@@ -110,15 +107,15 @@ public class PathMatchConfigurer {
}
public Boolean isUseSuffixPatternMatch() {
- return this.useSuffixPatternMatch;
+ return this.suffixPatternMatch;
}
public Boolean isUseTrailingSlashMatch() {
- return this.useTrailingSlashMatch;
+ return this.trailingSlashMatch;
}
public Boolean isUseRegisteredSuffixPatternMatch() {
- return this.useRegisteredSuffixPatternMatch;
+ return this.registeredSuffixPatternMatch;
}
public UrlPathHelper getUrlPathHelper() {
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
index e2b52c61db9..5ffb6aaf5c8 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java
@@ -78,19 +78,11 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
}
/**
- * Whether to use suffix pattern match for registered file extensions only
- * when matching patterns to requests.
- *
If enabled, a controller method mapped to "/users" also matches to
- * "/users.json" assuming ".json" is a file extension registered with the
- * provided {@link #setContentNegotiationManager(ContentNegotiationManager)
- * contentNegotiationManager}. This can be useful for allowing only specific
- * URL extensions to be used as well as in cases where a "." in the URL path
- * can lead to ambiguous interpretation of path variable content, (e.g. given
- * "/users/{user}" and incoming URLs such as "/users/john.j.joe" and
- * "/users/john.j.joe.json").
- *
If enabled, this flag also enables
- * {@link #setUseSuffixPatternMatch(boolean) useSuffixPatternMatch}. The
- * default value is {@code false}.
+ * Whether suffix pattern matching should work only against path extensions
+ * explicitly registered with the {@link ContentNegotiationManager}. This
+ * is generally recommended to reduce ambiguity and to avoid issues such as
+ * when a "." appears in the path for other reasons.
+ *
By default this is set to "false".
*/
public void setUseRegisteredSuffixPatternMatch(boolean useRegisteredSuffixPatternMatch) {
this.useRegisteredSuffixPatternMatch = useRegisteredSuffixPatternMatch;
diff --git a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.2.xsd b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.2.xsd
index 0b67e835e0e..7e32a96ed8b 100644
--- a/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.2.xsd
+++ b/spring-webmvc/src/main/resources/org/springframework/web/servlet/config/spring-mvc-4.2.xsd
@@ -52,12 +52,11 @@