使用Spring MVC开发的,应该都使用过@RequstBody接收json参数,转换成pojo对象,非常方便阿,但是功能并不是很全面,有点点瑕疵,并不能支持json key 方式注入到String、Integer 这类类型对象。
前端传值 | 后端接收 | 结果 |
---|---|---|
{“id”: 3,”name”:”xxx”} | User(id,name) | 成功注入 |
{“id”: 3,”name”:”xxx”} | (String name,int id) | 并不支持这个方式 |
有时候一个接口只有两个参数上传,我们并不想为此创建一个单独的对象,这样可能会导致每一个hangdler 方法可能都存在一个pojo对象,大部分对象可能并不能被其他handler 共享。 而是希望使用一两个参数就可以接收到。先看下@RequestBody
这个注解如何实现将json 转换成pojo对象的,通过spring HandlerMethodArgumentResolver 参数解析器来实现的,了解下接口。
1 | public interface HandlerMethodArgumentResolver { |
在RequestMappingHandlerAdapter
下可以看见默认参数解析器
1 | private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() { |
可以看见大部分方法参数都是通过上面处理器去实现的,重点放在RequestResponseBodyMethodProcessor 如何注入json的,主要看两个方法如何实现的。
1 |
|
将json 序列号成对象实现都是在readWithMessageConverters 方法中
1 | protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter, |
http 请求内容调用GenericHttpMessageConverter read 方法转换成对象,这时调用的是AbstractJackson2HttpMessageConverter
1 | private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) throws IOException { |
可以看见@RequestBody 是通过GenericHttpMessageConverter class 调用ObjectMapper readValue 进行转换的,只能将json转换成pojo 对象, 并不支持简单类型 String、Integer、Long这类转换的,有着天然缺陷。如果想将json key 注入到参数,需要手动实现一个参数解析器,下面展示简单实现代码。
动手实现
目标: 我们希望创建一个类似@RequestBody的注解,标注当前参数支持json key直接注入,这个注解也可以直接在方法修饰,表示整个方法参数都是用注解,当然也可以支持整个类,表示所有方法的参数都支持。在实现一个对应注解的参数解析器。
创建注解类
1 | ({ElementType.PARAMETER,ElementType.METHOD,ElementType.TYPE}) |
实现参数解析器
1 | public class RequestJsonKeyValueMethodProcessor implements HandlerMethodArgumentResolver { |
添加自定义参数解析器
1 |
|
这里不用担心自定义参数解析器会覆盖spring 原生的解析器,这里会将addArgumentResolvers 添加解析器自动放入到CustomArgumentResolvers中。
一个简单自定义参数解析器就完成了,支持普通类的String、Integer 这些参数的解析。注意的是这个参数解析器并没有考虑参数为空的处理,Optional 这类情况只满足一些简单、快速开发的场景。不知道各位同行是否在日常开发中有没有使用到这些知识,我公司的基础框架就是使用这些技术来做快速开发的,对开发效率提升特别大的。