Merge pull request #44040 from nosan

* pr/44040:
  Polish "Add property to configure Spring MVC default content types"
  Add property to configure Spring MVC default content types

Closes gh-44040
This commit is contained in:
Stéphane Nicoll
2025-02-04 12:40:36 +01:00
3 changed files with 47 additions and 8 deletions

View File

@@ -76,6 +76,7 @@ import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.DefaultMessageCodesResolver;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
@@ -271,8 +272,12 @@ public class WebMvcAutoConfiguration {
if (contentnegotiation.getParameterName() != null) {
configurer.parameterName(contentnegotiation.getParameterName());
}
Map<String, MediaType> mediaTypes = this.mvcProperties.getContentnegotiation().getMediaTypes();
Map<String, MediaType> mediaTypes = contentnegotiation.getMediaTypes();
mediaTypes.forEach(configurer::mediaType);
List<MediaType> defaultContentTypes = contentnegotiation.getDefaultContentTypes();
if (!CollectionUtils.isEmpty(defaultContentTypes)) {
configurer.defaultContentType(defaultContentTypes.toArray(new MediaType[0]));
}
}
@Bean

View File

@@ -17,7 +17,9 @@
package org.springframework.boot.autoconfigure.web.servlet;
import java.time.Duration;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -306,6 +308,11 @@ public class WebMvcProperties {
*/
private boolean favorParameter = false;
/**
* Query parameter name to use when "favor-parameter" is enabled.
*/
private String parameterName;
/**
* Map file extensions to media types for content negotiation. For instance, yml
* to text/yaml.
@@ -313,9 +320,10 @@ public class WebMvcProperties {
private Map<String, MediaType> mediaTypes = new LinkedHashMap<>();
/**
* Query parameter name to use when "favor-parameter" is enabled.
* List of default content types to be used when no specific content type is
* requested.
*/
private String parameterName;
private List<MediaType> defaultContentTypes = new ArrayList<>();
public boolean isFavorParameter() {
return this.favorParameter;
@@ -325,6 +333,14 @@ public class WebMvcProperties {
this.favorParameter = favorParameter;
}
public String getParameterName() {
return this.parameterName;
}
public void setParameterName(String parameterName) {
this.parameterName = parameterName;
}
public Map<String, MediaType> getMediaTypes() {
return this.mediaTypes;
}
@@ -333,12 +349,12 @@ public class WebMvcProperties {
this.mediaTypes = mediaTypes;
}
public String getParameterName() {
return this.parameterName;
public List<MediaType> getDefaultContentTypes() {
return this.defaultContentTypes;
}
public void setParameterName(String parameterName) {
this.parameterName = parameterName;
public void setDefaultContentTypes(List<MediaType> defaultContentTypes) {
this.defaultContentTypes = defaultContentTypes;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2024 the original author or authors.
* Copyright 2012-2025 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.
@@ -79,6 +79,7 @@ import org.springframework.format.Printer;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.http.CacheControl;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.util.ReflectionTestUtils;
@@ -86,6 +87,7 @@ import org.springframework.util.StringUtils;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.accept.FixedContentNegotiationStrategy;
import org.springframework.web.accept.ParameterContentNegotiationStrategy;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
@@ -577,6 +579,22 @@ class WebMvcAutoConfigurationTests {
});
}
@Test
void customDefaultContentTypes() {
this.contextRunner
.withPropertyValues("spring.mvc.contentnegotiation.default-content-types:application/json,application/xml")
.run((context) -> {
RequestMappingHandlerAdapter adapter = context.getBean(RequestMappingHandlerAdapter.class);
ContentNegotiationManager contentNegotiationManager = (ContentNegotiationManager) ReflectionTestUtils
.getField(adapter, "contentNegotiationManager");
assertThat(contentNegotiationManager).isNotNull();
assertThat(contentNegotiationManager.getStrategy(FixedContentNegotiationStrategy.class))
.extracting(FixedContentNegotiationStrategy::getContentTypes)
.asInstanceOf(InstanceOfAssertFactories.list(MediaType.class))
.containsExactly(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML);
});
}
@Test
void formContentFilterIsAutoConfigured() {
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(OrderedFormContentFilter.class));