Skip to content

Commit 3b8148e

Browse files
committed
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
2 parents 63ecfac + e5b0386 commit 3b8148e

File tree

3 files changed

+47
-8
lines changed

3 files changed

+47
-8
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import org.springframework.http.converter.HttpMessageConverter;
7777
import org.springframework.util.AntPathMatcher;
7878
import org.springframework.util.ClassUtils;
79+
import org.springframework.util.CollectionUtils;
7980
import org.springframework.validation.DefaultMessageCodesResolver;
8081
import org.springframework.validation.MessageCodesResolver;
8182
import org.springframework.validation.Validator;
@@ -271,8 +272,12 @@ public void configureContentNegotiation(ContentNegotiationConfigurer configurer)
271272
if (contentnegotiation.getParameterName() != null) {
272273
configurer.parameterName(contentnegotiation.getParameterName());
273274
}
274-
Map<String, MediaType> mediaTypes = this.mvcProperties.getContentnegotiation().getMediaTypes();
275+
Map<String, MediaType> mediaTypes = contentnegotiation.getMediaTypes();
275276
mediaTypes.forEach(configurer::mediaType);
277+
List<MediaType> defaultContentTypes = contentnegotiation.getDefaultContentTypes();
278+
if (!CollectionUtils.isEmpty(defaultContentTypes)) {
279+
configurer.defaultContentType(defaultContentTypes.toArray(new MediaType[0]));
280+
}
276281
}
277282

278283
@Bean

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcProperties.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
package org.springframework.boot.autoconfigure.web.servlet;
1818

1919
import java.time.Duration;
20+
import java.util.ArrayList;
2021
import java.util.LinkedHashMap;
22+
import java.util.List;
2123
import java.util.Map;
2224

2325
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -306,16 +308,22 @@ public static class Contentnegotiation {
306308
*/
307309
private boolean favorParameter = false;
308310

311+
/**
312+
* Query parameter name to use when "favor-parameter" is enabled.
313+
*/
314+
private String parameterName;
315+
309316
/**
310317
* Map file extensions to media types for content negotiation. For instance, yml
311318
* to text/yaml.
312319
*/
313320
private Map<String, MediaType> mediaTypes = new LinkedHashMap<>();
314321

315322
/**
316-
* Query parameter name to use when "favor-parameter" is enabled.
323+
* List of default content types to be used when no specific content type is
324+
* requested.
317325
*/
318-
private String parameterName;
326+
private List<MediaType> defaultContentTypes = new ArrayList<>();
319327

320328
public boolean isFavorParameter() {
321329
return this.favorParameter;
@@ -325,6 +333,14 @@ public void setFavorParameter(boolean favorParameter) {
325333
this.favorParameter = favorParameter;
326334
}
327335

336+
public String getParameterName() {
337+
return this.parameterName;
338+
}
339+
340+
public void setParameterName(String parameterName) {
341+
this.parameterName = parameterName;
342+
}
343+
328344
public Map<String, MediaType> getMediaTypes() {
329345
return this.mediaTypes;
330346
}
@@ -333,12 +349,12 @@ public void setMediaTypes(Map<String, MediaType> mediaTypes) {
333349
this.mediaTypes = mediaTypes;
334350
}
335351

336-
public String getParameterName() {
337-
return this.parameterName;
352+
public List<MediaType> getDefaultContentTypes() {
353+
return this.defaultContentTypes;
338354
}
339355

340-
public void setParameterName(String parameterName) {
341-
this.parameterName = parameterName;
356+
public void setDefaultContentTypes(List<MediaType> defaultContentTypes) {
357+
this.defaultContentTypes = defaultContentTypes;
342358
}
343359

344360
}

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfigurationTests.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -79,13 +79,15 @@
7979
import org.springframework.format.support.FormattingConversionService;
8080
import org.springframework.http.CacheControl;
8181
import org.springframework.http.HttpHeaders;
82+
import org.springframework.http.MediaType;
8283
import org.springframework.http.converter.HttpMessageConverter;
8384
import org.springframework.mock.web.MockHttpServletRequest;
8485
import org.springframework.test.util.ReflectionTestUtils;
8586
import org.springframework.util.StringUtils;
8687
import org.springframework.validation.Validator;
8788
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
8889
import org.springframework.web.accept.ContentNegotiationManager;
90+
import org.springframework.web.accept.FixedContentNegotiationStrategy;
8991
import org.springframework.web.accept.ParameterContentNegotiationStrategy;
9092
import org.springframework.web.bind.annotation.ControllerAdvice;
9193
import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
@@ -577,6 +579,22 @@ void customMediaTypes() {
577579
});
578580
}
579581

582+
@Test
583+
void customDefaultContentTypes() {
584+
this.contextRunner
585+
.withPropertyValues("spring.mvc.contentnegotiation.default-content-types:application/json,application/xml")
586+
.run((context) -> {
587+
RequestMappingHandlerAdapter adapter = context.getBean(RequestMappingHandlerAdapter.class);
588+
ContentNegotiationManager contentNegotiationManager = (ContentNegotiationManager) ReflectionTestUtils
589+
.getField(adapter, "contentNegotiationManager");
590+
assertThat(contentNegotiationManager).isNotNull();
591+
assertThat(contentNegotiationManager.getStrategy(FixedContentNegotiationStrategy.class))
592+
.extracting(FixedContentNegotiationStrategy::getContentTypes)
593+
.asInstanceOf(InstanceOfAssertFactories.list(MediaType.class))
594+
.containsExactly(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML);
595+
});
596+
}
597+
580598
@Test
581599
void formContentFilterIsAutoConfigured() {
582600
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(OrderedFormContentFilter.class));

0 commit comments

Comments
 (0)