SPRINGMVC uses message converters to automate the transition between request messages and objects, objects, and response messages
Overview
In Springmvc, you can use the @requestbody and @responsebody two annotations, respectively, to complete the request message to object and object to the response message conversion, the bottom of this flexible message conversion mechanism, Is the new httpmessageconverter called message Converter mechanism introduced in spring3.x.
Abstraction of an HTTP request
or return to the request-response, that is, parse the request body, and then return to the response message of the most basic HTTP request process. We know that in the servlet standard, you can use the following methods in the Javax.servlet.ServletRequest interface:
Public throws IOException;
To get a servletinputstream. In this servletinputstream, you can read all the contents of a RAW request message. Similarly, in the Javax.servlet.ServletResponse interface, you can use the following methods:
Public throws IOException;
To get a servletoutputstream, this servletoutputsteam, inherited from Java OutputStream, allows you to output HTTP response message content.
Let's try to think like a SPRINGMVC designer. We know that the HTTP request and response message is essentially a string, and when the request message arrives in the Java world, it is encapsulated as a servletinputstream input stream for us to read the message. The response message is a servletoutputstream output stream that outputs the response message.
We can only read the original string message from the stream, and we can only write the original character in the output stream. In the Java world, the processing of business logic is a business-meaningful object for the processing of dimensions, then the message arrives Springmvc and out from the SPRINGMVC, there is a string to the Java object impedance problem. This process cannot be manually converted by a developer. We know that in Struts2, OGNL is used to deal with this problem, and in Springmvc, it is the httpmessageconverter mechanism. Let's take a look at two interfaces first.
Httpinputmessage
This class is an abstraction of an HTTP request message within the SPRINGMVC, and in the Httpmessageconverter read () method, there is a httpinputmessage parameter, which is the receptor that the SPRINGMVC message converter acts " The internal abstraction of the request message, which the message converter extracts from the request message in accordance with the rules, into the object declared in the method parameter.
Package org.springframework.http; Import java.io.IOException; Import Java.io.InputStream; Public Interface extends httpmessage { throws IOException; }
Httpoutputmessage
This class is an abstraction of an HTTP response message within the SPRINGMVC, and in the Httpmessageconverter write () method, there is a httpoutputmessage parameter, It is the internal abstraction of the receptor "response message" that the SPRINGMVC message converter is acting upon, and the message converter writes the "response message" to the response in accordance with certain rules.
Package org.springframework.http; Import java.io.IOException; Import Java.io.OutputStream; Public Interface extends httpmessage { throws IOException; }
Httpmessageconverter
The most high-level interface abstraction of a message converter describes the general characteristics of a message converter, and we can understand the spring3.x designer's thought process of this mechanism from the method defined in this interface.
PackageOrg.springframework.http.converter; Importjava.io.IOException; Importjava.util.List; ImportOrg.springframework.http.HttpInputMessage; ImportOrg.springframework.http.HttpOutputMessage; ImportOrg.springframework.http.MediaType; Public InterfaceHttpmessageconverter<t> { BooleanCanRead (class<?>Clazz, mediatype mediatype); BooleanCanWrite (class<?>Clazz, mediatype mediatype); List<MediaType>getsupportedmediatypes (); T Read (Class<?extendsT> Clazz, Httpinputmessage inputmessage)throwsIOException, httpmessagenotreadableexception; voidWrite (T T, mediatype ContentType, Httpoutputmessage Outputmessage)throwsIOException, httpmessagenotwritableexception; }
The definition of the Httpmessageconverter interface appears paired with CanRead (), read (), and CanWrite (), the Write () method, and mediatype is the encapsulation of the requested media type property. As an example, when we declare the following method of processing.
@RequestMapping (value= "/string", method=requestmethod.post) public @ResponseBody string ReadString (@RequestBody string string) { return "Read String '" + string + "'"; }
Before Springmvc enters the ReadString method, the appropriate Httpmessageconverter implementation class is selected according to the @requestbody annotation to parse the request parameters into the string variable. Specifically, the Stringhttpmessageconverter class is used, and its CanRead () method returns True, and its read () method reads the request parameter from the request, bound to the string variable of the ReadString () method.
When Springmvc executes the ReadString method, the return value identifies the @responsebody,springmvc will use the Write () method of Stringhttpmessageconverter. Writes the result as a string value to the response message, of course, at which point the CanWrite () method returns True.
We can use the following diagram to briefly describe the process.
Requestresponsebodymethodprocessor
One of the classes described in the above procedure is Org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor, and this class implements the Handlermet Hodargumentresolver and Handlermethodreturnvaluehandler two interfaces. The former is the policy interface that binds the request message to the processing method parameter, and the latter is the policy interface for processing the return value of the processing method. The source code for the two interfaces is as follows:
PackageOrg.springframework.web.method.support; ImportOrg.springframework.core.MethodParameter; ImportOrg.springframework.web.bind.WebDataBinder; Importorg.springframework.web.bind.support.WebDataBinderFactory; Importorg.springframework.web.context.request.NativeWebRequest; Public InterfaceHandlermethodargumentresolver {Booleansupportsparameter (methodparameter parameter); Object resolveargument (methodparameter parameter, Modelandviewcontainer Mavcontainer, Nativewebrequest webRequest, webdatabinderfactory binderfactory)throwsException; } PackageOrg.springframework.web.method.support; ImportOrg.springframework.core.MethodParameter; Importorg.springframework.web.context.request.NativeWebRequest; Public InterfaceHandlermethodreturnvaluehandler {BooleanSupportsreturntype (Methodparameter returntype); voidHandlereturnvalue (Object returnvalue, Methodparameter returntype, Modelandviewcontainer Mavcontainer, nativewebrequest webRequest)throwsException; }
Requestresponsebodymethodprocessor This class, while acting as the method parameter parsing and return value processing two kinds of roles. From its source code, we can find the method implementation of the above two interfaces.
Implementation of the Handlermethodargumentresolver interface:
Public Booleansupportsparameter (methodparameter parameter) {returnParameter.hasparameterannotation (requestbody.class); } PublicObject resolveargument (methodparameter parameter, Modelandviewcontainer mavcontainer, Nativewebrequest webRe Quest, Webdatabinderfactory Binderfactory)throwsException {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 ()); returnargument; }
Implementation of the Handlermethodreturnvaluehandler interface
Public BooleanSupportsreturntype (Methodparameter returntype) {returnReturntype.getmethodannotation (responsebody.class) !=NULL; } Public voidHandlereturnvalue (Object returnvalue, Methodparameter returntype,modelandviewcontainer MavContainer, Nativewebrequest webRequest)throwsIOException, httpmediatypenotacceptableexception {mavcontainer.setrequesthandled (true); if(ReturnValue! =NULL) {writewithmessageconverters (returnvalue, ReturnType, webRequest); } }
After reading the above code, the whole Httpmessageconverter message transformation is very clear. Because of the implementation of two interfaces, respectively, with the @requestbody and @responsebody as the condition, and then call Httpmessageconverter respectively to read and write the message.
If you want to ask, how to trace to Requestresponsebodymethodprocessor, please follow the previous several blog ideas, and then here spring-mvc-showcase download source back, Httpmessageconverter related to the example of debugging, as long as you work hard, I believe you will have their own harvest.
Thinking
Zhang Xiaolong in the nature of the talk, said: "Just a platform, the flow of news in it." In our process of SPRINGMVC source code Analysis, we can learn from the httpmessageconverter mechanism of similar truth. In the eyes of Springmvc's designer, a request message and a response message are abstracted as a request messages httpinputmessage and a response messages httpoutputmessage, respectively.
When a request is processed, the request message is bound by the appropriate message converter to the parameter object in the method, where the same object is likely to appear in a variety of different message forms, such as JSON and XML. Similarly, when responding to a request, the return value of the method may also be returned as a different message form, such as JSON and XML.
In Springmvc, for different message forms, we have different httpmessageconverter implementation classes to handle various message forms. However, as long as the "valid information" contained in these messages is consistent, a variety of different message converters will produce the same conversion results. The differences between the various message parsing details are masked in different httpmessageconverter implementation classes.
SPRINGMVC Source--Message Converter Httpmessageconverter