与上篇类似,HandlerMethodReturnValueHandler是对返回值的解析,相关的注解有, 用法也基本一样 先看看源码,打开类RequestResponseBodyMethodProcessor,这个类是对@RequestBody和@ResponseBody进行整合的一个类,本篇只解析@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)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
//对请求体和响应体进行封装,将返回值写入响应流里,
mavContainer.setRequestHandled(true);
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
// Try even with null return value. ResponseBodyAdvice could get involved.
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
protected <T> void writeWithMessageConverters(@Nullable T value, MethodParameter returnType,
ServletServerHttpRequest inputMessage, ServletServerHttpResponse outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {
Object outputValue;
Class<?> valueType;
Type declaredType;
//返回值是否是String类型 进行类型转换
if (value instanceof CharSequence) {
outputValue = value.toString();
valueType = String.class;
declaredType = String.class;
}
else {
outputValue = value;
valueType = getReturnValueType(outputValue, returnType);
declaredType = getGenericType(returnType);
}
//
if (isResourceType(value, returnType)) {
outputMessage.getHeaders().set(HttpHeaders.ACCEPT_RANGES, "bytes");
if (value != null && inputMessage.getHeaders().getFirst(HttpHeaders.RANGE) != null) {
Resource resource = (Resource) value;
try {
List<HttpRange> httpRanges = inputMessage.getHeaders().getRange();
outputMessage.getServletResponse().setStatus(HttpStatus.PARTIAL_CONTENT.value());
outputValue = HttpRange.toResourceRegions(httpRanges, resource);
valueType = outputValue.getClass();
declaredType = RESOURCE_REGION_LIST_TYPE;
}
catch (IllegalArgumentException ex) {
outputMessage.getHeaders().set(HttpHeaders.CONTENT_RANGE, "bytes */" + resource.contentLength());
outputMessage.getServletResponse().setStatus(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value());
}
}
}
List<MediaType> mediaTypesToUse;
//包装响应头 响应类型等参数
MediaType contentType = outputMessage.getHeaders().getContentType();
if (contentType != null && contentType.isConcrete()) {
mediaTypesToUse = Collections.singletonList(contentType);
}
else {
HttpServletRequest request = inputMessage.getServletRequest();
List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(request);
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(request, valueType, declaredType);
if (outputValue != null && producibleMediaTypes.isEmpty()) {
throw new HttpMessageNotWritableException(
"No converter found for return value of type: " + valueType);
}
......
//将值写入response里,然后封装为对象返回到前端
if (selectedMediaType != null) {
selectedMediaType = selectedMediaType.removeQualityValue();
for (HttpMessageConverter<?> converter : this.messageConverters) {
GenericHttpMessageConverter genericConverter =
(converter instanceof GenericHttpMessageConverter ? (GenericHttpMessageConverter<?>) converter : null);
//这里是进行格式转换器进行判断(xml/json等)
if (genericConverter != null ?
((GenericHttpMessageConverter) converter).canWrite(declaredType, valueType, selectedMediaType) :
converter.canWrite(valueType, selectedMediaType)) {
outputValue = (T) getAdvice().beforeBodyWrite(outputValue, returnType, selectedMediaType,
(Class<? extends HttpMessageConverter<?>>) converter.getClass(),
inputMessage, outputMessage);
if (outputValue != null) {
addContentDispositionHeader(inputMessage, outputMessage);
if (genericConverter != null) {
genericConverter.write(outputValue, declaredType, selectedMediaType, outputMessage);
}
else {
((HttpMessageConverter) converter).write(outputValue, selectedMediaType, outputMessage);
}
}
}
}
if (outputValue != null) {
throw new HttpMediaTypeNotAcceptableException(this.allSupportedMediaTypes);
}
}
package org.choviwu.movie.config;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.choviwu.movie.annotation.Response;
import org.choviwu.movie.util.JsonUtils;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@Slf4j
public class ResponseHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
private final HandlerMethodReturnValueHandler handlerMethodReturnValueHandler;
/**
* 定义默认构造,为了让此类拦截返回值然后用@ResponseBody执行器执行包装
* @param handlerMethodReturnValueHandler
*/
public ResponseHandlerMethodReturnValueHandler(HandlerMethodReturnValueHandler handlerMethodReturnValueHandler) {
this.handlerMethodReturnValueHandler = handlerMethodReturnValueHandler;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseBody.class));
}
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
// Object result = returnValue;
Map map = Maps.newHashMap();
map.put("code", 0);
map.put("msg", "success");
map.put("data", returnValue);
mavContainer.setRequestHandled(true);
log.info(">>>>>>>>>>>>>>>>Return Value : {}", JsonUtils.toJson(map));
//包装好对象之后,实际执行者为responseReturnHandler
handlerMethodReturnValueHandler.handleReturnValue(map, returnType, mavContainer, webRequest);
}
}
package org.choviwu.movie.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.method.annotation.RequestParamMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.List;
/**
* @author Administrator
*/
@Configuration
public class WebConfig extends WebMvcConfigurationSupport implements InitializingBean{
@Autowired
RequestMappingHandlerAdapter requestMappingHandlerAdapter;
@Override
public void afterPropertiesSet() throws Exception {
List<HandlerMethodReturnValueHandler> unmodifiableList = requestMappingHandlerAdapter.getReturnValueHandlers();
List<HandlerMethodReturnValueHandler> list = new ArrayList<>(unmodifiableList.size());
for (HandlerMethodReturnValueHandler returnValueHandler : unmodifiableList) {
if (returnValueHandler instanceof RequestResponseBodyMethodProcessor) {
//将RequestResponseBodyMethodProcessor 实际返回值替换为自定义的,实际执行为RequestResponseBodyMethodProcessor
//重要
ResponseHandlerMethodReturnValueHandler handler = new ResponseHandlerMethodReturnValueHandler(returnValueHandler);
list.add(handler);
}
else {
list.add(returnValueHandler);
}
}
requestMappingHandlerAdapter.setReturnValueHandlers(list);
}
}
这里就配置完毕,验证成功