网站首页 > 技术文章 正文
1. 前言
今天聊聊我们接触最多的接口,主要是聊接口上的出入参,有的同学就说了,啊不就是接口入参吗,有什么好聊的,大家不都这样用吗,都成规范了;但是所写,都是我在实习公司听到的、见到的一些”现实“
其实聊这个问题,就是希望一些新入行的同学也好,还是外包行业的一些”老油子“也好,我们不得不承认,有些时候我们正在生产难以维护的代码。
虽然这个难以维护是相对的,假如这个项目写出来后,就不再需要任何的维护,不会再有任何的改动,那理论上随你怎么写,因为不会有人再去看这段代码;但是现实中真的有这种情况吗,哪怕有,我相信也很少
2. 使用 Map 作为入参的现象
当我入职的时候,第一个任务是熟悉项目,在我一顿操作后,打开代码,发现接口层出现大量的这种代码:
@PostMapping("/addProject")
public Map addProject(Map map) {
//对某个参数进行校验
if (map.get("id") == null) {
throw new Exception();
}
//使用faster json将map转为对象
Project project = ObjectUtil.ConvertMapToBean(map);
//经过service处理后再返回Map给前端
Map result = projectService.add(project);
return result;
}
复制代码
别的不说先,这里首先就有几个很明显的问题:
- 难以维护:接口入参使用了 Map 进行封装,如果没有接口文档,维护的人很难知道到底传的是什么参数进来,直接进行调试也变成了不可能
- 参数校验又长又臭:需要手动对进行参数校验,假如需要校验的参数特别多,那这个参数校验是不是要写特别的长?
- 低效:每一次入参都是用了 FasterJson 进行转换,这样大大降低了接口的效率,特别是 QPS 高的时候
- 空指针异常:容易造成空指针异常,当我们代码中需要用到的参数去 Map 里获取,假如参数校验没做好,且入参的时候没有传,就会出现空指针异常
当我带着这些问题找到项目的负责人,一开始我认为会是一场讨论,然而我得到的回复是:”这样开发是有好处的,这大大减轻了后端开发的难度,让我们用更少的代码,更少的时间可以把这个事情做好!“
所谓道不同不相为谋,既然项目负责人坚持这么用,那就可以说得通为什么代码里面到处都是这种风格,甚至为了解决使用 Map 而出现的问题封装了一堆解决这些问题的工具类。
带着这些问题我又继续深入学习,一段时间后,我果然的发现,他们是没有接口文档的,不是他们不想用 Swagger,是因为 Map 的封装导致 Swagger 根本无法使用,并且出 Bug 的概率也是相当的高
3. 为何还有人坚持这么做
在我的理解来看,有三种可能:
- 项目负责人追求快速的完成工作,而不追求质量,特别是外包性质的工作,乙方只管完成合同把代码给你,至于维护性什么的,谁理呢?
- 开发项目的同事在初学时,遇到了第一种情况的导师,认为这种情况是理所当然的,长年累积,不愿意改,也不想改,于是又变成了第一种人
- ”老油子“,你们怎么用,我就怎么用,改变什么的,不存在的,团队的风格就是我的风格
4. 现在我们怎么做
看完了反面教材,我们来看看现在大部分人怎么做:
@PostMapping("/students")
public Response<Student> insert(@RequestBody @Validated Student student) {
return success(studentService.save(student));
}
现在的一个业务接口,可能就是这么简单明了,让我们来看看这里都包含了什么信息:
- 遵从 RestFul 风格的 API,使用 Post 来进行保存操作
- 封装了同一的返回对象 Response<Student>,返回的格式是统一的,让前端可以封装统一的接收格式
- 使用了 @RequsetBody + 实体类对象来接收 Json 格式的参数,传了什么一目了然
再来说说这样做的好处:
- 参数校验:接口入参中,添加了 @Validated 注解,只要在 Student 类中添加对应的参数校验注解,就可以对入参进行自动校验,不合规的参数直接返回错误信息
- 一目了然:什么进来了,什么出去了,维护者一目了然
- 目的清晰:熟悉 RestFul 的人一看,基本就能知道你这个接口要做什么
- 接口文档:同样的,这种接口可以引入 Swagger 等自动化接口文档工具,可以在开发的时候花一点点时间就把接口文档写好,同时更新的时候也只需要该少量的代码
5. 写在最后
随着技术、项目的迭代,也许这种现象会越来越少直至消失,但是我想要表达的思想是:
- 当我们遇到技术时,不能盲目的使用,而是要横向对比,你得明白,他能干什么,不能干什么,给未来的自己留一条退路
- 也许你不得已在做错的事情,但是你要明白你做的事情是错的,并且努力修正这个错误,比如做好注释
- 努力用技术武装自己,哪怕你只是在这个行业呆一段时间,也请你有基本的职业道德,尽量不给后人埋坑
猜你喜欢
- 2025-07-28 如何优雅的实现 Spring Boot 接口参数加密解密?
- 2025-07-28 SpringBoot注解最全详解(9大常用注解)
- 2025-07-28 SpringBoot注解全攻略:这些注解让你的代码更专业!
- 2025-07-28 后端使用技术 —— 规范统一入口方法
- 2025-07-28 关于远程调用feign的优雅写法(feign远程调用怎么用restful)
- 2025-07-28 自研分布式高性能RPC框架及服务注册中心ApiRegistry实践笔记
- 2025-07-28 spring基础面试题整理(2)(spring基本面试题)
- 2025-07-28 Spring Boot异常处理太难搞,这样实现让你轻松应对!
- 2025-07-28 独立开发:高效集成大模型,看这篇就够了
- 2025-07-28 Spring&SpringBoot常用注解总结
- 1518℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 600℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 521℃MySQL service启动脚本浅析(r12笔记第59天)
- 490℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 489℃启用MySQL查询缓存(mysql8.0查询缓存)
- 477℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 457℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 454℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- windowsscripthost (69)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)