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 2a42e7623f..395de4772a 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 @@ -233,8 +233,8 @@ public class ContentNegotiationManagerFactoryBean *

By default this is not set. * @see #setDefaultContentTypeStrategy */ - public void setDefaultContentType(MediaType contentType) { - this.defaultNegotiationStrategy = new FixedContentNegotiationStrategy(contentType); + public void setDefaultContentType(List contentTypes) { + this.defaultNegotiationStrategy = new FixedContentNegotiationStrategy(contentTypes); } /** diff --git a/spring-web/src/main/java/org/springframework/web/accept/FixedContentNegotiationStrategy.java b/spring-web/src/main/java/org/springframework/web/accept/FixedContentNegotiationStrategy.java index 50478683b1..cb292a4d3e 100644 --- a/spring-web/src/main/java/org/springframework/web/accept/FixedContentNegotiationStrategy.java +++ b/spring-web/src/main/java/org/springframework/web/accept/FixedContentNegotiationStrategy.java @@ -16,12 +16,11 @@ package org.springframework.web.accept; -import java.util.Collections; +import java.util.Arrays; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.springframework.http.MediaType; import org.springframework.web.context.request.NativeWebRequest; @@ -35,23 +34,36 @@ public class FixedContentNegotiationStrategy implements ContentNegotiationStrate private static final Log logger = LogFactory.getLog(FixedContentNegotiationStrategy.class); - private final List contentType; + private final List contentTypes; /** * Create an instance with the given content type. */ - public FixedContentNegotiationStrategy(MediaType contentType) { - this.contentType = Collections.singletonList(contentType); + public FixedContentNegotiationStrategy(MediaType... contentTypes) { + this.contentTypes = Arrays.asList(contentTypes); + } + + /** + * Create an instance with the given content type. + * + *

+ * List is ordered in the same manner as a "quality" parameter on incoming requests. + * If destinations which do not support any of the media types provided are present, + * end the list with {@link MediaType#ALL} to allow standard media type determination + */ + public FixedContentNegotiationStrategy(List contentTypes) { + this.contentTypes = contentTypes; } @Override public List resolveMediaTypes(NativeWebRequest request) { if (logger.isDebugEnabled()) { - logger.debug("Requested media types: " + this.contentType); + logger.debug("Requested media types: " + this.contentTypes); } - return this.contentType; + + return this.contentTypes; } } diff --git a/spring-web/src/test/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBeanTests.java b/spring-web/src/test/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBeanTests.java index 5041ed05cb..0a86763274 100644 --- a/spring-web/src/test/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBeanTests.java +++ b/spring-web/src/test/java/org/springframework/web/accept/ContentNegotiationManagerFactoryBeanTests.java @@ -16,13 +16,13 @@ package org.springframework.web.accept; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.junit.Before; import org.junit.Test; - import org.springframework.http.MediaType; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.mock.web.test.MockServletContext; @@ -161,10 +161,10 @@ public class ContentNegotiationManagerFactoryBeanTests { assertEquals(Collections.emptyList(), manager.resolveMediaTypes(this.webRequest)); } - + @Test public void setDefaultContentType() throws Exception { - this.factoryBean.setDefaultContentType(MediaType.APPLICATION_JSON); + this.factoryBean.setDefaultContentType(Arrays.asList(MediaType.APPLICATION_JSON)); this.factoryBean.afterPropertiesSet(); ContentNegotiationManager manager = this.factoryBean.getObject(); @@ -176,6 +176,21 @@ public class ContentNegotiationManagerFactoryBeanTests { assertEquals(Collections.singletonList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(this.webRequest)); } + + @Test + public void setMultipleDefaultContentTypess() throws Exception { + this.factoryBean.setDefaultContentType(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.ALL)); + this.factoryBean.afterPropertiesSet(); + ContentNegotiationManager manager = this.factoryBean.getObject(); + + assertEquals(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.ALL), + manager.resolveMediaTypes(this.webRequest)); + + // SPR-15367 + this.servletRequest.addHeader("Accept", MediaType.ALL_VALUE); + assertEquals(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.ALL), + manager.resolveMediaTypes(this.webRequest)); + } @Test // SPR-12286 public void setDefaultContentTypeWithStrategy() throws Exception { 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 c085e62a29..b0f5fed7df 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 @@ -15,8 +15,10 @@ */ package org.springframework.web.servlet.config.annotation; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; + import javax.servlet.ServletContext; import org.springframework.http.MediaType; @@ -218,11 +220,18 @@ public class ContentNegotiationConfigurer { /** * Set the default content type to use when no content type is requested. - *

By default this is not set. + *

+ * Media types are ordered in the same manner as a "quality" parameter on incoming + * requests. If destinations which do not support any of the media types provided are + * present, end the list with {@link MediaType#ALL} to allow standard media type + * determination + *

+ * By default this is not set. + * * @see #defaultContentTypeStrategy */ - public ContentNegotiationConfigurer defaultContentType(MediaType defaultContentType) { - this.factory.setDefaultContentType(defaultContentType); + public ContentNegotiationConfigurer defaultContentType(MediaType... defaultContentTypes) { + this.factory.setDefaultContentType(Arrays.asList(defaultContentTypes)); return this; } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ContentNegotiationConfigurerTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ContentNegotiationConfigurerTests.java index 902c09af89..7a4d5e7b2c 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ContentNegotiationConfigurerTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/config/annotation/ContentNegotiationConfigurerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2017 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,7 +20,6 @@ import java.util.Collections; import org.junit.Before; import org.junit.Test; - import org.springframework.http.MediaType; import org.springframework.mock.web.test.MockHttpServletRequest; import org.springframework.web.accept.ContentNegotiationManager; @@ -111,6 +110,14 @@ public class ContentNegotiationConfigurerTests { assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(this.webRequest)); } + + @Test + public void setMultipleDefaultContentTypes() throws Exception { + this.configurer.defaultContentType(MediaType.APPLICATION_JSON, MediaType.ALL); + ContentNegotiationManager manager = this.configurer.getContentNegotiationManager(); + + assertEquals(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.ALL), manager.resolveMediaTypes(this.webRequest)); + } @Test public void setDefaultContentTypeStrategy() throws Exception {