概述
笼统一点的说就是导入jackson包,能够使用@ResponseBody,@RequestBody注解,这个不太详细写了,本来就是复习ssm
HttpMessageConverter
概述
使用 HttpMessageConverter 将请求信息转化并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,
Spring 提供了两种途径:
使用 @RequestBody / @ResponseBody 对处理方法进行标注
使用 HttpEntity / ResponseEntity 作为处理方法的入参或返回值
当控制器处理方法使用到 @RequestBody/@ResponseBody 或 HttpEntity/ResponseEntity 时,
Spring 首先根据返回值和返回值类型找到合适的 HandlerMethodReturnValueHandler,
进而根据参数类型或泛型类型的过滤得到匹配的 HttpMessageConverter,
若找不到可用的 HttpMessageConverter 将报错
@RequestBody 和 @ResponseBody 不需要成对出现
示例
流程解析
HttpEntityTest
@RequestMapping("/responseEntity")
public ResponseEntity<String> HttpEntityTest() {
String response = "success";
HttpHeaders headers = new HttpHeaders();
headers.add("response", response);
ResponseEntity responseEntity = new ResponseEntity(response,headers, HttpStatus.OK);
return responseEntity;
}
使用返回值类型是 ResponseEntity<String>举例,其他的返回值类型大差不差,只是调用的实现方法不一样
前面的统一流程
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
||
mav = invokeHandlerMethod(request, response, handlerMethod);
||
invocableMethod.invokeAndHandle(webRequest, mavContainer);
||
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
handleReturnValue
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
--
//根据方法的返回值,返回值类型选择出合适的HandlerMethodReturnValueHandler
--
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
--
//处理器进行返回值处理
--
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
handleReturnValue
@Override
public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
--
//不需要进行页面渲染的,都会设置这个属性值为true,以标志请求处理完成
//后续就不会调用也没有render方法
--
mavContainer.setRequestHandled(true);
if (returnValue == null) {
return;
}
--
//获取请求的输入信息以及要输出的信息
--
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
Assert.isInstanceOf(HttpEntity.class, returnValue);
HttpEntity<?> responseEntity = (HttpEntity<?>) returnValue;
--
//获取信息的Headers headers.add("response", response);
[response:"success"]
--
HttpHeaders outputHeaders = outputMessage.getHeaders();
HttpHeaders entityHeaders = responseEntity.getHeaders();
--
//三个if进行一些别的判断,这里不关注
--
if (!entityHeaders.isEmpty()) {
entityHeaders.forEach((key, value) -> {
if (HttpHeaders.VARY.equals(key) && outputHeaders.containsKey(HttpHeaders.VARY)) {
List<String> values = getVaryRequestHeadersToAdd(outputHeaders, entityHeaders);
if (!values.isEmpty()) {
outputHeaders.setVary(values);
}
}
else {
outputHeaders.put(key, value);
}
});
}
if (responseEntity instanceof ResponseEntity) {
int returnStatus = ((ResponseEntity<?>) responseEntity).getStatusCodeValue();
outputMessage.getServletResponse().setStatus(returnStatus);
if (returnStatus == 200) {
if (SAFE_METHODS.contains(inputMessage.getMethod())
&& isResourceNotModified(inputMessage, outputMessage)) {
// Ensure headers are flushed, no body should be written.
outputMessage.flush();
// Skip call to converters, as they may update the body.
return;
}
}
else if (returnStatus / 100 == 3) {
String location = outputHeaders.getFirst("location");
if (location != null) {
saveFlashAttributes(mavContainer, webRequest, location);
}
}
}
// Try even with null body. ResponseBodyAdvice could get involved.
--
//使用MessageConverters进行数据的输出
--
writeWithMessageConverters(responseEntity.getBody(), returnType, inputMessage, outputMessage);
// Ensure headers are flushed even if no body was written.
outputMessage.flush();
}
writeWithMessageConverters
前面还有一长串的前置判断和赋值,节约空间就不黏贴了
--------------------------
选择出来的媒体类型不为null
---
if (selectedMediaType != null) {
selectedMediaType = selectedMediaType.removeQualityValue();
--
//增强for循环,选择出合适的converter
--
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);
if (body != null) {
Object theBody = body;
LogFormatUtils.traceDebug(logger, traceOn ->
"Writing [" + LogFormatUtils.formatValue(theBody, !traceOn) + "]");
addContentDispositionHeader(inputMessage, outputMessage);
if (genericConverter != null) {
genericConverter.write(body, targetType, selectedMediaType, outputMessage);
}
else {
((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Nothing to write: null body");
}
}
return;
}
}
}
上述writeWithMessageConverters完成后,response里就完成响应值的绑定
messageConverters
问题:messageConverters什么时候有的?
messageConverters只在某些handlerAdapters的returnValueHandlers中存在;
例如:RequestMappingHandlerAdapter
那么RequestMappingHandlerAdapter什么时候有的messageConverters?
还是之前源码说的一样
在AnnotationDrivenBeanDefinitionParser类下,
有public BeanDefinition parse(Element element, ParserContext context) {}这么一个方法
其中有一部分是这样的:
--
在项目启动的时候,根据配置文件、context等获取到messageConverters
--
ManagedList<?> messageConverters = getMessageConverters(element, source, context);
而在getMessageConverters内部,会注册什么样的messageConverters也是已经写好了的
messageConverters部分代码如下:
if (convertersElement == null || Boolean.valueOf(convertersElement.getAttribute("register-defaults"))) {
messageConverters.setSource(source);
messageConverters.add(createConverterDefinition(ByteArrayHttpMessageConverter.class, source));
RootBeanDefinition stringConverterDef = createConverterDefinition(StringHttpMessageConverter.class, source);
stringConverterDef.getPropertyValues().add("writeAcceptCharset", false);
messageConverters.add(stringConverterDef);
messageConverters.add(createConverterDefinition(ResourceHttpMessageConverter.class, source));
messageConverters.add(createConverterDefinition(ResourceRegionHttpMessageConverter.class, source));
messageConverters.add(createConverterDefinition(SourceHttpMessageConverter.class, source));
messageConverters.add(createConverterDefinition(AllEncompassingFormHttpMessageConverter.class, source));
if (romePresent) {
messageConverters.add(createConverterDefinition(AtomFeedHttpMessageConverter.class, source));
messageConverters.add(createConverterDefinition(RssChannelHttpMessageConverter.class, source));
}
……
--
在注册RequestMappingHandlerAdapter的时候,将messageConverters加入进去
--
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
handlerAdapterDef.setSource(source);
handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);
handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);
--
将messageConverters加入
--
handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);
addRequestBodyAdvice(handlerAdapterDef);
addResponseBodyAdvice(handlerAdapterDef);