本文使用的demo基于maven,是根据入门blog的例子继续写下去的。
我们先来看一看对应的现象。 我们这里的配置文件 *-dispatcher.xml中的关键配置如下(其他常规的配置文件不在讲解,可参考本文一开始提到的入门blog):
(视图配置省略)
<mvc:resources location="/static/" mapping="/static/**"/> <mvc:annotation-driven/> <context:component-scan base-package="org.format.demo.controller"/>
pom中需要有以下依赖(Spring依赖及其他依赖不显示):
<dependency> <groupId>org.codehaus.jackson</groupId> jackson-core-asl <version>1.9.13</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> jackson-mapper-asl <version>1.9.13</version> </dependency>
这个依赖是json序列化的依赖。
ok。我们在Controller中添加一个method:
@RequestMapping(“/xmlOrJson”) @ResponseBody public Map<String, Object> xmlOrJson() { Map<String, Object> map = new HashMap<String, Object>(); map.put(“list”, employeeService.list()); return map; }
直接访问地址:
我们看到,短短几行配置。使用@ResponseBody注解之后,Controller返回的对象 自动被转换成对应的json数据,在这里不得不感叹SpringMVC的强大。
我们好像也没看到具体的配置,唯一看到的就是*-dispatcher.xml中的一句配置: mvc:annotation-driven/ 。其实就是这个配置,导致了java对象自动转换成json对象的现象。
那么spring到底是如何实现java对象到json对象的自动转换的呢? 为什么转换成了json数据,如果想转换成xml数据,那该怎么办?
源码分析
本文使用的spring版本是4.0.2。
在讲解 mvc:annotation-driven/ 这个配置之前,我们先了解下Spring的消息转换机制。@ResponseBody这个注解就是使用消息转换机制,最终通过json的转换器转换成json数据的。
HttpMessageConverter接口就是Spring提供的http消息转换接口。有关这方面的知识大家可以参考”参考资料”中的 第二条链接 ,里面讲的很清楚。
下面开始分析 mvc:annotation-driven/ 这句配置:
这句代码在spring中的解析类是:
在AnnotationDrivenBeanDefinitionParser源码的152行parse方法中:
分别实例化了RequestMappingHandlerMapping,ConfigurableWebBindingInitializer,RequestMappingHandlerAdapter等诸多类。
其中 RequestMappingHandlerMapping和RequestMappingHandlerAdapter 这两个类比较重要。
RequestMappingHandlerMapping处理请求映射的,处理@RequestMapping跟请求地址之间的关系。
RequestMappingHandlerAdapter是请求处理的适配器,也就是请求之后处理具体逻辑的执行,关系到哪个类的哪个方法以及转换器等工作,这个类是我们讲的重点,其中它的属性messageConverters是本文要讲的重点。
私有方法:getMessageConverters
从代码中我们可以,RequestMappingHandlerAdapter设置messageConverters的逻辑:
1.如果 mvc:annotation-driven 节点有子节点message-converters,那么它的转换器属性messageConverters也由这些子节点组成。
message-converters的子节点配置如下:
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.example.MyHttpMessageConverter"/> <bean class="org.example.MyOtherHttpMessageConverter"/>