还记得上次我写过一篇关于实际项目代码分层和规划的文章《看完这篇,别人的开源项目结构应该能看懂了》, 在文尾处提到过一些注意事项,其中第一条就是:

  • Contorller层参数传递建议不要使用HashMap,推荐使用数据模型定义

私信里竟然有很多小伙伴提问说,为什么不能这样做?

我心里暗自寻思:难道这么做的小伙伴都没有被同事捶吗?(滑稽)

得嘞,今天咱们就掰扯掰扯这件事,这是实际写代码时常忽略的一个问题


是不是有人也这么写过?

我自己曾经接手过一个前人留下来的老项目,拿到代码,导入IDEA的那一刻,我哭出了声。


因为它的Controller层代码都是类似这样写的:

@RestController@RequestMapping("/index")public class IndexController {

    // 获取App首页内容    @PostMapping("/getIndexContent")    public ResponseWrapper getIndexContent( @RequestBody Map 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 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层代码还在使用HashMap传参的话,答应我,二话别说,赶快全部偷偷去改掉,快!速度!跑步前进!



每天进步一点点,Peace!

2020.04.02晚

给个[在看],是对程序羊最大的支持

获取map第一个的key和value_谁要是再敢用Map传参,我过去就是一JIO相关推荐

  1. 获取map第一个的key和value_Hadoop学习之路(3)Map-Shuffle-Reduce详解与源码

    @[TOC] 1 Split阶段 首先,接到hdf文件输入,在mapreduce中的map task开始之前,将文件按照指定的大小切割成若干个部分,每一部分称为一个split,默认是split的大小与 ...

  2. 一个多数程序员都会犯的错:Java方法传参的问题

    不是危言耸听,这道题很多人都做错,其中很多是资深开发人员. 请问下面程序运行后输出什么: A.老唐 B.令狐冲 C.杨过 D.郭靖 public class Test {public static v ...

  3. java 一个数组key一个数组value_在各种语言中,使用key在map中获取value 和 使用下标获取数组中的数据 相比哪个更快?...

    数组和集合的效率问题数组是JAVA语言内置的数据类型,它是一个线性的序列,所以它可以快速的访问其他的元素.但是速度是要有代价的,当你创建了一个数组之后,它的容量就固定了,而且在其生命周期里是不能改变的 ...

  4. 获取一个时间段内,每一旬的天数 返回map key=年份+月份+旬 value=天数

    由于我们业务要用的,所以就写了这个方法.判断太多了,不知道考虑全部全,自己能想到的都测了,没有问题. public static Map<String, Integer> getXun(I ...

  5. MyBatis查询两个字段,返回Map,一个字段作为key,一个字段作为value的实现

    1. 问题描述 在使用MyBatis,我们经常会遇到这种情况:SELECT两个字段,需要返回一个Map,其中第一个字段作为key,第二个字段作为value.MyBatis的MapKey虽然很实用,但并 ...

  6. c++ map iterator 获取key_前K个高频的元素衍生之Map的Value与Key排序

    前言 本篇文章总结来自九月份的每日一题 347-前K个高频的元素 思考 对于系列的题目就是计算利用到Hash表的属性的Key与Value的双属性,能够满足我们后面计算对于每一个元素出现的频率的同时还能 ...

  7. mysql map 键值对获取_mysql map_get function,用于解析map结构数据,根据key返回相对应value...

    1.目的 mysql的列是固定的,不支持存储如Map 结构的数据,但现在我们的需求是希望有一个 ext Map的扩展列,可以存储Map结构的数据,并且可以在mysql里面进行运算.(即schema f ...

  8. Map之一个Key存多个Value的MultiValueMap(一个键多个值)

    在日常的开发中经常用到键值对,也就是Map啦,我们知道Map是一个接口,它的特点是一个Key对应一个Value,也就是一个键对应一个值,但是往往我们需要一个Key对应多个Value,这种时候系统的AP ...

  9. Java Map中如何使用key获取value数据呢?

    转自: Java Map中如何使用key获取value数据呢? 下文笔者讲述使用Map.get()方法获取集合中的value值的方法分享,如下所示: 实现思路:借助Map的get方法即可获取value ...

最新文章

  1. python画圣诞帽_用Python给头像加上圣诞帽
  2. RouterOS建立PPPOE服务器
  3. (30个原生js挑战)原生js实现钟表
  4. 独角兽也未能幸免,2019“阵亡”新经济公司大盘点
  5. csdn的自动化评论
  6. Oracle 执行计划 提示 'PLAN_TABLE' is old version 解决方法
  7. sql语句跨服务器跨数据库执行
  8. php入口函数,php 常用的系统函数
  9. python中字符串与字节转换
  10. 杭州微念申请李子柒商标被全部驳回,“最惨打工人”李子柒开始反击:已起诉!...
  11. 2017小米面试题(句子反转)
  12. Java中如何判断两个对象是否相等(Java equals and ==)
  13. two day python基础知识
  14. 华为USG6000防火墙基础配置简介
  15. batchplot插件用法_Batchplot辅助插件常见问题解决方法
  16. Linux-Kali——解决Gnome桌面右键菜单无法打开terminal终端的问题
  17. python开发cms_基于Django的Python CMS---wagtail介绍
  18. linux的字体文件夹在哪里,把windows下的字体安装到Linux系统下的方法介绍
  19. 在服务系统部署MFC程序,出现DLL缺失情况的问题解决方式
  20. Ajax+GridView+Xml的简易留言薄

热门文章

  1. 机器学习是什么--周志华
  2. 中国各类基金资助项目英文翻译(中英文对照)
  3. java封装弊端_JAVA-初步认识-第十三章-同步的好处和弊端
  4. python准备_python环境准备
  5. oracle tabe unlock_Oracle 学习之性能优化(四)收集统计信息
  6. 如何查看cplex的help文档_用摹客,写出更好的产品文档
  7. spring5源码解读
  8. 【数据算法】Java实现二叉树存储以及遍历
  9. BZOJ 1296 粉刷匠(分组背包套DP)
  10. Exynos4412裸机开发 —— 看门狗定时器