- HttpInputMessage
HttpInputMessage是对一次Http请求报文的抽象。接口定义了getBody方法用于得到http请求的InputStream对象。具体的接口定义如下:
package org.springframework.http;
import java.io.IOException;
import java.io.InputStream;
public interface HttpInputMessage extends HttpMessage {
/**
* Return the body of the message as an input stream.
* @return the input stream body
* @throws IOException in case of I/O Errors
*/
InputStream getBody() throws IOException;
}
- HttpOutputMessage
HttpOutputMessage是SpringMVC内部对一次Http响应报文的抽象,接口定义了getBody方法用于得到输出数据的OutputStream对象。源码如下:
package org.springframework.http;
import java.io.IOException;
import java.io.OutputStream;
public interface HttpOutputMessage extends HttpMessage {
/**
* Return the body of the message as an output stream.
* @return the output stream body
* @throws IOException in case of I/O Errors
*/
OutputStream getBody() throws IOException;
}
- HttpMessageConverter
对消息转换器最高层次的接口抽象,描述了一个消息转换器的一般特征。源代码如下:
package org.springframework.http.converter;
import java.io.IOException;
import java.util.List;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
public interface HttpMessageConverter<T> {
//根据clazz与mediaType判断当前Converter是否能进行读操作
boolean canRead(Class<?> clazz, MediaType mediaType);
//根据clazz与mediaType判断当前Converter是否能进行写操作
boolean canWrite(Class<?> clazz, MediaType mediaType);
//得到支持的MediaType
List<MediaType> getSupportedMediaTypes();
//读方法 通过inputMessage能够得到http的输入流,然后转成业务对象T
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
//写方法,通过outputMessage能够得到http的输出流,然后将T对象写出
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
光有接口定义是不行的, 还得有具体的实现才能够实现请求报文与对象之间的转换,下面我们来看看我们熟悉的json对象是如何来进行转换的。我们实际的业务会用到阿里的fastjson,fastjson通过FastJsonHttpMessageConverter这个类来实现对json数据的转换,我们先来看看FastJsonHttpMessageConverter的父类AbstractHttpMessageConverter的逻辑,代码如下:
package org.springframework.http.converter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> {
protected final Log logger = LogFactory.getLog(getClass());
//这里维护了支持的MediaType类型,是个集合对象
private List<MediaType> supportedMediaTypes = Collections.emptyList();
//下面三个方法是构造方法,
protected AbstractHttpMessageConverter() {
}
//这里需要传入一个MediaType对象
protected AbstractHttpMessageConverter(MediaType supportedMediaType) {
setSupportedMediaTypes(Collections.singletonList(supportedMediaType));
}
//这里需要传入一组MediaType对象
protected AbstractHttpMessageConverter(MediaType... supportedMediaTypes) {
setSupportedMediaTypes(Arrays.asList(supportedMediaTypes));
}
//对MediaType集合进行初使化
public void setSupportedMediaTypes(List<MediaType> supportedMediaTypes) {
Assert.notEmpty(supportedMediaTypes, "'supportedMediaTypes' must not be empty");
this.supportedMediaTypes = new ArrayList<MediaType>(supportedMediaTypes);
}
//得到支持的MediaType对象,通过Collections.unmodifiableList来防止外部进行修改
public List<MediaType> getSupportedMediaTypes() {
return Collections.unmodifiableList(this.supportedMediaTypes);
}
//这里实现了canRead方法,分为了两部,一个看clazz是否支持,一个看MediaType是否支持
public boolean canRead(Class<?> clazz, MediaType mediaType) {
return supports(clazz) && canRead(mediaType);
}
//这里提供了canRead的默认实现
protected boolean canRead(MediaType mediaType) {
if (mediaType == null) {
return true;
}
for (MediaType supportedMediaType : getSupportedMediaTypes()) {
if (supportedMediaType.includes(mediaType)) {
return true;
}
}
return false;
}
//这是canWrite方法,同样分为根据class与MediaType进行判断
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return supports(clazz) && canWrite(mediaType);
}
//提供的默认实现
protected boolean canWrite(MediaType mediaType) {
if (mediaType == null || MediaType.ALL.equals(mediaType)) {
return true;
}
for (MediaType supportedMediaType : getSupportedMediaTypes()) {
if (supportedMediaType.isCompatibleWith(mediaType)) {
return true;
}
}
return false;
}
//read方法,内部抽象了readInternal留给子类实现
public final T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException {
return readInternal(clazz, inputMessage);
}
//write方法,首先处理需要写入header的类型与长度,并提供writeInternal方法留给子类实现,最后调用flash方法将数据写入到客户端
public final void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
HttpHeaders headers = outputMessage.getHeaders();
if (headers.getContentType() == null) {
if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) {
contentType = getDefaultContentType(t);
}
if (contentType != null) {
headers.setContentType(contentType);
}
}
if (headers.getContentLength() == -1) {
Long contentLength = getContentLength(t, headers.getContentType());
if (contentLength != null) {
headers.setContentLength(contentLength);
}
}
writeInternal(t, outputMessage);
outputMessage.getBody().flush();
}
//返回默认的MediaType
protected MediaType getDefaultContentType(T t) throws IOException {
List<MediaType> mediaTypes = getSupportedMediaTypes();
return (!mediaTypes.isEmpty() ? mediaTypes.get(0) : null);
}
//得到数据的长度
protected Long getContentLength(T t, MediaType contentType) throws IOException {
return null;
}
//子类需要实现的方法
protected abstract boolean supports(Class<?> clazz);
//这里实现读数据的功能
protected abstract T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
//这里实现写数据的功能
protected abstract void writeInternal(T t, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
从上面的代码分析,我们只需要关注FastJsonHttpMessageConverter类里的supports, readInternal与writeInternal方法,源码如下:
public class FastJsonHttpMessageConverter //
extends AbstractHttpMessageConverter<Object> //
implements GenericHttpMessageConverter<Object> {
//supports方法里可以解析任何对象
@Override
protected boolean supports(Class<?> clazz) {
return true;
}
// 这里实现将输入流转成clazz对象
@Override
protected Object readInternal(Class<? extends Object> clazz, //
HttpInputMessage inputMessage //
) throws IOException, HttpMessageNotReadableException {
InputStream in = inputMessage.getBody();
return JSON.parseObject(in, fastJsonConfig.getCharset(), clazz, fastJsonConfig.getFeatures());
}
//这里是写入数据的逻辑,将obj对象通过outputMessage写入,其中还会将数据的长度写入到http的头信息里
@Override
protected void writeInternal(Object obj, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
HttpHeaders headers = outputMessage.getHeaders();
ByteArrayOutputStream outnew = new ByteArrayOutputStream();
int len = JSON.writeJSONString(outnew, //
fastJsonConfig.getCharset(), //
obj, //
fastJsonConfig.getSerializeConfig(), //
fastJsonConfig.getSerializeFilters(), //
fastJsonConfig.getDateFormat(), //
JSON.DEFAULT_GENERATE_FEATURE, //
fastJsonConfig.getSerializerFeatures());
if (fastJsonConfig.isWriteContentLength()) {
headers.setContentLength(len);
}
OutputStream out = outputMessage.getBody();
outnew.writeTo(out);
outnew.close();
}
}
知道了HttpMessageConverter是如何进行类型转换的了,下一步就需要知道在Spring MVC里,HttpMessageConverter在那里起作用的。我们知道在Spring MVC里有两个很重要的解色,一个是HandlerMapping 用于将请求的url转到具体处理的请求Controller(Handler)上,职责为查找Handler, 另一个是 HandlerAdapter ,用于适配Handler,DispatcherServlet将不同Handler的调用职责转交给HandlerAdapter。从职责划分上我们可以很容易的猜想这是在某一个HandlerAdapter会调用的逻辑啦。我们以RequestMappingHandlerAdapter为入口来看看Spring MVC内部是如何处理类型转换的。以下是部分关键代码:
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware,
InitializingBean {
//HandlerAdapter内部持有的对象
private List<HandlerMethodArgumentResolver> customArgumentResolvers;
private HandlerMethodArgumentResolverComposite argumentResolvers;
private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers;
private List<HandlerMethodReturnValueHandler> customReturnValueHandlers;
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
private List<ModelAndViewResolver> modelAndViewResolvers;
private List<HttpMessageConverter<?>> messageConverters;
//默认的构造方法,里面有我们熟悉的HttpMessageConverter对象
public RequestMappingHandlerAdapter() {
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false); // See SPR-7316
this.messageConverters = new ArrayList<HttpMessageConverter<?>>();
this.messageConverters.add(new ByteArrayHttpMessageConverter());
this.messageConverters.add(stringHttpMessageConverter);
this.messageConverters.add(new SourceHttpMessageConverter<Source>());
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
}
//**
**这个方法是HandlerAdapter的核心方法, 里面有我们熟悉的ModelAndView 做为方法的返回值
**//
@Override
protected final ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
// Always prevent caching in case of session attribute management.
checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
}
else {
// Uses configured default cacheSeconds setting.
checkAndPrepare(request, response, true);
}
// Execute invokeHandlerMethod in synchronized block if required.
if (this.synchronizeOnSession) {
HttpSession session = request.getSession(false);
if (session != null) {
Object mutex = WebUtils.getSessionMutex(session);
synchronized (mutex) {
return invokeHandleMethod(request, response, handlerMethod);
}
}
}
//最终会调用invokeHandleMethod方法
return invokeHandleMethod(request, response, handlerMethod);
}
//这个方法里会处理请求类型的转换与返回对象的转换
private ModelAndView invokeHandleMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
//这里面会处理会处理请求数据到对象的转换
ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.setTaskExecutor(this.taskExecutor);
asyncManager.setAsyncWebRequest(asyncWebRequest);
asyncManager.registerCallableInterceptors(this.callableInterceptors);
asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
if (asyncManager.hasConcurrentResult()) {
Object result = asyncManager.getConcurrentResult();
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
asyncManager.clearConcurrentResult();
if (logger.isDebugEnabled()) {
logger.debug("Found concurrent result value [" + result + "]");
}
requestMappingMethod = requestMappingMethod.wrapConcurrentResult(result);
}
//最终处理还是在这个ServletInvocableHandlerMethod对象里处理啦
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
//这里构造了ServletInvocableHandlerMethod 对象,用于hanlder方法的调用
private ServletInvocableHandlerMethod createRequestMappingMethod(
HandlerMethod handlerMethod, WebDataBinderFactory binderFactory) {
ServletInvocableHandlerMethod requestMethod;
requestMethod = new ServletInvocableHandlerMethod(handlerMethod);
//argumentResolvers用于处理请求数据
requestMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
//returnValueHandlers用于处理返回数据 requestMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
requestMethod.setDataBinderFactory(binderFactory);
requestMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
return requestMethod;
}
//这个方法会在Spring IOC容器初使化的时候调用,里面初使化好了argumentResolvers , returnValueHandlers 对象
public void afterPropertiesSet() {
if (this.argumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers();
this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.initBinderArgumentResolvers == null) {
List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers();
this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers);
}
if (this.returnValueHandlers == null) {
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
initControllerAdviceCache();
}
//这个方法里把处理handler method方法里参数的ArgumentResolver统一放到集合对象里
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
//这里有我们熟悉的PathVariableMethodArgumentResolver
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
//这里就是我们文章开口说的@RequestBody与ResponseBody啦
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
//返回对象的handler
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();
// Single-purpose return value types
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
// Annotation-based return value types
handlers.add(new ModelAttributeMethodProcessor(false));
//这里有处理文章开头说的@RequestBody和@ResponseBody两个注释的处理逻辑
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
// Multi-purpose return value types
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
// Custom return value types
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
// Catch-all
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
handlers.add(new ModelAttributeMethodProcessor(true));
}
return handlers;
}
}
上面对关键代码进行了相应的注释,我们从handleInternal方法跟踪到invokeHandleMethod方法里,发现最终处理请求对象与返回对象的是一个叫ServletInvocableHandlerMethod的对象,下面来看看ServletInvocableHandlerMethod的关键代码
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
public final void invokeAndHandle(ServletWebRequest webRequest,
ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
//invokeForRequest方法里应该就是调用逻辑了
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
setResponseStatus(webRequest);
if (returnValue == null) {
if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(this.responseReason)) {
mavContainer.setRequestHandled(true);
return;
}
mavContainer.setRequestHandled(false);
//下面的方法会处理返回的对象,通过returnValueHandlers集合对象
try {
this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(getReturnValueHandlingErrorMessage("Error handling return value", returnValue), ex);
}
throw ex;
}
}
//这个方法是InvocableHandlerMethod类里的,为了方便展示我们放到这里一起注释
public final Object invokeForRequest(NativeWebRequest request,
ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//这里得到method里的参数
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
if (logger.isTraceEnabled()) {
StringBuilder builder = new StringBuilder("Invoking [");
builder.append(this.getMethod().getName()).append("] method with arguments ");
builder.append(Arrays.asList(args));
logger.trace(builder.toString());
}
//根据args调用具体的handler方法
Object returnValue = invoke(args);
if (logger.isTraceEnabled()) {
logger.trace("Method [" + this.getMethod().getName() + "] returned [" + returnValue + "]");
}
//返回handler方法返回的对象
return returnValue;
}
//这个方法一样是InvocableHandlerMethod类里的
private Object[] getMethodArgumentValues(
NativeWebRequest request, ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
//得到方法的所有参数
MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
//遍历方法里的每一个参数
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
parameter.initParameterNameDiscovery(parameterNameDiscoverer);
GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
args[i] = resolveProvidedArgument(parameter, providedArgs);
if (args[i] != null) {
continue;
}
//argumentResolvers就是上面接到的集合对象,里面存了不同的ArgumentResolver对象
if (argumentResolvers.supportsParameter(parameter)) {
try {
args[i] = argumentResolvers.resolveArgument(parameter, mavContainer, request, dataBinderFactory);
continue;
} catch (Exception ex) {
if (logger.isTraceEnabled()) {
logger.trace(getArgumentResolutionErrorMessage("Error resolving argument", i), ex);
}
throw ex;
}
}
if (args[i] == null) {
String msg = getArgumentResolutionErrorMessage("No suitable resolver for argument", i);
throw new IllegalStateException(msg);
}
}
return args;
}
//这里会调用HandlerMethodArgumentResolver 处理具体的方法参数
public Object resolveArgument(
MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
throws Exception {
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
Assert.notNull(resolver, "Unknown parameter type [" + parameter.getParameterType().getName() + "]");
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
}
通过上面代码的分析我们可以很清晰的知道ServletInvocableHandlerMethod最终通过HandlerMethodArgumentResolvers与HandlerMethodReturnValueHandlers这两个集合对象来分别处理http请求数据到handler方法里参数的转换与返回对象转成希望输出的对象 。下面分别来看看这两个集合里存的对象都是如何处理数据的,首先是HandlerMethodArgumentResolver类的接口定义:
package org.springframework.web.method.support;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
public interface HandlerMethodArgumentResolver {
//用于判断当前ArgumentResolver是否支持这种类型转换
boolean supportsParameter(MethodParameter parameter);
//具体的转换方法
Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception;
}
HandlerMethodReturnValueHandler接口的定义如下:
public interface HandlerMethodReturnValueHandler {
boolean supportsReturnType(MethodParameter returnType);
void handleReturnValue(Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception;
}
我们重点关注的RequestResponseBodyMethodProcessor同时继承了上面两个接口,所以他能够处理@RequestBody和@ResponseBody这两个注释啦,下面看一下关键代码:
public class RequestResponseBodyMethodProcessor extends AbstractMessageConverterMethodProcessor {
//这里看参数是否有增加RequestBody注解
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestBody.class);
}
//这里看返回的对象是否有RequestBody注解
public boolean supportsReturnType(MethodParameter returnType) {
return returnType.getMethodAnnotation(ResponseBody.class) != null;
}
//这里的方法会处理请求参数的逻辑
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//通过readWithMessageConverters这个方法名我们可算看到了MessageConverter了
Object argument = readWithMessageConverters(webRequest, parameter, parameter.getGenericParameterType());
String name = Conventions.getVariableNameForParameter(parameter);
WebDataBinder binder = binderFactory.createBinder(webRequest, argument, name);
if (argument != null) {
validate(binder, parameter);
}
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
return argument;
}
// 这个方法里应该会调用我们上面说的HttpMessageConverter
@Override
protected <T> Object readWithMessageConverters(NativeWebRequest webRequest,
MethodParameter methodParam, Type paramType) throws IOException, HttpMediaTypeNotSupportedException {
//这里封培训HttpInputMessage对象,这个对象我们文章开头就提过了
final HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
HttpInputMessage inputMessage = new ServletServerHttpRequest(servletRequest);
RequestBody annot = methodParam.getParameterAnnotation(RequestBody.class);
if (!annot.required()) {
InputStream inputStream = inputMessage.getBody();
if (inputStream == null) {
return null;
}
else if (inputStream.markSupported()) {
inputStream.mark(1);
if (inputStream.read() == -1) {
return null;
}
inputStream.reset();
}
else {
final PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
int b = pushbackInputStream.read();
if (b == -1) {
return null;
}
else {
pushbackInputStream.unread(b);
}
inputMessage = new ServletServerHttpRequest(servletRequest) {
@Override
public InputStream getBody() throws IOException {
// Form POST should not get here
return pushbackInputStream;
}
};
}
}
return super.readWithMessageConverters(inputMessage, methodParam, paramType);
}
//这个方法是RequestResponseBodyMethodProcessor的父类AbstractMessageConverterMethodProcessor里的方法,为了方便看源码,我们把这个方法也放到这里注释
@SuppressWarnings("unchecked")
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage,
MethodParameter methodParam, Type targetType) throws IOException, HttpMediaTypeNotSupportedException {
MediaType contentType = inputMessage.getHeaders().getContentType();
if (contentType == null) {
contentType = MediaType.APPLICATION_OCTET_STREAM;
}
Class<?> contextClass = methodParam.getDeclaringClass();
Map<TypeVariable, Type> map = GenericTypeResolver.getTypeVariableMap(contextClass);
Class<T> targetClass = (Class<T>) GenericTypeResolver.resolveType(targetType, map);
//这里调用我们熟悉的HttpMessageConverter对象
for (HttpMessageConverter<?> converter : this.messageConverters) {
if (converter instanceof GenericHttpMessageConverter) {
GenericHttpMessageConverter genericConverter = (GenericHttpMessageConverter) converter;
if (genericConverter.canRead(targetType, contextClass, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Reading [" + targetType + "] as \"" +
contentType + "\" using [" + converter + "]");
}
return genericConverter.read(targetType, contextClass, inputMessage);
}
}
if (targetClass != null) {
if (converter.canRead(targetClass, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Reading [" + targetClass.getName() + "] as \"" +
contentType + "\" using [" + converter + "]");
}
return ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage);
}
}
}
throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
}
//这个方法是处理返回对象的方法了,会调用到父类里writeWithMessageConverters方法
public void handleReturnValue(Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException {
mavContainer.setRequestHandled(true);
if (returnValue != null) {
writeWithMessageConverters(returnValue, returnType, webRequest);
}
}
//这个方法是AbstractMessageConverterMethodProcessor类的方法,方法里分别构造了inputMessage与outputMessage对象,然后调用writeWithMessageConverters方法处理
protected <T> void writeWithMessageConverters(T returnValue,
MethodParameter returnType,
NativeWebRequest webRequest)
throws IOException, HttpMediaTypeNotAcceptableException {
ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}
//这个方法也是父类AbstractMessageConverterMethodProcessor类的方法
@SuppressWarnings("unchecked")
protected <T> void writeWithMessageConverters(T returnValue,
MethodParameter returnType,
ServletServerHttpRequest inputMessage,
ServletServerHttpResponse outputMessage)
throws IOException, HttpMediaTypeNotAcceptableException {
Class<?> returnValueClass = returnValue.getClass();
HttpServletRequest servletRequest = inputMessage.getServletRequest();
//这里看到了熟悉的MediaType对象
List<MediaType> requestedMediaTypes = getAcceptableMediaTypes(servletRequest);
List<MediaType> producibleMediaTypes = getProducibleMediaTypes(servletRequest, returnValueClass);
Set<MediaType> compatibleMediaTypes = new LinkedHashSet<MediaType>();
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<MediaType> mediaTypes = new ArrayList<MediaType>(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();
//看看messageConverters里的对象那个可以处理当前对象,最终还是调用HttpMessageConverter的write方法
for (HttpMessageConverter<?> messageConverter : messageConverters) {
if (messageConverter.canWrite(returnValueClass, selectedMediaType)) {
((HttpMessageConverter<T>) messageConverter).write(returnValue, selectedMediaType, outputMessage);
if (logger.isDebugEnabled()) {
logger.debug("Written [" + returnValue + "] as \"" + selectedMediaType + "\" using [" +
messageConverter + "]");
}
return;
}
}
}
throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
}
}
到这里我们分析了整个的处理流程,下面我们总结一个各个对象的作用:
- HttpMessageConverter 这个对象用于处理http请求数据到handler方法参数的转换,同时也处理handler方法返回对象输出到浏览器数据的转换。
- HttpInputMessage用于抽象请求报文对象,可以简单理解为Servlet里的HttpRequest对象
- HttpOutputMessage用于抽象响应报文对象,可以简单理解为Servlet里的HttpResponse对象
- HandlerAdapter 对象是Spring MVC里最重要的对象,他对我们的handler(业务系统里写的Controller)进行了包装,这样在Spring MVC里任务对象都可以做为Controller,只要提供合适的HandlerAdapter。
- HandlerMethodArgumentResolver 用于处理handler方法的参数转换
- HandlerMethodReturnValueHandler 用于处理handler返回对象的转换
- RequestResponseBodyMethodProcessor 这个同时实现了HandlerMethodArgumentResolver与HandlerMethodReturnValueHandler内部通过注入的HttpMessageConverter集合来转换对象
上面代码里的messageConverters是从那里来的呢,这里具体可以参考org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser这个类里的源码。此类处理了spring mvc配置文件里<mvc:annotation-driven>这个标签里的逻辑。 - HttpMessageConverter 用于处理请求的Body部分的数据,而非Body部分的数据转换用的还是Spring Convert。
使用FastJsonHttpMessageConverter踩坑
1:在用FastJsonHttpMessageConverter将json转成请求对象的时候,如果请求的类型为application/json。需要在supportedMediaTypes属性配置<value>application/json;charset=UTF-8</value>。关键配置如下:
<mvc:annotation-driven conversion-service="conversionService">
<mvc:message-converters register-defaults="true">
<bean
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
<property name="features">
<array>
<value>WriteDateUseDateFormat</value>
<value>WriteMapNullValue</value>
<value>WriteNullStringAsEmpty</value>
</array>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
注意上面的mvc:message-converters是用于将http请求的body对象进行转换的。而conversion-service="conversionService"会对如通过URL,Header,对象进行转换,这是两套不同的转换体系。