关于Spring MVC中@ResponseBody怎么知道我需要什么类型

2025-05-06 13:39:41
推荐回答(1个)
回答1:

@ResponseBody注解在 method上具体返回什么类型的数据流(json、xml等)主要有两个方面决定的:1. 是否有对应的第三方jar包出现在classpath,比如jackson jar、jaxb2
jar,如果只存在spring mvc就会注册对应的HttpMessageConvert(将return
obj写为response的流是靠httpMessageConvert的实现类来完成的) 2.
有@RequestMapping注解的consumes具体的mediaTypes和http请求的accept能结束的mime
type来联合决定。
有这两点决定@ResponseBody注解的返回值的返回流的类型具体的实现参见
RequestResponseBodyMthodProcessor,java中,具体的写流实现如下在
AbstractMessageConverterMethodProcessor.writeWithMessageConverters()来实现
的。具体代码:
/**
* Writes the given return type to the given output message.
*
* @param returnValue the value to write to the output message
* @param returnType the type of the value
* @param inputMessage the input messages. Used to inspect the {@code Accept} header.
* @param outputMessage the output message to write to
* @throws IOException thrown in case of I/O errors
* @throws HttpMediaTypeNotAcceptableException thrown when the conditions indicated by {@code Accept} header on
* the request cannot be met by the message converters
*/
@SuppressWarnings("unchecked")
protected void writeWithMessageConverters(T returnValue,
MethodParameter returnType,
ServletServerHttpRequest inputMessage,
ServletServerHttpResponse outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException {

Class returnValueClass = returnValue.getClass();

HttpServletRequest servletRequest = inputMessage.getServletRequest();
List requestedMediaTypes = getAcceptableMediaTypes(servletRequest);
List producibleMediaTypes = getProducibleMediaTypes(servletRequest, returnValueClass);

Set compatibleMediaTypes = new LinkedHashSet();
for (MediaType r : requestedMediaTypes) {
for (MediaType p : producibleMediaTypes) {
if (r.isCompatibleWith(p)) {
compatibleMediaTypes.add(getMostSpecificMediaType(r, p));
}
}
}
if (compatibleMediaTypes.isEmpty()) {
throw new HttpMediaTypeNotAcceptableException(producibleMediaTypes);
}

List mediaTypes = new ArrayList(compatibleMediaTypes);
MediaType.sortBySpecificityAndQuality(mediaTypes);

MediaType selectedMediaType = null;
for (MediaType mediaType : mediaTypes) {
if (mediaType.isConcrete()) {
selectedMediaType = mediaType;
break;
}
else if (mediaType.equals(MediaType.ALL) || mediaType.equals(MEDIA_TYPE_APPLICATION)) {
selectedMediaType = MediaType.APPLICATION_OCTET_STREAM;
break;
}
}

if (selectedMediaType != null) {
selectedMediaType = selectedMediaType.removeQualityValue();
for (HttpMessageConverter messageConverter : messageConverters) {
if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {
((HttpMessageConverter) messageConverter).write(returnValue, selectedMediaType, outputMessage);
if (logger.isDebugEnabled()) {
logger.debug("Written [" + returnValue + "] as \"" + selectedMediaType + "\" using [" +
messageConverter + "]");
}
return;
}
}
}
throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
}