1. Questions
Spring is how to convert the body in HTTP to the specified class, the difficulty is actually the processing of generics.
2.Spring Processing 2.1 Handlermethod
This class of spring's encapsulation of method, such as using the @requestmapping annotation method, uses the Handlermethod wrapper (in fact its subclass Invocablehandlermethod). It is then called by the Invocablehandlermethod
The properties of the Handlermethod are as follows
Private final Object bean;private final beanfactory beanfactory;private final class<?> beantype;private final metho D Method;private Final method bridgedmethod;private final methodparameter[] parameters; The point is this private httpstatus responsestatus;private String responsestatusreason;private Handlermethod Resolvedfromhandlermethod;
2.2 How to parse a parameter
Refer to Invocablehandlermethod's Getmethodargumentvalues method, which uses various handlermethodargumentresolver to parse the spring MVC call parameters
For example, the parameters in the path/path/${var} use the Pathvariablemapmethodargumentresolver related annotations @PathVariable
For example, the parameters in the header are parsed using Requestheadermapmethodargumentresolver, and related annotations @requestheader
So @responsebody used the requestresponsebodymethodprocessor to parse,
2.3 How to convert body to parameter class
@Overridepublic Object resolveargument (methodparameter parameter, Modelandviewcontainer Mavcontainer, Nativewebrequest webRequest, Webdatabinderfactory binderfactory) throws Exception {parameter = Parameter.nestedifoptional (); Object arg = Readwithmessageconverters (webRequest, parameter, Parameter.getnestedgenericparametertype ());.... return adaptargumentifnecessary (arg, parameter);}
Where the Readwithmessageconverters method is the focus, note that Methodparameter is actually the attribute in Handlermethod
Keep jumping inside.
Generichttpmessageconverter<?> Genericconverter = (generichttpmessageconverter<?>) converter;
...
BODY = Genericconverter.read (TargetType, Contextclass, inputmessage);
The code above is to read the body of HTTP and convert it to the specified class. We take the code in the common Fastjson fastjsonhttpmessageconverter, it's simple.
Public Object read (type type,// class<?> Contextclass,// httpinputmessage inputmessage// ) throws IOException, httpmessagenotreadableexception { return Readtype (GetType (Type, contextclass), inputmessage); } Private Object Readtype (type type, Httpinputmessage inputmessage) throws IOException { try { InputStream in = Inpu Tmessage.getbody (); Return Json.parseobject (In, Fastjsonconfig.getcharset (), type, fastjsonconfig.getfeatures ()); } catch (Jsonexception ex) { throw new Httpmessagenotreadableexception ("JSON Parse Error:" + ex.getmessage (), ex);
} catch (IOException ex) { throw new httpmessagenotreadableexception ("I/O error while reading input message", ex); } }
3 How to implement it yourself
Through the above analysis, how to implement a simple data mock replay (assuming that our mock data is stored using JSON)
new// Second step: Get the return type of Methodparameter methodparameter Methodparameter =// Third step: Use Fastjson to deserialize the Jsonobject.parseobject (Phxresult.getval (), Methodparameter.getnestedgenericparametertype ()); // Note that the Bean is an instance of the called class, and method is a concrete call to get through reflection, how to get not the focus here, omit to get
How to implement @responsebody to convert a JSON string to a specified type