您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
这问题巧了,SpringMVC 不同参数处理机制引发的思考
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
这问题巧了,SpringMVC 不同参数处理机制引发的思考
完成设置321
2023-06-21
IP归属:北京
7200浏览
> 这个问题非常有趣,不是SpringMVC 的问题,是实际开发中混合使用了两种请求方式暴露出来的。 ## 问题场景 功能模块中,提供两个 Http 服务。一个是列表查询(application/json 请求),一个是列表导出(表单请求)。运行环境发现个问题:MVC model 新添加的属性,类似的 Http 请求,一个有值,一个没有 **** 代码如下: ```java /** * application/json 请求。 这种情况 param.field2 有值 ✔ * @param param RequestResponseBodyMethodProcessr 处理 HttpServletRequest 参数 */ @PostMapping(value = "query") public ResponseResult<Page<SomeData>> queryByCondition(@RequestBody SomeParam param){ // 业务逻辑... } /** * application/x-www-form-urlencoded 请求 这种情况 param.field2 没有有赋值 ❌ * @param param ServletModelAttributeMethodProcessor 处理 HttpServletRequest 参数 */ @PostMapping(value = "export") public void exportExcel(SomeParam param) { // 业务逻辑... } public class SomeParam { // 这个是原有的,有 get set 方法 private String field1; // 这个是新增的,没有get set 方法 (这是一个巧合、意外🎈)。 问题就出在这里。 private String field2; } ``` ❓ 根据代码分析,那应该是 SpringMVC 针对这两种参数处理的机制不同。 针对上述的参数处理,可以参考:RequestResponseBodyMethodProcessor、 ServletModelAttributeMethodProcessor ## Insight RequestResponseBodyMethodProcessor > 处理 Http Body 的数据。解析注解 RequestBody 的参数。 > > 针对 MimeType 为 application/json 的请求,按照json 格式进行反序列化。 > > 默认参数处理器 MappingJackson2HttpMessageConverter string 反序列化为对象,使用的是 com.fasterxml.jackson.databind.ObjectMapper。 上述工程中,对 ObjectMapper 开启 private 属性检测。新增的属性可以正常反序列化。 ```java ObjectMapper mapper = new ObjectMapper(); // 这又是一个巧合、意外 🎈🎈 咋还有这个用法 🤣 mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY); ``` Visibility 具体的用法示例参考: [Jackson - Decide What Fields Get (De)Serialized | Baeldung](https://www.baeldung.com/jackson-field-serializable-deserializable-or-not) 原理: 如果没有 setter 方法,jackson 会操作 field 来完成赋值。 ```java /** * This concrete sub-class implements property that is set directly assigning to a Field. */ public final static class FieldProperty extends SettableBeanProperty { @Override public final void set(Object instance, Object value) throws IOException { try { _field.set(instance, value); } catch (Exception e) { _throwAsIOE(e, value); } } } ``` ## Insight ServletModelAttributeMethodProcessor > 自定义 Class 参数解析 > > 通过解析 request parameters, 用来构造和初始化对应的方法入参。 > > 主要通过 ServletRequestDataBinder.bind(request) 来完成。 ```java /** * Apply given property values to the target object. * By default, unknown fields will be ignored. * * @see org.springframework.validation.DataBinder#applyPropertyValues */ protected void applyPropertyValues(MutablePropertyValues mpvs) { try { // Bind request parameters onto target object. // 默认使用 BeanWrapperImpl.setPropertyValue() getPropertyAccessor().setPropertyValues(mpvs, isIgnoreUnknownFields(), isIgnoreInvalidFields()); } catch (PropertyBatchUpdateException ex) { // Use bind error processor to create FieldErrors. } } ``` ```java public void setPropertyValues(PropertyValues pvs, boolean ignoreUnknown, boolean ignoreInvalid) throws BeansException { // 通过遍历 request parameters 来尝试对 target 进行赋值 List<PropertyValue> propertyValues = (pvs instanceof MutablePropertyValues ? ((MutablePropertyValues) pvs).getPropertyValueList() : Arrays.asList(pvs.getPropertyValues())); for (PropertyValue pv : propertyValues) { try { // etPropertyValue 使用 JDK 的 Introspector 来进行序列化操作。 // 没有setter 方法,自然没法赋值。 setPropertyValue(pv); } } } ``` ## 总结 - 一件事情出错,不是一处问题造成的。 - 工程开发要规范,用最常规、最稳定的办法来实现。遇到稀奇古怪的问题就是冷门用法带来的。 - 对于常用的框架和工具库熟悉其底层原理,遇到问题可以很快定位。 ## more 引流: [H2 数据库 索引和存储原理 Code Insight](http://xingyun.jd.com/shendeng/article/detail/15199) 🙉
上一篇:京东到家小程序-在性能及多端能力的探索实践
下一篇:Elasticsearch必知必会-基础篇
完成设置321
文章数
7
阅读量
1155
作者其他文章
01
稳,从数据库连接池 testOnBorrow 看架构设计
本文从 Commons DBCP testOnBorrow 的作用机制着手,管中窥豹,从一点去分析数据库连接池获取的过程以及架构分层设计。以下内容会按照每层的作用,贯穿分析整个调用流程。1️⃣框架层 commons-poolThe indication of whether objects will be validated before being borrowed from the pool.
01
分布式数据库 Join 查询设计与实现浅析
相对于单例数据库的查询操作,分布式数据查询会有很多技术难题。本文记录 Mysql 分库分表 和 Elasticsearch Join 查询的实现思路,了解分布式场景数据处理的设计方案。文章从常用的关系型数据库 MySQL 的分库分表Join 分析,再到非关系型 ElasticSearch 来分析 Join 实现策略。逐步深入Join 的实现机制。①Mysql 分库分表 Join 查询场景分库分表场
01
这问题巧了,SpringMVC 不同参数处理机制引发的思考
这个问题非常有趣,不是SpringMVC 的问题,是实际开发中混合使用了两种请求方式暴露出来的。问题场景功能模块中,提供两个 Http 服务。一个是列表查询(application/json 请求),一个是列表导出(表单请求)。运行环境发现个问题:MVC model 新添加的属性,类似的 Http 请求,一个有值,一个没有代码如下:/** * application/json 请求。 这种情况 p
01
h2database BTree 设计实现与查询优化思考
h2database 是使用Java 编写的开源数据库,兼容ANSI-SQL89。即实现了常规基于 BTree 的存储引擎,又支持日志结构存储引擎。功能非常丰富(死锁检测机制、事务特性、MVCC、运维工具等),数据库学习非常好的案例。本文理论结合实践,通过BTree 索引的设计和实现,更好的理解数据库索引相关的知识点以及优化原理。BTree 实现类h2database 默认使用的 MVStore
完成设置321
文章数
7
阅读量
1155
作者其他文章
01
稳,从数据库连接池 testOnBorrow 看架构设计
01
分布式数据库 Join 查询设计与实现浅析
01
h2database BTree 设计实现与查询优化思考
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号