该接口的设计用到了设计模式中的“策略模式”,spring提供了下面一些实现类:
那么有这么多HandlerMethodReturnValueHandler实现类,在spring在处理请求时是如何选择合适的HandlerMethodReturnValueHandler实现类的呢,这里有一个重要的类:org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite,该类实现中使用了“组合模式”:
public class HandlerMethodReturnValueHandlerComposite implements AsyncHandlerMethodReturnValueHandler {
protected final Log logger = LogFactory.getLog(getClass());
private final List<HandlerMethodReturnValueHandler> returnValueHandlers =
new ArrayList<HandlerMethodReturnValueHandler>();
选择合适的HandlerMethodReturnValueHandler的方法为selectHandler:
private HandlerMethodReturnValueHandler selectHandler(Object value, MethodParameter returnType) {
//调用supportsReturnType方法来选择合适的HandlerMethodReturnValueHandler实现类
boolean isAsyncValue = isAsyncReturnValue(value, returnType);
for (HandlerMethodReturnValueHandler handler : this.returnValueHandlers) {
if (isAsyncValue && !(handler instanceof AsyncHandlerMethodReturnValueHandler)) {
continue;
}
if (handler.supportsReturnType(returnType)) {
return handler;
}
}
return null;
}
HandlerMethodReturnValueHandlerComposite类对外提供的处理http请求的方法如下:
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
//分两步:第一步找到具体的HandlerMethodReturnValueHandler;第二部调用该handler的
//handleReturnValue方法
HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
if (handler == null) {
throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
}
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
spring消息转换就是调用RequestResponseBodyMethodProcessor类的handleReturnValue方法来调用相关消息转换器
代码的:
@Override
public void handleReturnValue(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);
}