Converter和HttpMessageConveter是springboot和springmvc在处理请求的时候需要用到的。但是这两者的完全是不一样的,作用的地方也不一样。
1,springboot和springmvc处理请求的流程
先来回顾一下处理请求的流程:
用户向服务器发送请求,请求被前端控制器 DispatcherServlet捕获。
DispatcherServlet根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain执行链对象的形式返回
DispatcherServlet 根据获得的 Handler,选择一个合适的HandlerAdapter
如果成功获得HandlerAdapter,此时将开始执行拦截器的preHandler(…)方法
提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)方法,处理请求,在填充Handler的入参过程中,根据你的配置,Springboot或Springmvc将帮你做一些额外的工作:
1,HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的类型信息
2,数据转换(Converter):对请求消息进行数据转换。如String转换成Integer、Double等
3,数据格式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
4,数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象。
此时将开始执行拦截器的postHandle(…)方法
根据返回的ModelAndView(此时会判断是否存在异常:如果存在异常,则执行HandlerExceptionResolver进行异常处理)选择一个适合的ViewResolver进行视图解析,根据Model和View,来渲染视图
渲染视图完毕执行拦截器的afterCompletion(…)方法
将渲染结果返回给客户端
可以看到填充Handler入参的时候用到Converter和HttpMessageConveter。那到底什么时候用Converter,什么时候用HttpMessageConveter呢?
2,GET和POST请求可以用来传递业务参数
get和post请求携带参数的支持方式是不同,如图:
上述的4个部分都是用HttpMessageConverter来进行类型转换的吗?不是的,HttpMessageConverter和Convert 各有分工, HttpMessageConverte只负责解析Http包的Body体部分,其余部分都交由相关的Convert处理。
HttpMessageConverter和Convert各自支持的部分如图:
除上表所示之外,SpringMVC还有一些需要Convert的场景,如读取Cookie值的@CookieValue(本质是Header),解析矩阵URL的@MatrixVariable(本质是URL),读取本地会话@SessionAttribute,解析SpEL的@Value。
所以,在处理请求时,HttpMessageConverter和Convert 分别用来反序列化请求的Body和非Body部分,即HttpMessageConverter是一套小型、独立、额外为用户提供的专门的Body体的类型转换器;而Convert 则与PropertyEditor类似,可以处理更为通用的类型转换。比如要将一个Body部分为json格式的字符串转换为对象,就需要HttpMessageConverter来做这件事情,因为不同的HttpMessageConverter才知道如何解析这种类型的Body,具体该Body能否被某个HttpMessageConverter所解析,要看这个HttpMessageConverter能否支持某个请求,或者某个响应的Content-Type。然后可以使用该HttpMessageConverter进行解析。将一个String类型的参数id转换成方法的Long类型参数id就使用Convert。另外在HttpMessageConverter解析Body部分的时候,其同样可能会用到Convert/Format的转换器,因为他内部在将Body转换为对象或者其他类型时,可能也会需要将字符串转化为整型数字。