(三十四)如何在Apifox工具中写接口文档(java)+【新增部门+数据库和代码双重保障防重】
一、在Apifox工具中创建一个项目
第一步:选择项目类型
界面默认选中的 「通用模式」 就是我们要用的,它适合可视化接口设计、调试和自动生成文档,不用切换其他选项。

第二步:填写项目名称
在「项目名称」输入框里,给你的项目起个名字,比如:部门管理API接口文档(写个你自己能看懂的就行)

第三步:点击「创建」
右下角的「创建」按钮会自动亮起,点击它就能进入项目主界面。

太棒了!项目创建完成,接下来我带你一步步把你的 5 个接口(增删改查)做成完整的接口文档,全程跟着点就行👇
二、创建好项目,先配置「环境」(只做一次,后面所有接口通用)
- 进入项目后,点击左侧菜单栏的 「环境管理」
- 点击「新建环境」,配置如下:
- 环境名称:
本地开发环境 - 前置 URL:
http://localhost:8089(你的后端服务地址)
- 环境名称:
- 保存后,在右上角环境下拉框,把它设为默认环境。

你现在的场景,直接选 「开发环境」 就可以了,然后把前置 URL 改成你本地后端地址。
1. 环境选择
- 左侧列表里,当前高亮的 「开发环境」 就是我们要用的,不用新建别的环境。
- 其他几个环境(测试 / 正式 / Mock)暂时不用管,后续项目上线了再用。
2. 关键配置:修改前置 URL
把当前输入框里的默认地址 http://dev-cn.your-api-server.com 删掉,换成你的本地服务地址:
http://localhost:8089
(和你 IDEA 里 Spring Boot 项目启动的端口保持一致)
3. 保存生效
修改完成后,点击右下角的 「保存」 或 「保存并关闭」 就可以了。
三、环境配置好以后,创建「接口目录」,把 5 个接口分类管理
我们需要完成整体CRUD 通俗解释(部门模块对应)
| 缩写 | 英文 | 中文功能 | 对应接口 |
|---|---|---|---|
| C | Create | 新增数据 | POST /depts 添加新部门 |
| R | Read | 查询数据 | GET /depts、GET /depts/{id}(这是2个接口) |
| U | Update | 修改数据 | PUT /depts/{id} 修改部门名字 |
| D | Delete | 删除数据 | DELETE /depts/{id} 删除部门 |
- 查全部:GET /depts → 页面展示部门列表
- 查单个:GET /depts/{id} → 编辑 / 详情页回显数据
- POST /depts 新增部门(添加新部门)
- PUT /depts/{id} 修改部门(改部门名称)
- DELETE /depts/{id} 删除部门(删掉部门)
创建「接口目录」
- 点击左侧「接口管理」→ 点「+ 新建」→ 选择「新建目录」
- 目录名称写:
部门管理接口后续我们把 5 个接口都放到这个目录里,文档结构会更清晰。

3.新建一个叫“部门管理接口”的文件夹-点添加目录

(一)创建 GET 接口・查询所有部门列表・核心五步
第一步:添加HTTP接口“部门管理接口”的接口

第二步:填写接口地址,点击发送,测试 GET 接口连通性。

第三步:测试 GET 接口连通性,成功后,填写接口名字“查询所有部门列表”


第四步:测试成功后,先把这个接口的文档补全
1.点击下方的 「文档模式」 切换过去


2.点击上方的 「编辑页面」 切换过去

3.填接口功能和请求说明、返回说明文档

非必填项目

✅ 当前【查询所有部门列表】接口全部标签说明:全都不用填,保持空白
- Params:无参数,空白
- Body:GET 接口没有请求体,空白
- Headers/Cookies/Auth/ 前置 / 后置操作 / 设置:无鉴权、无特殊请求头,全部留空即可
第五步:接口文档字段说明通过JAON生成
操作步骤
- 点击右上角【通过 JSON 生成】按钮
- 复制下方示例 JSON 填入生成框
{"code":1,"msg":"操作成功","data":[{"id":1,"name":"技术部","createTime":null,"updateTime":null}]}
- 确认生成,系统自动创建所有返回字段



小细节:找到createTime、updateTime,在字段右侧勾选 N(允许为空),类型保持string不变,保存。

结构完全正确,只改 2 处类型 + 填充中文名、说明
表格
| 字段 | 类型修正 | 中文名 | 说明 |
|---|---|---|---|
| code | integer 不变 | 响应码 | 1 = 接口成功,0 = 业务失败 |
| msg | string 不变 | 提示信息 | 接口执行返回的文字提示 |
| data | array 不变 | 部门列表 | 多条部门数据组成的数组 |
| id | integer 不变 | 部门 ID | 部门唯一主键编号 |
| name | string 不变 | 部门名称 | 部门名字 |
| createTime | null → string | 创建时间 | 部门创建时间,可为空 |
| updateTime | null → string | 更新时间 | 部门最后修改时间,可为空 |
再测试 GET 接口连通性,成功。
完成:页面点【保存】,GET /depts 查询所有部门 接口完工。
(二)创建 GET 接口・根据ID查询单个部门・核心五步
第一步:添加HTTP接口“根据ID查询单个部门”的接口
第二步:在调试页面输入/depts/{id}参数填1测试这个接口联通性再保存
第三步:测试 GET 接口连通性,成功后,填写接口名字“根据ID查询单个部门”


第四步:测试成功后,先把这个接口的文档补全
在编辑页面,填写根据 ID 查询单个部门接口说明文档
1、接口基础信息
表格
| 项目 | 内容 |
|---|---|
| 接口地址 | /depts/{id} |
| 请求方式 | GET |
| 接口用途 | 根据部门主键 ID,查询单条部门详情数据 |
| 请求参数 | Path 路径参数:id |
2、请求参数说明
表格
| 参数名 | 参数类型 | 中文名 | 说明 |
|---|---|---|---|
| id | integer | 部门主键 ID | 必填,需要查询的部门编号,数据库无对应数据时返回 data=null |
3、返回 JSON 示例
json
{
"code": 1,
"msg": "操作成功",
"data": {
"id": 1,
"name": "技术部",
"createTime": null,
"updateTime": null
}
}
4、返回字段说明
表格
| 字段 | 类型 | 中文名 | 字段释义 |
|---|---|---|---|
| code | integer | 响应码 | 1 = 接口业务执行成功;0 = 业务处理失败 |
| msg | string | 提示信息 | 接口执行结果文字描述 |
| data | object | 部门详情对象 | 单条部门实体,无数据时为 null |
| →id | integer | 部门 ID | 部门唯一主键编号 |
| →name | string | 部门名称 | 部门名称 |
| →createTime | string | 创建时间 | 部门创建时间,字段允许为 null(未创建则为空) |
| →updateTime | string | 更新时间 | 部门最后修改时间,字段允许为 null(未修改则为空) |
5、调用说明
- 仅需要在路径携带 id 参数,无 Query 参数、无 Body 请求体;
- HTTP 状态码 200 代表接口请求正常,
data=null表示数据库不存在该 ID 的部门; - 想要查询 id=2 的数据,需要先调用新增部门接口存入 id=2 的数据。
第五步:接口文档字段说明通过JAON生成
操作步骤
- 点击右上角【通过 JSON 生成】按钮
2.填上对应说明


(三)创建 POST 接口・新增部门・核心五步
第一步:添加HTTP接口“新增部门”的接口
- 点击【Body】标签页,格式选择:JSON
- 输入新增参数:
- Params 全部留空,直接点【发送】
{"name":"财务部"}

第二步:点击发送,测试接口联通性,再保存为”新增部门“的HTTP接口


第三步:用 GET 接口查询“查询所有部门列表”,发现多了一个“财务部”

小知识
-
没做名称唯一校验时连续发
{"name":"财务部"},数据库:id=2 财务部id=3 财务部id=4 财务部…… 无限新增多条同名数据。 -
后续开发加限制(二选一)
- 方案 1:数据库给
name加唯一约束 → 同名新增直接报错,不让重复添加; - 方案 2:后端代码先查询,存在同名就返回失败,不再入库。
第四步:测试成功后,先把这个接口的文档补全
POST 新增部门接口文档
1. 基础信息
表格
| 项目 | 内容 |
|---|---|
| 接口地址 | /depts |
| 请求方式 | POST |
| 接口作用 | 新增一条部门数据,自动生成主键 ID 存入数据库 |
| 编码格式 | Content-Type: application/json |
2. 请求入参(Body JSON)
表格
| 字段名 | 数据类型 | 必填 | 中文名 | 说明 |
|---|---|---|---|---|
| name | string | 是 | 部门名称 | 部门自定义名称,不能为空字符串;如需禁止重复名称需后端 + 数据库配置唯一约束 |
请求示例
json
{"name":"财务部"}
3. 返回数据示例
json
{
"code": 1,
"msg": "操作成功",
"data": {
"id": 2,
"name": "财务部",
"createTime": null,
"updateTime": null
}
}
4. 返回字段说明
表格
| 字段 | 类型 | 中文名 | 备注 |
|---|---|---|---|
| code | integer | 响应码 | 1 = 业务执行成功;0 = 业务失败(如重名校验不通过) |
| msg | string | 提示信息 | 接口执行结果描述文字 |
| data | object | 部门实体 | 新增完成的部门详情 |
| →id | integer | 部门主键 ID | 数据库自增生成,唯一标识 |
| →name | string | 部门名称 | 提交的部门名称 |
| →createTime | string | 创建时间 | 允许为 null,后续业务生成入库时间 |
| →updateTime | string | 修改时间 | 允许为 null,首次新增无修改数据 |
5. 调用说明
- 无 Query 参数、无 Header 自定义参数,仅 JSON 传参;
- 参数
name为空直接请求,后端校验失败返回错误; - 未配置数据库唯一约束时,重复提交同名名称会持续新增多条数据;
- 新增成功后,可通过
GET /depts/{id}、GET /depts查询验证数据。
6. 异常说明
- 400:未携带 Body 请求体、name 为空;
- 自定义异常:开启 name 唯一约束后,重复名称新增返回业务失败。
第五步:接口文档字段说明通过JAON生成
操作步骤
- 点击右上角【通过 JSON 生成】按钮
2.填上对应说明

(四)创建接口・删除部门・核心五步
第一步:添加HTTP接口“删除部门”的接口

第二步:在调试页面选DELETE 输入:http://localhost:8089/depts/4测试这个接口联通性再保存
第三步:保存接口“删除部门”HTTP的接口。

第四步:写说明文档
DELETE 删除部门接口文档
一、基础信息
表格
| 项目 | 内容 |
|---|---|
| 接口地址 | DELETE /depts/{id} |
| 请求方式 | DELETE |
| 接口作用 | 根据主键 ID 删除指定部门数据 |
| 编码格式 | application/json |
二、请求参数
路径参数
表格
| 参数名 | 数据类型 | 必填 | 说明 |
|---|---|---|---|
| id | Integer | 是 | 需要删除的部门主键 ID,路径占位符,调试替换为数字,例:/depts/4 |
请求 Body
无请求体,Body 内容留空。
三、返回数据
返回示例
json
{
"code": 1,
"msg": "操作成功",
"data": null
}
返回字段说明
表格
| 字段 | 类型 | 中文名 | 备注 |
|---|---|---|---|
| code | integer | 业务状态码 | 1 = 删除成功;0 = 删除失败(ID 不存在) |
| msg | string | 提示信息 | 操作结果描述文案 |
| data | object | 部门数据 | 允许为 null,删除后无实体数据,统一返回 null |
四、调用示例
- 请求地址:
http://localhost:8089/depts/4 - 请求方式:DELETE
- 成功返回:如上示例 JSON
五、校验验证方式
删除完成后调用 GET /depts/4 查询接口,返回data:null,代表数据已从数据库删除。
六、异常场景
- 路径 id 传入非数字字符串 → 后端参数类型转换异常;
- id 在数据库不存在 → 返回
code:0,msg:"部门不存在",data:null。
第五步:接口文档字段说明通过JAON生成
操作步骤
- 点击右上角【通过 JSON 生成】按钮
2.填上对应说明

(五)创建接口・修改部门・核心五步
修改部门(PUT)新建接口步骤
第一步:添加 HTTP 接口根据 ID 修改部门
第二步:调试页录入地址/depts/{id},路径参数 id 填已有部门编号(如 3),Body 填写{"name":"财务总部"},发送测试连通后保存
第三步:PUT 请求调试连通成功,填写接口名称根据 ID 修改部门
前面的代码中:@PutMapping 没有写/{id}路径,当前接口地址是PUT /depts,不是PUT /depts/{id},所以访问/depts/3报 405
1、原来的代码
@PutMapping
public Result update(@RequestBody Dept dept) {
deptService.update(dept);
return Result.success();
}
2、现在改代码
@PutMapping("/{id}")
public Result update(@PathVariable Integer id, @RequestBody Dept dept) {
dept.setId(id); // 把路径id绑定到实体
deptService.update(dept);
return Result.success(dept); // 返回修改后的部门数据
}
2、改完操作
- 重启 SpringBoot 项目
- Apifox 保持:
PUT http://localhost:8089/depts/3,Body:{"name":"后勤部"},再次发送测试

第四步:PUT 根据 ID 修改部门接口文档
一、基础信息
表格
| 项目 | 内容 |
|---|---|
| 接口地址 | PUT /depts/{id} |
| 请求方式 | PUT |
| 接口用途 | 根据路径携带的部门 ID,更新部门名称 |
| 数据格式 | Content-Type: application/json |
二、请求参数
1. 路径参数
表格
| 参数名 | 数据类型 | 必填 | 参数说明 |
|---|---|---|---|
| id | Integer | ✅是 | 需要修改的部门主键编号,调试时替换为真实数字,例:/depts/3 |
2. 请求体 Body(JSON)
json
{"name":"财务总部"}
表格
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | String | ✅是 | 修改后的部门名称,不能为空字符串 |
三、返回数据说明
返回成功示例
json
{
"code": 1,
"msg": "操作成功",
"data": {
"id": 3,
"name": "财务总部",
"createTime": null,
"updateTime": null
}
}
返回字段释义
表格
| 字段 | 类型 | 中文名 | 备注 |
|---|---|---|---|
| code | Integer | 业务状态码 | 1 = 修改成功;0 = 修改失败(ID 不存在) |
| msg | String | 提示信息 | 接口执行结果描述 |
| data | Object | 部门实体 | 修改完成后的完整部门数据 |
| →id | Integer | 部门主键 | 路径传入的修改 ID |
| →name | String | 部门名称 | 修改后的新名称 |
| →createTime | String | 创建时间 | 允许为 null,数据创建时间 |
| →updateTime | String | 更新时间 | 允许为 null,首次修改可空 |
四、调用示例
- 请求地址:
http://localhost:8089/depts/3 - 请求方式:PUT
- 请求体:
{"name":"财务总部"}
五、验证方案
调用GET /depts/3单查接口,查询出的 name 变为【财务总部】即修改生效。
六、异常场景
- 路径 id 不存在:返回
code:0、msg:"部门不存在"、data:null; - body 中 name 为空:后端参数校验失败,返回错误提示。
第五步:接口文档字段说明通过JAON生成
操作步骤
- 点击右上角【通过 JSON 生成】按钮
2.填上对应说明
附:部门模块 CRUD 全接口汇总
GET /depts:查询全部部门GET /depts/{id}:根据 ID 单查部门POST /depts:新增部门DELETE /depts/{id}:删除部门PUT /depts/{id}:修改部门
这里我们做一个【新增部门+数据库和代码双重保障防重】
部门名称防重复新增 开发存档文档
先改数据库代码,直接复制代码到数据库
一、第一步:Mapper 层代码
1.DeptMapper 接口
// 根据部门名称查询
Dept selectByName(@Param("name") String name);
2.本次需求
新增部门时同名不能重复插入:代码 Service 层查重 + 数据库唯一索引双重拦截,重复返回统一错误 JSON,弹窗由前端接收 code=0 实现。
二、数据库修改(DataGrip 执行 SQL)
1、执行语句(tlias 库 dept 表)
-- 给name添加唯一约束,数据库底层禁止重名
ALTER TABLE dept ADD UNIQUE uk_dept_name(name);
绕过 Java 代码直接插库也会报错,兜底防重。
-- 切换到 tlias 数据库
USE tlias;
-- 如果 dept 表已存在,先删除(避免报错)
DROP TABLE IF EXISTS dept;
-- 创建部门表,和你的 Dept.java 实体类完全对应
CREATE TABLE dept (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '部门ID',
name VARCHAR(50) NOT NULL COMMENT '部门名称',
update_time DATETIME NOT NULL COMMENT '最后操作时间'
) COMMENT '部门表';
-- 插入和老师 dept.txt 里一模一样的测试数据
INSERT INTO dept (name, update_time)
VALUES
('教研部', '2023-01-01 12:00:00'),
('学工部', '2023-02-01 12:00:00'),
('研发部', '2023-03-01 12:00:00'),
('人事部', '2023-04-01 12:00:00'),
('行政部', '2023-05-01 12:00:00');
-- 给name字段添加唯一约束,部门名称不能重复
ALTER TABLE dept ADD UNIQUE uk_dept_name(name);
-- 查询验证数据是否插入成功
SELECT * FROM dept;
三、需要修改的已有文件(共 4 个)
① DeptMapper.java(mapper 接口)
新增方法:按名称查询部门
//【本次新增】根据部门名称查询
Dept selectByName(@Param("name") String name);
package org.example.lvzhiaiserver.mapper;
import org.example.lvzhiaiserver.entity.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface DeptMapper {
List<Dept> list();
Dept getById(Integer id);
void insert(Dept dept);
void update(Dept dept);
void deleteById(Integer id);
//【本次新增】根据部门名称查询
Dept selectByName(@Param("name") String name);
}
② DeptMapper.xml(映射文件)
新增 selectByName 标签,所有 resultType 统一全类名
<!--【本次新增】按名字查询SQL -->
<select id="selectByName" resultType="org.example.lvzhiaiserver.entity.Dept">
select id,name,update_time from dept where name = #{name}
</select>
1、修改 DeptMapper.xml(全部 SQL 删掉 create_time)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.lvzhiaiserver.mapper.DeptMapper">
<select id="list" resultType="org.example.lvzhiaiserver.entity.Dept">
select id, name, update_time from dept
</select>
<select id="getById" resultType="org.example.lvzhiaiserver.entity.Dept">
select id, name, update_time from dept where id = #{id}
</select>
<select id="selectByName" resultType="org.example.lvzhiaiserver.entity.Dept">
select id,name,update_time from dept where name = #{name}
</select>
<insert id="insert">
insert into dept (name, update_time)
values (#{name}, #{updateTime})
</insert>
<update id="update">
update dept set name = #{name}, update_time = #{updateTime} where id = #{id}
</update>
<delete id="deleteById">
delete from dept where id = #{id}
</delete>
</mapper>
③ DeptService.java(Service 接口)
新增抽象方法 getByName (String name)
//【本次新增】根据名称查询部门
Dept getByName(String name);
package org.example.lvzhiaiserver.service;
import org.example.lvzhiaiserver.entity.Dept;
import java.util.List;
public interface DeptService {
List<Dept> list();
Dept getById(Integer id);
void add(Dept dept);
void update(Dept dept);
void delete(Integer id);
//【本次新增】根据名称查询部门
Dept getByName(String name);
}
④ DeptServiceImpl.java(Service 实现类)
- 实现 getByName 方法
- add () 方法内部增加名称查重逻辑,重名抛运行时异常
// 新增:实现接口的getByName
@Override
public Dept getByName(String name) {
return deptMapper.selectByName(name);
}
@Override
public void add(Dept dept) {
// 查重逻辑
Dept existDept = getByName(dept.getName());
if (existDept != null) {
throw new RuntimeException("部门名称已存在,不能重复添加");
}
// 删除setCreateTime,数据库无此字段
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
package org.example.lvzhiaiserver.service.impl;
import org.example.lvzhiaiserver.entity.Dept;
import org.example.lvzhiaiserver.mapper.DeptMapper;
import org.example.lvzhiaiserver.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Override
public List<Dept> list() {
return deptMapper.list();
}
@Override
public Dept getById(Integer id) {
return deptMapper.getById(id);
}
// 新增:实现接口的getByName
@Override
public Dept getByName(String name) {
return deptMapper.selectByName(name);
}
@Override
public void add(Dept dept) {
// 查重逻辑
Dept existDept = getByName(dept.getName());
if (existDept != null) {
throw new RuntimeException("部门名称已存在,不能重复添加");
}
// 删除setCreateTime,数据库无此字段
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
@Override
public void update(Dept dept) {
dept.setUpdateTime(LocalDateTime.now());
deptMapper.update(dept);
}
@Override
public void delete(Integer id) {
deptMapper.deleteById(id);
}
}
四、需要全新创建的文件(1 个)
新建目录:org.example.lvzhiaiserver.config
新建文件:GlobalExceptionHandler.java(全局异常处理器,统一异常返回 JSON)
package org.example.lvzhiaiserver.config;
import org.example.lvzhiaiserver.pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
// 捕获RuntimeException,返回统一错误Result
@ExceptionHandler(RuntimeException.class)
public Result handleRuntimeException(RuntimeException e){
return Result.error(e.getMessage());
}
}
五、最终测试方案
接口:POST /depts
请求体:{"name":"教研部"}(数据库已存在该部门)预期返回结果:
{"code":0,"msg":"部门名称已存在,不能重复添加","data":null}
后端只返回 JSON,前端拿到 code=0,调用弹窗代码弹出提示框。
六、文件改动汇总存档
表格
| 操作 | 文件名称 | 修改内容 |
|---|---|---|
| 修改 | DeptMapper.java | 新增 selectByName 接口方法 |
| 修改 | DeptMapper.xml | 新增 selectByName 查询 SQL |
| 修改 | DeptService.java | 新增 getByName 抽象方法 |
| 修改 | DeptServiceImpl.java | 实现 getByName、add 增加查重抛异常 |
| 新建 | config/GlobalExceptionHandler.java | 全局异常捕获,统一返回错误 JSON |
| 数据库 | dept 表 | 添加 name 唯一索引 uk_dept_name |
更多推荐







所有评论(0)