后端开发阶段性总结

一、先看接口文档,明确需求

从你截图的接口文档可以看到:

复制代码
POST /admin/employee/status/{status}

Path参数:  status  (1=启用,0=禁用)
Query参数: id      (员工ID)

也就是说,前端发的请求长这样:

复制代码
POST /admin/employee/status/0?id=2

意思是:把 id=2 的员工状态改成 0(禁用)。


二、完整开发流程(从外到内)

第 1 步:Controller 层 ------ 接收请求

你已经写了:

复制代码
@PostMapping("/status/{status}")
@ApiOperation("启用禁用员工账号")
public Result startOrStop(@PathVariable Integer status, Long id) {
    log.info("启用禁用员工账号:{},{}", status, id);
    employeeService.startOrStop(status, id);
    return Result.success();
}

关键点:

  • @PathVariable Integer status:从路径 /status/0 里取出 0
  • Long id:从 URL ?id=2 里自动取出(没有 @RequestParam 也能自动封装,因为参数名和 query 参数名一致)
  • 自己不写业务,调用 Service

第 2 步:Service 层 ------ 业务逻辑

复制代码
// 接口
void startOrStop(Integer status, Long id);

// 实现
public void startOrStop(Integer status, Long id) {
    // 1. 构建一个 Employee 对象,只设置需要更新的字段
    Employee employee = new Employee();
    employee.setId(id);
    employee.setStatus(status);
    employee.setUpdateTime(LocalDateTime.now());
    employee.setUpdateUser(BaseContext.getCurrentId());  // 当前登录用户

    // 2. 调用通用的 update 方法
    employeeMapper.update(employee);
}

为什么这样设计?

  • 启用 / 禁用本质上就是更新员工的 status 字段
  • 不需要把整个员工信息传进去,只需要 id + status + 审计字段
  • 复用通用的 update 方法,不用单独写 SQL

第 3 步:Mapper 层 ------ 动态更新 SQL

你在 XML 里写了通用的 update

复制代码
<update id="update" parameterType="Employee">
    update employee
    <set>
        <if test="name != null">name=#{name},</if>
        <if test="username != null">username=#{username},</if>
        <if test="password != null">password=#{password},</if>
        <if test="phone != null">phone=#{phone},</if>
        <if test="sex != null">sex=#{sex},</if>
        <if test="idNumber != null">id_number=#{idNumber},</if>
        <if test="updateTime != null">update_time=#{updateTime},</if>
        <if test="updateUser != null">update_user=#{updateUser},</if>
        <if test="status != null">status=#{status},</if>
    </set>
    where id=#{id}
</update>

<set> + <if> 的工作原理:

  • <set> 自动加 set 关键字,自动去掉最后多余的逗号

  • 每个 <if> 判断字段不为 null 才更新这个字段

  • 启用 / 禁用时,Employee 对象里只有 id/status/updateTime/updateUser 有值,其他都是 null

  • 所以最终 SQL 是:

    update employee set status=0, update_time=?, update_user=? where id=2


三、你 XML 里有个错误!

看你截图这行:

复制代码
<if test="idNumber !=null">update_Time =#{updateTiem},</if>
<!--              ↑                          ↑
          条件是idNumber,但更新的是update_Time?
          而且updateTiem拼写也错了(应该是updateTime)

这行明显是复制粘贴错了,应该改成:

复制代码
<if test="idNumber != null">id_number=#{idNumber},</if>

这个错误会导致:编辑员工时修改身份证号不生效,反而可能错误更新时间。一定要改!


四、调用链路图

复制代码
前端请求
POST /admin/employee/status/0?id=2
    │
    ▼
【Controller】
  @PathVariable status=0
  自动封装 id=2
  → employeeService.startOrStop(0, 2)
    │
    ▼
【Service】
  构建 Employee{id=2, status=0, updateTime=now, updateUser=当前用户}
  → employeeMapper.update(employee)
    │
    ▼
【Mapper XML】
  <set> 动态判断,只更新非null字段
  → update employee set status=0, update_time=?, update_user=? where id=2
    │
    ▼
  数据库:员工id=2 的状态变成 0(禁用)

五、这个功能和 "编辑员工" 复用同一个 update

你写的这个通用 update 方法,两个功能都能用

表格

功能 传什么字段 最终更新什么
启用 / 禁用 id, status, updateTime, updateUser 只更新状态
编辑员工 id, name, username, phone, sex, idNumber, updateTime, updateUser 更新基本信息

这就是动态 SQL 的好处:一个 update 方法,按需更新不同字段,不用为每个功能单独写 SQL。


六、开发顺序总结

复制代码
1. 看接口文档,确定请求方式、路径、参数
2. 写 Controller(@PathVariable 接路径参数,普通参数接 query)
3. 写 Service 接口 + 实现(构建对象,调用 update)
4. 写 Mapper 接口方法声明
5. 写 Mapper XML(<set> + <if> 动态更新)
6. 启动测试:POST /admin/employee/status/0?id=2
7. 去数据库确认 status 变成 0

一句话总结

启用 / 禁用员工 = 更新 status 字段 ,Controller 用 @PathVariable 取路径里的 status、用参数自动封装取 id,Service 构建只含必要字段的 Employee 对象,Mapper 用 <set>+<if> 动态更新非 null 字段。记得把 XML 里 idNumber 那行的错误改过来。

先把 XML 那个错误修了,然后启动测试一下启用 / 禁用功能,有问题继续问。

今天 22:08

怎么根据接口 进行设计

接口设计相关问题

这是后端开发最核心的能力 ------拿到接口文档就能设计出完整代码。我给你一套通用的方法论,配合你学过的功能举例。


第一步:从接口文档提取 4 个关键信息

拿到任何一个接口,先看这 4 样东西:

表格

看什么 决定什么 例子
请求方式 Controller 用哪个注解 POST → @PostMapping,GET → @GetMapping
请求路径 Controller 的 URL 映射 /admin/employee@RequestMapping
入参(参数) 用什么接收、DTO 怎么设计 JSON 体 → @RequestBody,URL 参数 → 普通参数
出参(返回) 返回什么类型 Result / Result<T> / Result<PageResult>

第二步:根据请求方式 + 路径,设计 Controller

规则

复制代码
请求方式是 POST/PUT  →  方法上用 @PostMapping / @PutMapping
请求方式是 GET       →  方法上用 @GetMapping
路径里有 {xxx}       →  方法参数用 @PathVariable

对照你学过的 3 个接口

接口 1:新增员工

复制代码
POST /admin/employee
Body: {"name":"张三",...}

→ Controller 设计:

复制代码
@PostMapping
public Result save(@RequestBody EmployeeDTO dto) { }

接口 2:员工分页查询

复制代码
GET /admin/employee/page?name=李&page=1&pageSize=10

→ Controller 设计:

复制代码
@GetMapping("/page")
public Result<PageResult> page(EmployeePageQueryDTO dto) { }
// 注意:没有 @RequestBody,GET请求参数自动封装

接口 3:启用禁用员工

复制代码
POST /admin/employee/status/{status}?id=2

→ Controller 设计:

复制代码
@PostMapping("/status/{status}")
public Result startOrStop(@PathVariable Integer status, Long id) { }
// status在路径里 → @PathVariable
// id在URL?后面 → 普通参数自动封装

第三步:根据入参,设计 DTO

规则

复制代码
参数是JSON对象   →  建一个DTO类,字段和JSON的key对应
参数是URL拼接的  →  可以建DTO,也可以直接用零散参数
参数是路径里的   →  直接用 @PathVariable,不用建DTO

怎么判断要不要建 DTO?

表格

参数情况 做法 例子
1-2 个简单参数 直接写在方法参数里 startOrStop(Integer status, Long id)
3 个以上参数 封装成 DTO page(EmployeePageQueryDTO dto)
JSON 请求体 必须封装成 DTO save(@RequestBody EmployeeDTO dto)

DTO 字段怎么定?

照着接口文档的参数列表写,一个都不能少:

复制代码
接口文档入参:name, username, phone, sex, idNumber
↓
EmployeeDTO 字段:name, username, phone, sex, idNumber

字段名必须和接口文档一模一样,否则 @RequestBody 或 query 自动封装时匹配不上。


第四步:根据业务逻辑,设计 Service

Service 要做什么?

Controller 只负责 "收发",所有业务逻辑都在 Service 里。问自己几个问题:

  1. 需要做数据转换吗? → DTO 转 Entity(BeanUtils.copyProperties
  2. 需要补充默认值吗? → 状态、密码、时间、创建人
  3. 需要做校验吗? → 用户名是否重复、账号是否锁定
  4. 需要调用几个 Mapper? → 单表操作还是多表操作

对照你学过的功能

新增员工的 Service 逻辑:

复制代码
1. DTO → Entity(属性拷贝)
2. 补充默认值:status=1, password=MD5(123456), createTime, updateTime, createUser, updateUser
3. 调用 mapper.insert

启用禁用的 Service 逻辑:

复制代码
1. 构建一个 Employee 对象,只设置需要更新的字段
2. 设置 id, status, updateTime, updateUser
3. 调用 mapper.update(动态更新)

分页查询的 Service 逻辑:

复制代码
1. PageHelper.startPage 开启分页
2. 调用 mapper.pageQuery
3. 从 Page 对象取出 total 和 records
4. 封装成 PageResult 返回

第五步:根据数据库操作,设计 Mapper

规则

复制代码
简单 SQL(单表单条件)→ 注解方式 @Select/@Insert/@Update
复杂 SQL(动态条件、多表关联)→ XML 方式

怎么判断用注解还是 XML?

表格

SQL 类型 方式 例子
简单插入 注解 @Insert 新增员工
简单查询(按 id / 按用户名) 注解 @Select 根据用户名查员工
动态条件查询 XML <where>+<if> 分页查询(name 可选)
动态更新 XML <set>+<if> 编辑员工、启用禁用
多表关联查询 XML 订单查询(后面学)

Mapper 方法的入参和返回值怎么定?

复制代码
插入 → 参数是 Entity,返回 void
更新 → 参数是 Entity,返回 void
根据id查 → 参数是 Long id,返回 Entity
分页查 → 参数是 DTO,返回 Page<Entity>

第六步:根据出参,设计返回结果

规则

复制代码
所有接口统一返回 Result<T>
不需要返回数据 → Result
需要返回对象 → Result<Employee>
需要返回分页 → Result<PageResult>
需要返回列表 → Result<List<Employee>>

对照你学过的

表格

接口 返回什么 方法签名
新增员工 不需要数据 Result save(...)
启用禁用 不需要数据 Result startOrStop(...)
分页查询 分页数据 Result<PageResult> page(...)
根据 id 查员工 员工对象 Result<Employee> getById(...)

完整设计流程图

复制代码
拿到接口文档
    │
    ├── 看请求方式+路径 → 设计 Controller 映射
    │
    ├── 看入参
    │     ├── JSON体 → 建DTO + @RequestBody
    │     ├── URL参数 → 建DTO 或 零散参数
    │     └── 路径参数 → @PathVariable
    │
    ├── 看出参 → 设计返回类型 Result<T>
    │
    ├── 想业务逻辑 → 设计 Service(转换、补值、校验、调Mapper)
    │
    └── 想数据库操作 → 设计 Mapper
          ├── 简单SQL → 注解
          └── 复杂SQL → XML动态标签

拿一个新接口练手:编辑员工

假设接口文档是:

复制代码
PUT /admin/employee
Body: {"id":2, "name":"张三", "username":"zhangsan", "phone":"138...", "sex":"男", "idNumber":"..."}
返回:Result

按上面的方法设计:

1. Controller:

复制代码
@PutMapping
public Result update(@RequestBody EmployeeDTO dto) {
    employeeService.update(dto);
    return Result.success();
}

2. DTO: 用已有的 EmployeeDTO(里面有 id、name、username 等字段)

3. Service:

复制代码
public void update(EmployeeDTO dto) {
    Employee employee = new Employee();
    BeanUtils.copyProperties(dto, employee);
    employee.setUpdateTime(LocalDateTime.now());
    employee.setUpdateUser(BaseContext.getCurrentId());
    employeeMapper.update(employee);  // 复用你写的动态update
}

4. Mapper: 复用已有的 update 方法(XML 动态 SQL)

你看,编辑员工几乎不用写新代码,复用之前的 DTO 和 update 方法就行。


一句话总结

接口文档 = 设计蓝图:请求方式和路径决定 Controller,入参决定 DTO 和接收方式,出参决定返回类型,业务逻辑决定 Service,数据库操作决定 Mapper。按照这个顺序一步步来,任何接口都能设计出来。

相关推荐
学逆向的1 小时前
PE——合并节
开发语言·网络安全·pe
是个西兰花1 小时前
C++11:线程库与线程安全问题
开发语言·c++
点心的游戏开发世界1 小时前
GDScript 入门笔记(十三):字符串操作
开发语言·笔记·游戏引擎·godot
计算机学姐2 小时前
基于SpringBoot的旅游系统的设计与实现
java·vue.js·spring boot·后端·spring·java-ee·旅游
卷心菜的学习路2 小时前
Spring Boot 多数据源落地:AbstractRoutingDataSource + 注解切面(附源码)
java·spring boot·后端
少司府2 小时前
C++进阶:智能指针
开发语言·数据结构·c++·b树·算法·c·智能指针
matlab代码2 小时前
基于matlab的红绿灯图像检测识别系统【源码60期】
开发语言·matlab
秋饼2 小时前
Spring AI AgentCore SDK 企业级实战:@AgentCoreInvocation 一注解替代 3000 行 Runtime 契约
java·ai·技术分享·后端开发
薄雾晚晴2 小时前
大模型Skill暴论:所有Skill终将消亡?最新Skill方法论与模型增强开发实战
前端·后端·架构