Allow defining default content negotiation strategy

During the HTTP Content Negotiation phase, the ContentNegotiationManager
uses configured ContentNegotiationStrategy(ies) to define the list of
content types accepted by the client.

When HTTP clients don't send Accept headers, nor use a configured
file extension in the request, nor a request param, developers can
define a default content type using the
ContentNegotiationConfigurer.defaultContentType() method.

This change adds a new overloaded defaultContentType method that takes a
ContentNegotiationStrategy as an argument. This strategy will take the
current request as an argument and return a default content type.

Issue: SPR-12286
This commit is contained in:
Brian Clozel 2014-10-22 16:32:12 +02:00
parent a2731f1a4f
commit 86d97baf65
4 changed files with 53 additions and 1 deletions

View File

@ -63,6 +63,8 @@ public class ContentNegotiationManagerFactoryBean
private MediaType defaultContentType;
private ContentNegotiationStrategy defaultNegotiationStrategy;
private ContentNegotiationManager contentNegotiationManager;
private ServletContext servletContext;
@ -187,6 +189,17 @@ public class ContentNegotiationManagerFactoryBean
this.defaultContentType = defaultContentType;
}
/**
* Set the {@link ContentNegotiationStrategy} to be used to resolving the default content type.
* <p>This content type will be used when neither the request path extension,
* nor a request parameter, nor the {@code Accept} header could help determine
* the requested content type.
* @since 4.1.2
*/
public void setDefaultContentType(ContentNegotiationStrategy defaultStrategy) {
this.defaultNegotiationStrategy = defaultStrategy;
}
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
@ -226,6 +239,10 @@ public class ContentNegotiationManagerFactoryBean
strategies.add(new FixedContentNegotiationStrategy(this.defaultContentType));
}
if(this.defaultNegotiationStrategy != null) {
strategies.add(defaultNegotiationStrategy);
}
this.contentNegotiationManager = new ContentNegotiationManager(strategies);
}

View File

@ -168,4 +168,17 @@ public class ContentNegotiationManagerFactoryBeanTests {
assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(this.webRequest));
}
// SPR-12286
@Test
public void setDefaultContentTypeWithStrategy() throws Exception {
this.factoryBean.setDefaultContentType(new FixedContentNegotiationStrategy(MediaType.APPLICATION_JSON));
this.factoryBean.afterPropertiesSet();
ContentNegotiationManager manager = this.factoryBean.getObject();
assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(this.webRequest));
this.servletRequest.addHeader("Accept", MediaType.ALL_VALUE);
assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(this.webRequest));
}
}

View File

@ -22,6 +22,7 @@ import javax.servlet.ServletContext;
import org.springframework.http.MediaType;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.accept.ContentNegotiationManagerFactoryBean;
import org.springframework.web.accept.ContentNegotiationStrategy;
/**
* Helps with configuring a {@link ContentNegotiationManager}.
@ -167,6 +168,18 @@ public class ContentNegotiationConfigurer {
return this;
}
/**
* Set the {@link ContentNegotiationStrategy} to be used to resolving the default content type.
* <p>This content type will be used when neither the request path extension,
* nor a request parameter, nor the {@code Accept} header could help determine
* the requested content type.
* @since 4.1.2
*/
public ContentNegotiationConfigurer defaultContentType(ContentNegotiationStrategy defaultStrategy) {
this.factoryBean.setDefaultContentType(defaultStrategy);
return this;
}
/**
* Return the configured {@link ContentNegotiationManager} instance
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -24,6 +24,7 @@ import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.accept.FixedContentNegotiationStrategy;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
@ -110,4 +111,12 @@ public class ContentNegotiationConfigurerTests {
assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(this.webRequest));
}
@Test
public void setDefaultContentTypeWithStrategy() throws Exception {
this.configurer.defaultContentType(new FixedContentNegotiationStrategy(MediaType.APPLICATION_JSON));
ContentNegotiationManager manager = this.configurer.getContentNegotiationManager();
assertEquals(Arrays.asList(MediaType.APPLICATION_JSON), manager.resolveMediaTypes(this.webRequest));
}
}