【SpringMVC】浅谈Convert/Format机制与HttpMessageConverter的关系

简介

Spring3引入了较Spring2的PropertyEditor更增强大、通用的Convert/Format SPIConvert SPI能够实现任意类型的转换;Format SPI支持国际化,并在前者的基础上实现了String与任意类型的转换。这两类SPI属于spring-core,被整个spring-framework共享,是一种通用的类型转换器。java

HttpMessageConverter虽然功能上也表现为HttpMessage与任意类型的转换,但其接口和Convert SPI并无继承关系。HttpMessageConverter属于spring-webHttpMessage是SpringMVC对Servlet规范中HttpServletRequestHttpServletResponse的包装,所以接受请求时须要把HttpMessage转换成用户须要的数据,在生成响应时须要把用户生成的数据转换成HttpMessage。若是用户在XML的<mvc:message-converters>中没有指定register-defaults=false,SpringMVC默认至少会注册一些自带的HttpMessageConvertor(从前后顺序排列分别为ByteArrayHttpMessageConverterStringHttpMessageConverterResourceHttpMessageConverterSourceHttpMessageConverterAllEncompassingFormHttpMessageConverter)。web

若是后端服务使用Restful API的形式,通常使用JSON做为先后端通讯的格式规范,因为SpringMVC自带MappingJackson2HttpMessageConverter,在依赖中引入jackson后,容器会把该转换器自动注册到converter链的末尾。ajax

二者的分工

Http请求中有几个经常使用的部分能够用来传递业务信息,以常见的GetPost方法为例。spring

是否可用 URL Parameter Header Body
Get
Post

那么上述的4个部分都是用HttpMessageConverter来进行类型转换的吗?显然不是,HttpMessageConverterConvert SPI各有分工, HttpMessageConverte只负责解析Http包的Body体部分1,其他部分都交由相关的Convert SPI处理2后端

是否支持 URL Parameter Header Body
HttpMessageConverter
Convert SPI

除上表所示以外,SpringMVC还有一些须要Convert SPI的场景,如读取Cookie值的@CookieValue(本质是Header),解析矩阵URL的@MatrixVariable(本质是URL),读取本地会话的@SessionAttribute,解析SpEL的@Valuemvc

Convert SPI类型转换实例

在SpringMVC中,单次请求的整个处理流程中有哪些地方须要类型转换?以Delete /ajax/shop/12345/blacklist?id=1请求为例,后端对应的处理方法以下。app

@DeleteMapping("/ajax/{shopId}/blacklist") @ResponseBody
public boolean deleteBlackItem(@RequestParam Integer id, @PathVariable Integer shopId) {
    //省略
    return true;
}

因为请求的URL为String类型,而接受的参数idshopId都是Integer类型,所以Spring会自动查找合适的Converter(具体实现为StringToNumberConverterFactory的工厂产品)把字符串“12345”“1”转化为数字123451,分别赋值给shopIdid。处理完业务逻辑后,方法返回true,但须要将其格式化成String类型的“true”才能输出到响应的Body中,这时Spring就会使用StringToBooleanConverter来完成转换。以下图所示,除了上述常见的数据绑定和格式化显示功能,数据验证功能(JSR-303)基于数据绑定也间接利用了这两套SPI。spa

SpringMVC数据绑定、验证与Convert SPI的关系

结语

在SpringMVC处理请求时,HttpMessageConverterConvert SPI分别用来反序列化请求的Body和非Body部分,即HttpMessageConverter是一套小型、独立、额外为用户提供的专门的Body体的类型转换器;而Convert SPI则与PropertyEditor相似,能够处理更为通用的类型转换。3d

Reference

  1. SpringMVC数据类型转换——第七章 注解式控制器的数据验证、类型转换及格式化——跟着开涛学SpringMVC

  1. 具体见HandlerMethodInvoker.readWithMessageConverters方法
  2. 具体见不一样的HandlerMethodArgumentResolver实现
相关文章
相关标签/搜索