What Determines @ResponseBody’s Default Return Format in Spring MVC?
In Spring MVC, the default data format returned by @ResponseBody depends on the client’s Accept header, and the framework selects an appropriate HttpMessageConverter through RequestResponseBodyMethodProcessor, which evaluates acceptable and producible media types to produce JSON, XML, or other formats.
Background
@ResponseBody default return format when backend does not specify produces MediaType?
<code>@Controller
public class DemoController {
@ResponseBody
@GetMapping(value = "/demo")
public DemoVO demo() {
return new DemoVO("lengleng", "123456");
}
}
</code>Search results show that @ResponseBody converts a Java object to JSON.
Correct Answer
We first publish the correct answer.
The output format of @ResponseBody, by default, is determined by the client’s
Acceptrequest header.
Source Code Analysis
RequestResponseBodyMethodProcessor
<code>public class RequestResponseBodyMethodProcessor {
// handle @ResponseBody annotated methods
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
}
// handle return value
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) {
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// write with converters
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
}
</code>writeWithMessageConverters
<code>protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) {
HttpServletRequest request = inputMessage.getServletRequest();
// Get Accept header media types
List<MediaType> acceptableTypes = getAcceptableMediaTypes(request);
// Get producible media types declared by the controller
List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType);
// Determine media types to use
List<MediaType> mediaTypesToUse = new ArrayList<>();
for (MediaType requestedType : acceptableTypes) {
for (MediaType producibleType : producibleTypes) {
if (requestedType.isCompatibleWith(producibleType)) {
mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType));
}
}
}
// Sort by specificity and quality
MediaType.sortBySpecificityAndQuality(mediaTypesToUse);
for (MediaType mediaType : mediaTypesToUse) {
if (mediaType.isConcrete()) {
selectedMediaType = mediaType;
break;
} else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) {
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
break;
}
}
selectedMediaType = selectedMediaType.removeQualityValue();
// Find a suitable HttpMessageConverter and write the body
for (HttpMessageConverter<?> converter : this.messageConverters) {
GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ?
(GenericHttpMessageConverter<?>) converter : null);
if (genericConverter != null ?
genericConverter.canWrite(targetType, valueType, selectedMediaType) :
converter.canWrite(valueType, selectedMediaType)) {
body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,
(Class<? extends HttpMessageConverter<?>>) converter.getClass(),
inputMessage, outputMessage);
return;
}
}
}
</code>Why Study This Issue
When upgrading to
spring cloud alibaba 2.2.1, the sentinel module brings in additional dependencies.
If the
dataformatjar appears, RestTemplate adds the following media types to the default Accept header:
application/xml | text/xml | application/*+xml
<code>public MappingJackson2XmlHttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper,
new MediaType("application", "xml", StandardCharsets.UTF_8),
new MediaType("text", "xml", StandardCharsets.UTF_8),
new MediaType("application", "*+xml", StandardCharsets.UTF_8));
Assert.isInstanceOf(XmlMapper.class, objectMapper, "XmlMapper required");
}
</code>When using RestTemplate without specifying Accept, the response may be XML, preventing a smooth upgrade.
Java Architecture Diary
Committed to sharing original, high‑quality technical articles; no fluff or promotional content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.