谁要是再敢用Map传参,我过去就是一JIO
还记得上次我写过一篇关于实际项目代码分层和规划的文章《看完这篇,别人的开源项目结构应该能看懂了》,
在文尾处提到过一些注意事项,其中第一条就是:
- Contorller层参数传递建议不要使用HashMap,推荐使用数据模型定义
私信里竟然有很多小伙伴提问说,为什么不能这样做?
我心里暗自寻思:难道这么做的小伙伴都没有被同事捶吗?(滑稽)
得嘞,今天咱们就掰扯掰扯这件事,这是实际写代码时常忽略的一个问题
是不是有人也这么写过?
我自己曾经接手过一个前人留下来的老项目,拿到代码,导入IDEA的那一刻,我哭出了声。
因为它的
Controller层代码都是类似这样写的:
@RestController @RequestMapping("/index") public class IndexController { // 获取App首页内容 @PostMapping("/getIndexContent") public ResponseWrapper getIndexContent( @RequestBody Map<String, Object> paramMap ) { ResponseWrapper res = new ResponseWrapper(); // 下面开始做传参有效性的校验 if (!paramMap.containsKey("article_id")) { res.setCode(500); res.setMsg("缺少 article_id 信息"); return res; } if (!paramMap.containsKey("page")) { res.setCode(500); res.setMsg("缺少 page 信息"); return res; } if (!paramMap.containsKey("size")) { res.setCode(500); res.setMsg("缺少 size 信息"); return res; } if (!paramMap.containsKey("version")) { res.setCode(500); res.setMsg("缺少 version 信息"); return res; } // ...... 此处省略 } // ...... 此处省略 }
别的咱先不说,居然明目张胆地在
Controller层里方法里用
Map传参?!简直丧心病狂了。幸亏下面还有一波传参有效性的验证,对于传递的参数,我好歹也能猜个大概,不然那真是喵了个咪了。
接下来,我们就好好唠一唠:为什么不要在Controller
层传参时使用Map
类型!
Map一时爽,维护爽歪歪
正好,这地方有一个咱小伙伴活生生的例子。
记得之前有个小伙伴提问,问过一个这样的问题,说他接手了一个别人的老项目,问了我一个类似这样的问题:
看到没!
用
Map传参的第一个(也是最大的一个)弊端就是:这会导致后续接手和维护的人怀疑自己的人生,因为他根本不知道代码传的啥参数,想要构造参数去调试接口只能靠脑补、摸瞎、以及猜测了。
试想一下,其实我们代码里任何一个地方的传参都可以使用
Map来传,如果真的这么做了,代码中连任何数据模型类都不需要定义了,果真如此的话,这样的代码咱能看懂吗?
而且这位小伙伴接手的项目居然还用的是
LinkedHashMap参数,可以说很秀了。
除此之外,紧接着还会带来下面这个问题。
好用的API工具与你无缘了
我之前写过一篇文章《前后端都分离了,该搞个好用的API管理系统了!》,聊过现在市面上一些比较好用的、能极大提升前后端开发效率的API管理工具,这对于前后端开发来说,简直是莫大的福音。
我们就以
Swagger这个API工具为例,如果
Controller传参使用
Map的话:
// 获取App首页内容 @ApiOperation("获取App首页内容") @PostMapping("/getIndexContent") public ResponseWrapper getIndexContent( @RequestBody Map<String, Object> paramMap ) { // ...... 此处省略 }
则
API工具无法读取具体参数项目和参数类型,所以传参什么的也看不出来:
换言之,我如果将上面的
Map传参改为自定义数据模型类
IndexQueryDto来传参的话:
// 获取App首页内容 @ApiOperation("获取App首页内容(改造后)") @PostMapping("/getIndexContent") public ResponseWrapper getIndexContent( @RequestBody IndexQueryDto indexQueryDto ) { // ...... 此处省略 }
@ApiModel(value = "App首页内容请求参数实体对象") class IndexQueryDto { @ApiModelProperty(value = "文章ID号") @NotNull(message = "缺少 article_id 信息") private Long article_id; @ApiModelProperty(value = "页面数") @NotNull(message = "缺少 page 信息") private Integer page; @ApiModelProperty(value = "每页条目数") @NotNull(message = "缺少 size 信息") private Integer size; @ApiModelProperty(value = "App版本号") @NotNull(message = "缺少 version 信息") private String version; // ...... 此处省略set/get方法 }
则类似
Swagger这种
API工具就非常方便地能帮助我们管理参数了:
这样不管是自己调试,还是前、后端对接口都会方便得多。
同理,除了
Swagger这种
API管理工具之外,像在我的前文《没用过这些IDEA插件?怪不得写代码头疼》中推荐过的一个非常好用的接口管理插件
RestfulToolkit也无法识别出
Map类型所盛放的具体参数:
但是对于数据模型的定义参数,就能非常清晰的给出参数细节,并方便地提供接口测试:
优秀的注解没法使用了
还是以文章开头举例的代码来说,不管怎么样,写这段代码的哥们还是负责的,毕竟兢兢业业地用手工连环
if()判断完成了所有参数的有效性校验:
但问题是,我们真的需要这种辣眼睛的手工连环
if()判断来做参数校验吗?
同样在前文《啥?听说你还在手写复杂的参数校验?》中也说过了,我们其实可以通过注解来方便地规避繁杂的参数校验工作,但前提是不能使用
Map类型传参,需要使用数据模型的定义,就像这样:
class IndexQueryDto { @NotNull(message = "缺少 article_id 信息") private Long article_id; @NotNull(message = "缺少 page 信息") private Integer page; @NotNull(message = "缺少 size 信息") private Integer size; @NotNull(message = "缺少 version 信息") private String version; // ...... 此处省略get/set方法 }
一个
NotNull注解即可搞定,它不香吗?
Map传参真的一无是处吗?
有些小伙伴表示用
Map传参的好处就是可以随意扩展,后期变动灵活,想往里面塞几个参数就塞几个参数;而且也省去了各种对象定义和命名的烦恼。
如果非要用Map传参
如果实在不能避免用
Map传参,也麻请配备完备的测试用例吧,省得让后来接手维护的人天天看着代码怀疑人生了。
通过测试用例,后来接手维护的人也能快速搞清代码间的参数传递和调用,不然真的只能靠脑补画面去调试了。
嘘…
好了,说了这么多,如果你项目的
Controller层代码还在使用
Map传参的话,答应我,二话别说,赶快全部偷偷去改掉,快!速度!跑步前进!
- 点赞 216
- 收藏
- 分享
- 文章举报
- 啃透JDK源码-JCheckBox详解
- Java编程思想第五版(On Java8)读书笔记(一)-什么是对象
- JavaSwing-AbstractButton详解
- JavaSwing-ItemListener接口
- JavaSwing-ItemSelectable
- 写给大忙人看的 Java 基础知识
- 2020中国数字化转型优秀案例征集
- Milvus加入LF AI孵化,立志成为最流行的AI数据平台
- 凌乱的DSP笔记(5)-按键
- 父组件传值子组件
- MySQL数据库常用知识(2)
- TCP漫谈之keepalive和time_wait
- 数据库性能提升利器—Mycat数据切分
- 听说哈佛教授搞了个领导模型,专治95后不服! - 职场生涯
- 不谈宽泛的智能运维,聊聊我在用的异常检测核心算法 - 运维
- 2018 机试
- MySQL数据库常用知识(1)
- 只需一篇文章“吃透”Android多线程技术?大牛最佳总结,建议收藏
- 条形码SDK,开源还是商用?
- 标注案例分享:道路病害图片数据标注项目丨曼孚科技