DispatcherServlet
从HandlerMapping
中获取HandlerMethod
, 并将其交给HandlerAdapter
,由HandlerAdater
触发调用HandlerMethod
的方法(最终触发执行Controller中的对应方法)获取执行结果。
在HandlerMethod
的方法中通过HandlerMethodArgumentResolver
参数解析器从request中解析拿到Controller方法对应的实参,然后在反射执行controller的方法时传递参数
参数解析器HandlerMethodArgumentResolver
在HandlerMethod
中会从众多HandlerMethodArgumentResolver
的实现类中找到能够解析对应MethodParam
(MethodParam中包含了Controller对应方法中某一个参数的元信息,如方法参数类型、该参数使用的注解等)的解析器来解析参数☞策略模式
- 例如controller对应方法中某个参数使用了
@RequestParam
注解标注,则会找到RequestParamMethodArgumentResolver
解析器, 然后使用该参数解析器从request中读取参数值,调用ServletRequest#getParameterValues
获取参数值
- 若controller对应的方法的某个参数使用了
@RequestBody
注解标注,则会拿到RequestResponseBodyMethodProcessor
解析器,它也是HandlerMethodArgumentResolver
的实现类。
在RequestResponseBodyMethodProcessor
的解析方法中,会使用HttpMessageConverter
消息转换器的实现类从request的Inpustream
中读取数据
消息转换器HttpMessageConverter
在RequestResponseBodyMethodProcessor
的解析方法中会根据参数类型和content-type决定使用哪个HttpMessageConverter
读取request中的数据
-
若content-type类型是
application/json
,则获得的HttpMessageConverter
的实现类是MappingJackson2HttpMessageConverter
, 该HttpMessageConverter实现类会从request的InputStream
中读取数据 -
若content-type类型是
application/x-www-form-urlencoded
, 并且参数类型是MultiValueMap
,会使用AllEncompassingFormHttpMessageConverter
(FormHttpMessageConverter
的子类)
因此使用@RequestBody的前提下,要想处理content-type为application/x-www-form-urlencoded
的请求,则参数类型必须使用MultiValueMap
。当然,读取x-www-form-urlencode
的参数也可以不使用@RequestBody注解,这种情况下就不要求参数类型是MultiValueMap
了在
content-type
是application/x-www-form-urlencoded
的情况下,调用request的getParamMap方法,底层也是调用的InputStream的read方法来读取参数,因为表单数据也是置于请求体中传输的。