首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >苍穹外卖:接口设计理念深入与实战及对象属性拷贝

苍穹外卖:接口设计理念深入与实战及对象属性拷贝

作者头像
北极的代码
发布2026-04-22 17:17:32
发布2026-04-22 17:17:32
990
举报

目录

新增员工表时,为什么需要接口设计

1. 实现数据与应用的解耦

2. 保障数据安全与权限控制

3. 规范业务流程与数据校验

4. 提供统一的交互契约

5. 便于监控、统计与限流

总结

接口设计的流程:

第一步:明确业务需求(做什么)

第二步:定义接口契约(长什么样)

1. 接口地址

2. 请求方法

3. 请求参数

4. 返回响应

5. 接口状态码

第三步:编写接口逻辑(怎么做)

第四步:生成接口文档

第五步:联调与测试

Jason数据的来源:

. 如果是“新增员工”时

如果是“查询/编辑员工”时

关于在新增员工中的对象属性拷贝:

1. 首先,为什么要分 DTO 和 Employee(实体)?

2. 为什么不能直接用 Employee 接收前端的参数?

3. 对象属性拷贝在这里起了什么作用?

具体流程:


前言:前面我们学习了项目开发环境的搭建,今天我们学习项目的具体业务操作,以及实现这些业务操作的原理。

新增员工表时,为什么需要接口设计

在新增员工表(或任何数据库表)时,接口设计并不是一个必须与建表同时发生的物理步骤,但它是系统开发中至关重要的一环

简单来说,表是数据的“仓库”,而接口是操作这个仓库的“门”。如果只建表而不设计接口,数据就无法被安全、高效地使用。

以下是为什么在新增员工表时需要(或建议)进行接口设计的几个核心原因:

1. 实现数据与应用的解耦

直接操作数据库的弊端: 如果让前端或其他系统直接连接数据库来操作员工表,意味着数据库的结构(表名、字段名)会暴露给所有调用方。

接口的作用: 接口(API)作为一个中间层,对外隐藏了数据库的具体实现。未来如果需要修改员工表(比如把字段 name 拆分成 first_name 和 last_name),只需要在接口内部做兼容转换即可,调用方无需修改代码。

2. 保障数据安全与权限控制

细粒度控制: 并不是所有人都需要看到员工的全部字段(如薪资、身份证号、家庭住址)。通过接口,可以精确控制返回给客户端的数据内容,只返回必要的信息。

防SQL注入与攻击: 接口层可以对传入的数据进行校验、清洗和防SQL注入处理。如果直接暴露数据库操作,恶意输入可能导致数据泄露或丢失。

3. 规范业务流程与数据校验

业务规则校验: 新增员工不仅仅是在表里插入一条记录。可能伴随复杂的业务逻辑: 工号不能重复,手机号格式必须正确,年龄必须在18-60岁之间,需要同时给该员工开通账户、设置默认密码等。

接口是实现这些复杂校验和事务控制的天然场所,确保数据的完整性和一致性**。

4. 提供统一的交互契约

前后端协作: 在团队开发中,接口设计文档(Swagger/YApi等)相当于前后端开发人员的“契约”。

并行开发: 后端工程师定义好接口(包括URL、请求方法、参数格式、返回示例)后,可以安心去实现内部逻辑;前端工程师可以依据这份文档进行Mock数据模拟,并行开发页面,而不必等待后端代码完全写完。

5. 便于监控、统计与限流

可观测性: 接口层可以方便地记录日志,统计谁在什么时间新增了员工、新增了多少次、哪个接口调用频繁等。

系统保护: 如果遇到突发流量(例如有人恶意刷接口创建大量假员工),接口层可以实施限流、熔断策略,保护底层数据库不被冲垮。

总结

新增员工表时考虑接口设计,本质上是将“数据存储”与“业务使用”分离开来。

只有表: 就像有一个装满文件的柜子,但谁都可以直接伸手进去翻、拿、改,乱成一团。

有表也有接口: 就像给柜子配了一个专业的档案管理员。你想取文件得找他,他会审核你的权限,帮你找到正确的文件,甚至把文件整理成你需要的格式给你。

所以,接口设计是为了让你的员工表用起来更安全、更稳定、更容易维护

接口设计的流程:

第一步:明确业务需求(做什么)

在设计接口之前,需要先搞清楚业务场景。不能只想着“往表里插数据”,而要思考“用户操作时的真实意图”。

业务描述: 管理员在后台点击“新增员工”,填写信息后提交。

涉及数据: 工号、姓名、手机号、邮箱、部门、入职日期等

隐含逻辑: 工号必须全局唯一。 手机号必须验证(11位,符合号段)。 如果没填密码,需要生成一个随机的默认密码。

  • 隐含逻辑:
    • 工号必须全局唯一。
    • 手机号必须验证(11位,符合号段)。
    • 如果没填密码,需要生成一个随机的默认密码。
第二步:定义接口契约(长什么样)

这是接口设计的核心产出,通常包含以下 5 个要素。我们可以使用工具(如 Swagger, Postman, YApi)或文档记录下来:

1. 接口地址 示例: /api/employees 命名规范: 通常使用名词复数形式,代表资源。

2. 请求方法 选择: 新增资源通常使用 HTTP POST 方法。 注:也有少数情况使用 PUT,但 POST 是创建资源最通用的标准。

3. 请求参数 定义前端需要传什么过来。需要指定每个字段的类型、是否必填、以及校验规则。 格式: 通常是 JSON。 示例报文: json { “empId”: “E2025001”, // 工号 [必填, 字符串, 唯一] “name”: “张三”, // 姓名 [必填, 字符串, 1-20位] “mobile”: “13800138000”, // 手机号 [必填, 字符串, 11位] “email”: “zhangsan@qq.com”,// 邮箱 [选填, 符合邮箱格式] “deptId”: “D01”, // 部门ID [必填] “hireDate”: “2026-03-01” // 入职日期 [必填, 日期格式] }

4. 返回响应 定义后端处理完后,返回什么给前端。 成功时的响应: 通常返回创建成功后的数据,或者简单的成功提示。 json { “code”: 200, “message”: “操作成功”, “data”: { “empId”: “E2025001”, “name”: “张三” // ... 可能返回完整的员工对象 } } 失败时的响应: json { “code”: 40001, “message”: “工号已存在,请重新输入” }

5. 接口状态码 定义通用的业务状态码,例如 200 成功、400 参数错误、500 服务器内部错误等。

  • 格式: 通常是 JSON。
  • 示例报文: json { “empId”: “E2025001”, // 工号 [必填, 字符串, 唯一] “name”: “张三”, // 姓名 [必填, 字符串, 1-20位] “mobile”: “13800138000”, // 手机号 [必填, 字符串, 11位] “email”: “zhangsan@qq.com”,// 邮箱 [选填, 符合邮箱格式] “deptId”: “D01”, // 部门ID [必填] “hireDate”: “2026-03-01” // 入职日期 [必填, 日期格式] }

4. 返回响应 定义后端处理完后,返回什么给前端。

  • 成功时的响应: 通常返回创建成功后的数据,或者简单的成功提示。 json { “code”: 200, “message”: “操作成功”, “data”: { “empId”: “E2025001”, “name”: “张三” // ... 可能返回完整的员工对象 } }
  • 失败时的响应: json { “code”: 40001, “message”: “工号已存在,请重新输入” }

5. 接口状态码 定义通用的业务状态码,例如 200 成功、400 参数错误、500 服务器内部错误等。

第三步:编写接口逻辑(怎么做)

契约定义好后,后端开始写代码实现内部逻辑。这一步虽然是对表的操作,但绝不仅仅是 insert into 员工表 这么简单。通常会分为三层:

Controller 层(接口层): 接收前端的请求,拿到 JSON 数据。负责最基础的格式校验。

Service 层(业务层): 编写核心逻辑。 校验1: 工号 E2025001 在数据库里存在吗?如果存在,直接返回“工号重复”的错误。 校验2: 手机号格式对吗?部门 ID 存在吗? 处理: 如果没有传密码,调用工具类生成一个 123456 的加密哈希值。 事务: 如果还需要同时创建员工账户,这里需要用事务包裹,保证两个表同时成功或失败。

Dao/Mapper 层(数据层): 最终拼接成 SQL,执行 insert into employee ...。

  1. Service 层(业务层): 编写核心逻辑。
    • 校验1: 工号 E2025001 在数据库里存在吗?如果存在,直接返回“工号重复”的错误。
    • 校验2: 手机号格式对吗?部门 ID 存在吗?
    • 处理: 如果没有传密码,调用工具类生成一个 123456 的加密哈希值。
    • 事务: 如果还需要同时创建员工账户,这里需要用事务包裹,保证两个表同时成功或失败。

Dao/Mapper 层(数据层): 最终拼接成 SQL,执行 insert into employee ...

第四步:生成接口文档

手动维护: 使用 Swagger 注解写在代码里,启动服务后自动生成在线文档。

工具维护: 在 YApi、Apifox 等平台录入上述信息。

目的: 提供给前端、测试人员查看和调用。

第五步:联调与测试

Mock数据: 在接口写好之前,前端可以根据接口文档,用 Mock 工具模拟返回数据,先画页面。

真实联调: 后端接口写完后,前端把请求地址指向后端的服务,测试数据是否能正确存入数据库。

Jason数据的来源:

. 如果是“新增员工”时

场景: 你在网页表单里填好信息,点提交。这时候发往后端的 JSON,来源于你的操作

  • 来源: 浏览器的内存 + 用户的输入
  • 产生过程:
    1. 你在输入框里打字(比如姓名:张三)。
    2. 前端JavaScript脚本监听到输入,或者在你点击提交时,读取这些输入框里的
    3. 前端JS代码把这些散乱的“值”拼装成一个 JSON 对象:
如果是“查询/编辑员工”时

场景: 你打开编辑页面,发现表单里自动填好了张三的信息。这时候你看到的 JSON 数据,来源于数据库

  • 来源: 数据库(DB) -> 后端服务器 -> 网络 -> 前端
  • 产生过程:
    • 第一步:数据库提供原料
      • 数据库里有一行记录:张三, 13800138000, D01
    • 第二步:后端加工(最关键的一步)
      • 后端代码执行 SQL:select * from employee where id = 123
      • 后端从数据库取出一堆字段(这时的数据在内存里还是ResultSet格式);
      • 后端代码会把这些数据,按照接口设计文档的要求,一个一个字段地塞进一个对象里,然后用JSON库(如Jackson、Fastjson)把这个对象序列化**成 JSON 文本。
    • 第三步:网络传输
      • 后端通过HTTP响应,把这串文本返给前端:
    • 第四步:前端解析
    • 前端拿到这个JSON字符串后,JS引擎会把它解析成JavaScript对象。
    • 然后代码读取 obj.name 的值,把它填充到页面的输入框里

关于在新增员工中的对象属性拷贝:

1. 首先,为什么要分 DTO 和 Employee(实体)?

在项目中,这两个类虽然长得很像,但职责完全不同:

Employee(实体): 对应数据库表。 它的字段结构通常和数据库的 employee 表一一对应。 位置: entity 包。 敏感度: 它包含了所有数据库字段,比如数据库里有个字段 password(密码)、create_time(创建时间)。

EmployeeDTO(数据传输对象): 对应前端请求。 前端传了什么参数,DTO 就写什么字段。 位置: dto 包。 特点: 它只包含前端允许传入的数据。 举例: 在“新增员工”的接口里,前端只需要传用户名、姓名、手机号。前端不应该传密码(即使传了后端也不能信),也不需要传创建时间(这是后端自动生成的)。

  • Employee(实体):
    • 对应数据库表。 它的字段结构通常和数据库的 employee一一对应
    • 位置: entity 包。
    • 敏感度: 它包含了所有数据库字段,比如数据库里有个字段 password(密码)、create_time(创建时间)。
  • EmployeeDTO(数据传输对象):
    • 对应前端请求。 前端传了什么参数,DTO 就写什么字段。
    • 位置: dto 包。
    • 特点: 它只包含前端允许传入的数据。
    • 举例: 在“新增员工”的接口里,前端只需要传用户名姓名手机号。前端不应该密码(即使传了后端也不能信),也不需要创建时间(这是后端自动生成的)。
2. 为什么不能直接用 Employee 接收前端的参数?

如果你在 Controller 里直接写成 public Result save(@RequestBody Employee employee),会发生两个严重问题:

安全隐患(关键): 正常情况下,前端只传 {“name”:“张三”}。 恶意用户抓到接口后,可能会额外传一个 {“name”:“张三”, “password”:“123456”, “status”:0}。 如果后端直接用 Employee 接收,数据库里的 password 和 status 就可能被前端传过来的值覆盖,造成严重的数据篡改。

数据冗余/无效: 前端根本不知道 create_time 是什么格式,也不应该由前端传。

  1. 安全隐患(关键):
    • 正常情况下,前端只传 {“name”:“张三”}
    • 恶意用户抓到接口后,可能会额外传一个 {“name”:“张三”, “password”:“123456”, “status”:0}
    • 如果后端直接用 Employee 接收,数据库里的 passwordstatus 就可能被前端传过来的值覆盖,造成严重的数据篡改。

数据冗余/无效: 前端根本不知道 create_time 是什么格式,也不应该由前端传。

3. 对象属性拷贝在这里起了什么作用?

当你通过了校验,确认前端发来的数据是合法的之后,就需要把数据从 DTO 转移到 Employee 上。

操作前: dto 里有:name, username, phone (这是前端传来的) employee 对象是全新的,什么都没有。

拷贝时(使用 BeanUtils.copyProperties 等工具): 把 dto.name 赋值给 employee.name把 dto.phone 赋值给 employee.phone 注意:只拷贝同名的属性。

拷贝后(补充数据)

  • 拷贝完基础信息后,通常紧接着会手动补充一些 DTO 里没有的字段:
具体流程:
代码语言:javascript
复制
[前端请求]
    |
    |  (只包含:name, phone, username)
    v
[EmployeeDTO]  <-- 这是"干净"的,只包含允许用户输入的数据
    |
    |  使用 BeanUtils.copyProperties
    |  (只拷贝同名属性,如 name->name, phone->phone)
    v
[Employee]     <-- 这是"完整"的,即将入库的数据
    |
    |  手动补充:id, password, createTime, createUser...
    v
[数据库]

结语:如果对你有帮助,请点赞,关注,收藏,你的支持就是我最大的动力!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 新增员工表时,为什么需要接口设计
    • 1. 实现数据与应用的解耦
    • 2. 保障数据安全与权限控制
    • 3. 规范业务流程与数据校验
    • 4. 提供统一的交互契约
    • 5. 便于监控、统计与限流
    • 总结
  • 接口设计的流程:
    • 第一步:明确业务需求(做什么)
    • 第二步:定义接口契约(长什么样)
    • 第三步:编写接口逻辑(怎么做)
    • 第四步:生成接口文档
    • 第五步:联调与测试
  • Jason数据的来源:
    • . 如果是“新增员工”时
    • 如果是“查询/编辑员工”时
  • 关于在新增员工中的对象属性拷贝:
    • 1. 首先,为什么要分 DTO 和 Employee(实体)?
    • 2. 为什么不能直接用 Employee 接收前端的参数?
    • 3. 对象属性拷贝在这里起了什么作用?
    • 具体流程:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档