Springmvc on the principle of JSON and XML automatic conversion [with source code Analysis] Directory
- Objective
- Phenomenon
- SOURCE Analysis
- Example explanation
- About configuration
- Summarize
- Resources
Objective
SPRINGMVC is currently one of the mainstream web MVC frameworks.
If a classmate is unfamiliar with it, then please refer to it's Getting started blog:http://www.cnblogs.com/fangjian0423/p/springmvc-introduction.html
Phenomenon
The demo used in this article is based on Maven and continues to be written according to the example of the entry blog.
Let's take a look at the corresponding phenomenon first. The key configuration in our configuration file *-dispatcher.xml is as follows (other general configuration files are not explained, refer to the introductory blog mentioned at the beginning of this article):
(View configuration omitted)
<mvc:resources location="/static/" mapping="/static/**"/><mvc:annotation-driven/><context:component-scan base-package="org.format.demo.controller"/>
The following dependencies are required in the POM (Spring dependencies and other dependencies are not shown):
<Dependency><Groupid>org.codehaus.jackson</Groupid><Artifactid>jackson-core-asl</artifactid> <version>1.9.13< Span class= "Hljs-tag" ></version></ dependency><dependency> <groupid>org.codehaus.jackson</groupid> <artifactid> Jackson-mapper-asl</artifactid> <version>1.9.13</version> </DEPENDENCY>
This dependency is a dependency of JSON serialization.
Ok. We add a method to the controller:
@RequestMapping ("/xmlorjson") @ResponseBodypublic map<string, object> Xmlorjson () { map<string, Object > map = new hashmap<string, object> (); Map.put ("List", Employeeservice.list ()); return map;}
Direct Access Address:
We see that in just a few lines of configuration. After using @responsebody annotations, the object returned by the controller is automatically converted to the corresponding JSON data, where it has to be lamented Springmvc's power.
We do not seem to see the specific configuration, the only thing to see is a *-dispatcher.xml in the configuration:<mvc:annotation-driven/>. This is actually the configuration, causing the Java object to automatically convert to JSON object phenomenon.
So how does spring actually implement the automatic conversion of Java objects to JSON objects? Why convert to JSON data and what if you want to convert it to XML data?
SOURCE Analysis
The spring version used in this article is 4.0.2.
Before explaining <mvc:annotation-driven/> This configuration, we will first understand the following spring's message transformation mechanism. @ResponseBody This annotation is the use of a message transformation mechanism, which is eventually converted to JSON data through a JSON converter.
The Httpmessageconverter interface is the HTTP message transformation interface provided by spring. For this, you can refer to the second link in the reference material, which is very clear.
The following begins the analysis <mvc:annotation-driven/> this sentence configuration:
The parsing class for this code in spring is:
In the 152-line parse method of the Annotationdrivenbeandefinitionparser source code:
Various classes such as Requestmappinghandlermapping,configurablewebbindinginitializer,requestmappinghandleradapter are instantiated separately.
The two classes of requestmappinghandlermapping and Requestmappinghandleradapter are more important.
Requestmappinghandlermapping handles the request mapping, processing the relationship between the @requestmapping and the request address.
Requestmappinghandleradapter is the adapter that requests processing, that is, the execution of the specific logic after the request, which is related to which method of the class and the work of the converter, this class is the focus of our talk, One of its properties messageconverters is the focus of this article.
Private method: Getmessageconverters
From the code we can, Requestmappinghandleradapter set the logic of Messageconverters:
1. If the <mvc:annotation-driven> node has child nodes Message-converters, then its converter attribute messageconverters is also composed of these child nodes.
The child nodes of the Message-converters are configured as follows:
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.example.MyHttpMessageConverter"/> <bean class="org.example.MyOtherHttpMessageConverter"/> </mvc:message-converters></mvc:annotation-driven>
If the 2.message-converters child node does not exist or its property is Register-defaults true, add other converters: Bytearrayhttpmessageconverter, Stringhttpmessageconverter, Resourcehttpmessageconverter and so on.
We see this passage:
Where do these Boolean properties come from, which are static variables of annotationdrivenbeandefinitionparser.
The Ispresent method in Classutils is as follows:
See here, the reader should understand why this article first in the Pom file needs to join the corresponding Jackson dependency, in order to make the JSON converter Jackson as one of the default converters.
The role of <mvc:annotation-driven> readers also understand.
Let's look at how to convert a Java object through a message converter.
Requestmappinghandleradapter in the handle, will be entrusted to the Handlermethod (specifically sub-class Servletinvocablehandlermethod processing) of the Invokeandhandle method for processing, This method is then transferred to Handlermethodreturnvaluehandlercomposite processing.
Handlermethodreturnvaluehandlercomposite maintains a list of Handlermethodreturnvaluehandler. Handlermethodreturnvaluehandler is a policy interface that handles the return value, which is very important. For details on this interface, please refer to the landlord's other blog:http://www.cnblogs.com/fangjian0423/p/springMVC-request-param-analysis.html. The corresponding handlermethodreturnvaluehandler are then found to process the resulting values.
Finally found Requestresponsebodymethodprocessor this handler (due to the use of @responsebody annotations).
Requestresponsebodymethodprocessor Method of Supportsreturntype:
Then use the Handlereturnvalue method for processing:
As we can see, the converter is used here.
The specific conversion method:
As to why the request for the head of the Accept data, the reader can go in debug this getacceptablemediatypes method to see. I'm not going to be so chatty.
Ok. So far, we've traveled through all the processes.
Now, look back. Why did the demo at the beginning output JSON data?
Let's analyze it.
Since we only have <mvc:annotation-driven> configured, we use the spring default converters.
Obviously, we've seen 2 XML and a JSON converter. to see if you can convert, look at the public boolean canWrite of the Httpmessageconverter interface (class<?> Clazz, mediatype mediatype) Determines whether the method returns True.
Let's analyze Sourcehttpmessageconverter first:
Its CanWrite method was rewritten by the parent class, Abstracthttpmessageconverter.
There is no map class found in supported_classes (this is the map class returned by this document) and is therefore not supported.
See below Jaxb2rootelementhttpmessageconverter:
This class directly overrides the CanWrite method.
Xmlrootelement annotations are required. Obviously, the map class is certainly not.
Final mappingjackson2httpmessageconverter matching, JSON conversion. (Why match, please check the source code for yourself)
Example explanation
After we have analyzed the conversion process of the converter, the following example validates our conclusion.
First, let's implement the XML converter first.
Previously parsed, the default converter is XML-enabled. Let's add a note to try it out.
Since map is part of the JDK source code, we use employee to do the demo.
Therefore, the controller adds a method:
@RequestMapping ("/xmlorjsonsimple") @ResponseBodypublic Employee xmlorjsonsimple () { return Employeeservice.getbyid (1);}
Add @xmlrootelement annotations to the entity
The results are as follows:
We found that parsing into XML.
Why parse it into XML instead of parsing it into JSON?
As previously analyzed, message converters are determined by class and mediatype.
We use Firebug to see:
We found that the accept has XML, there is no JSON. So it's parsed into XML.
Let's verify that the same address, HTTP header differs from accept. See if it's right.
$.ajax ({ URL: "${request.contextpath}/employee/xmlorjsonsimple", success:function (res) { Console.log (res); }, headers: { "Accept": "Application/xml" }});
$.ajax ({ URL: "${request.contextpath}/employee/xmlorjsonsimple", success:function (res) { Console.log (res); }, headers: { "Accept": "Application/json" }});
Validation succeeded.
About configuration
If you don't want to use the default Requestmappinghandleradapter in <mvc:annotation-driven/>, we can redefine the bean, Spring overwrites the default requestmappinghandleradapter.
Why overwrite, please refer to the landlord's other blog: http://www.cnblogs.com/fangjian0423/p/spring-Ordered-interface.html
<Beanclass="Org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter" ><PropertyName="Messageconverters" ><list> <bean class=" Org.springframework.http.converter.ByteArrayHttpMessageConverter "/> <bean class=" Org.springframework.http.converter.StringHttpMessageConverter "/> <bean class=" Org.springframework.http.converter.ResourceHttpMessageConverter "/> </list> </ property></bean>
Or if you just want to change messageconverters.
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.example.MyHttpMessageConverter"/> <bean class="org.example.MyOtherHttpMessageConverter"/> </mvc:message-converters></mvc:annotation-driven>
If you want to use other converters.
These are the converters in the Spring-mvc jar package.
Here we use the Marshallinghttpmessageconverter that transforms the XML.
This converter uses marshaller for conversion.
We use Xstreammarshaller here.
JSON has no converters and returns 406.
As for the XML format problem, we solve it by ourselves. Xstream~ is used here.
Using this method, POM does not forget to join the XStream dependency:
<dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.7</version></dependency>
Summarize
Having written so much, perhaps the reader feels a little wordy. After all, this is also some of their own experience, hope can be said to share with the reader.
Just contact Springmvc time, found this automatic conversion mechanism is very good, but has not studied its principle, at present, is a small wish, Springmvc still have a lot of content, later in the study of other content will also share with you.
The article will inevitably appear some mistakes, hope readers can point out.
Springmvc on the principle of JSON and XML automatic conversion [with source code analysis]