Contexte
-
Quel est le format des données renvoyées par @ResponseBody par défaut? L'interface d'arrière-plan dite par défaut ne spécifie pas Produit MediaType
@Controller
public class DemoController {
@ResponseBody
@GetMapping(value = "/demo")
public DemoVO demo() {
return new DemoVO("lengleng", "123456");
}
}
复制代码
-
En utilisant Baidu pour rechercher la réponse la mieux classée de @ ResponseBody, le rôle de @ ResponseBody est en fait de convertir des objets java en données au format json.
Bonne réponse
Publions d'abord la bonne réponse.
@ResponseBody format de sortie, en fonction par défaut du client en- Accept
tête de demande.
Analyse du code source
-
RequestResponseBodyMethodProcessor
public class RequestResponseBodyMethodProcessor {
// 处理 ResponseBody 标注的方法
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
}
// 处理返回值
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) {
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// 处理返回值
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
}
复制代码
-
writeWithMessageConverters
protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType, ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage) { HttpServletRequest request = inputMessage.getServletRequest(); // 获取请求头中的目标资源类型 List<MediaType> acceptableTypes = getAcceptableMediaTypes(request); // 获取接口指定支持的资源类型 List<MediaType> producibleTypes = getProducibleMediaTypes(request, valueType, targetType); // 获取能够输出资源类型 List<MediaType> mediaTypesToUse = new ArrayList<>(); for (MediaType requestedType : acceptableTypes) { for (MediaType producibleType : producibleTypes) { if (requestedType.isCompatibleWith(producibleType)) { mediaTypesToUse.add(getMostSpecificMediaType(requestedType, producibleType)); } } } /// 排序 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(); // 查找支持选中资源类型的 HttpMessageConverter,输出body for (HttpMessageConverter<?> converter : this.messageConverters) { GenericHttpMessageConverter genericConverter = (converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null); if (genericConverter != null ? ((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) : converter.canWrite(valueType, selectedMediaType)) { body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType, (Class<? extends HttpMessageConverter<?>>) converter.getClass(), inputMessage, outputMessage); return; } } } 复制代码
Pourquoi devrais-je étudier ce problème
-
Lors de la mise à niveau du spring cloud alibaba 2.2.1
temps, le module SENTINELLE introduire dépendant suivant
-
Lorsque le fichier de format de données apparaît dans la dépendance, RestTemplate augmente dans l'en-tête de demande Accept par défaut
application / xml | texte / xml | application / * + xml
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");
}
复制代码
-
Lorsque nous utilisons RestTemplate pour appeler l'interface, XML sera retourné si Accept n'est pas spécifié, ce qui se traduit par une mise à niveau fluide