@@ -423,7 +423,7 @@ initFlashMapManager方法会向容器注册SessionFlashMapManager对象,类图
423423protected void initHandlerMethods() {
424424 // 获取容器中所有的bean
425425 String [] beanNames = (this . detectHandlerMethodsInAncestorContexts ?
426- BeanFactoryUtils . beanNamesForTypeIncludingAncestors(getApplicationContext(), Object . class) : getApplicationContext(). getBeanNamesForType(Object . class));
426+ BeanFactoryUtils . beanNamesForTypeIncludingAncestors(getApplicationContext(), Object . class) : getApplicationContext(). getBeanNamesForType(Object . class));
427427 for (String beanName : beanNames) {
428428 if (! beanName. startsWith(SCOPED_TARGET_NAME_PREFIX )) {
429429 Class<?> beanType = null ;
@@ -960,3 +960,101 @@ protected void renderMergedOutputModel(
960960
961961可以看出,对jsp来说,所谓的渲染其实就是** 将Model中的属性设置到Request,再利用原生Servlet RequestDispatcher API进行转发的过程** 。
962962
963+ # 拾遗
964+
965+ ## @ResponseBody
966+
967+ 通常我们可以在Controller或方法上标注@ResponseBody 注解以表示需要将对象转为JSON并返回给前端,那么Spring MVC是如何自动完成这一过程的呢?
968+
969+ 从前面初始化-容器初始化-容器创建-配置解析一节可以看出,Spring MVC采用org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser进行配置的解析,核心的parse方法中完成了对HttpMessageConverter的初始化。
970+
971+ ### HttpMessageConverter
972+
973+ Spring的HttpMessageConverter接口负责HTTP请求-Java对象与Java对象-响应之间的转换。我们以Spring默认使用的Jackson转换器为例,类图:
974+
975+ ![ HttpMessageConverter] ( images/HttpMessageConverter.jpg )
976+
977+ HttpMessageConverter实现的初始化由AnnotationDrivenBeanDefinitionParser的getMessageConverters方法完成,HttpMessageConverter的来源分为自定义和默认。
978+
979+ 示例配置:
980+
981+ ``` xml
982+ <mvc : annotation-driven >
983+ <mvc : message-converters register-defaults =" true" >
984+ <bean class =" test.Converter" />
985+ </mvc : message-converters >
986+ </mvc : annotation-driven >
987+ ```
988+
989+ #### 自定义
990+
991+ Spring允许我们通过XML配置文件的message-converters元素来进行自定义。
992+
993+ #### 默认
994+
995+ 当** 检测到没有配置message-converters元素或者register-defaults="true"时Spring便会注册默认转换器** 。这其中便包括MappingJacksonHttpMessageConverter,相关源码:
996+
997+ ``` java
998+ else if (jacksonPresent) {
999+ messageConverters. add(createConverterDefinition(
1000+ org.springframework.http.converter.json. MappingJacksonHttpMessageConverter . class, source));
1001+ }
1002+ ```
1003+
1004+ jacksonPresent声明:
1005+
1006+ ``` java
1007+ private static final boolean jacksonPresent =
1008+ ClassUtils . isPresent(" org.codehaus.jackson.map.ObjectMapper" , AnnotationDrivenBeanDefinitionParser . class. getClassLoader()) &&
1009+ ClassUtils . isPresent(" org.codehaus.jackson.JsonGenerator" , AnnotationDrivenBeanDefinitionParser . class. getClassLoader());
1010+ ```
1011+
1012+ ### 转换
1013+
1014+ 入口位于ServletInvocableHandlerMethod的invokeAndHandle方法对于响应的处理:
1015+
1016+ ``` java
1017+ this . returnValueHandlers. handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
1018+ ```
1019+
1020+ returnValueHandlers其实就是RequestMappingHandlerAdapter内部的returnValueHandlers,后者由RequestMappingHandlerAdapter的afterPropertiesSet方法初始化,关键在于:
1021+
1022+ ``` java
1023+ handlers. add(new RequestResponseBodyMethodProcessor (getMessageConverters(), this . contentNegotiationManager));
1024+ ```
1025+
1026+ 对象到JSON的转换正是由RequestResponseBodyMethodProcessor完成,ServletInvocableHandlerMethod通过supportsReturnType方法决定HandlerMethodReturnValueHandler是否可以处理当前返回类型或返回方法,RequestResponseBodyMethodProcessor的实现:
1027+
1028+ ``` java
1029+ @Override
1030+ public boolean supportsReturnType(MethodParameter returnType) {
1031+ return ((AnnotationUtils . findAnnotation(returnType. getContainingClass(), ResponseBody . class) != null ) ||
1032+ (returnType. getMethodAnnotation(ResponseBody . class) != null ));
1033+ }
1034+ ```
1035+
1036+ 核心的handleReturnValue方法:
1037+
1038+ ``` java
1039+ @Override
1040+ public void handleReturnValue(Object returnValue, MethodParameter returnType,
1041+ ModelAndViewContainer mavContainer, NativeWebRequest webRequest) {
1042+ mavContainer. setRequestHandled(true );
1043+ if (returnValue != null ) {
1044+ writeWithMessageConverters(returnValue, returnType, webRequest);
1045+ }
1046+ }
1047+ ```
1048+
1049+ 这里其实是通过HttpMessageConverter的canRead或canWrite方法来判断给定的转换器是否合适,canWrite方法实现:
1050+
1051+ ``` java
1052+ @Override
1053+ public boolean canWrite(Class<?> clazz, MediaType mediaType) {
1054+ return (this . objectMapper. canSerialize(clazz) && canWrite(mediaType));
1055+ }
1056+ ```
1057+
1058+ 这里剩下的便是Jackson的事情了,注意MappingJacksonHttpMessageConverter中的objectMapper被所有的线程所共享,因为其是线程安全的,但是这样是否有性能问题?
1059+
1060+ //TODO HandlerMethodReturnValueHandler是神马?
0 commit comments