系列:后端路线 · 完整示例
把 Part 1(MySQL) ~ Part 4(部署) 全部焊死在一个项目里。这是一个复制即可跑的最小用户管理系统:建表 → 实体 → Mapper → Service → Controller → 接口自测。读完你已具备独立交付一个后端模块的能力。
1. 功能清单
| 接口 |
方法 |
路径 |
说明 |
| 注册用户 |
POST |
/api/users |
新增 |
| 用户列表 |
GET |
/api/users |
分页查询 |
| 用户详情 |
GET |
/api/users/{id} |
按主键查 |
| 更新用户 |
PUT |
/api/users/{id} |
改资料 |
| 删除用户 |
DELETE |
/api/users/{id} |
逻辑/物理删除 |
| 按名查询 |
GET |
/api/users?username=xxx |
条件查询 |
2. 建表 SQL(Part 1 的加强版)
1 2 3 4 5 6 7 8 9 10 11 12
| CREATE TABLE `user` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键', `username` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '用户名', `age` TINYINT NOT NULL DEFAULT 0 COMMENT '年龄', `balance` DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '余额', `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1正常 2禁用', `deleted` TINYINT NOT NULL DEFAULT 0 COMMENT '逻辑删除标记', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
|
3. 项目关键文件
3.1 依赖(pom.xml 核心)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.7</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> </dependencies>
|
3.2 配置(application.yml)
1 2 3 4 5 6 7 8 9 10 11 12 13
| server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/demo_db?useUnicode=true&characterEncoding=utf8mb4&serverTimezone=Asia/Shanghai username: root password: your_password mybatis-plus: global-config: db-config: logic-delete-field: deleted logic-not-delete-value: 0 logic-delete-value: 1
|
3.3 实体(Entity)
1 2 3 4 5 6 7 8 9 10 11 12 13
| @TableName("user") public class User { @TableId(type = IdType.AUTO) private Long id; private String username; private Integer age; private BigDecimal balance; private Integer status; private Integer deleted; private LocalDateTime createdAt; private LocalDateTime updatedAt; }
|
3.4 Mapper
1 2
| @Mapper public interface UserMapper extends BaseMapper<User> {}
|
3.5 Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Service public class UserService extends ServiceImpl<UserMapper, User> {
public User register(String username, int age) { if (this.lambdaQuery().eq(User::getUsername, username).count() > 0) { throw new RuntimeException("用户名已存在"); } User u = new User(); u.setUsername(username); u.setAge(age); u.setBalance(BigDecimal.ZERO); u.setStatus(1); this.save(u); return u; }
public IPage<User> pageList(long current, long size) { return this.page(new Page<>(current, size)); } }
|
3.6 Controller(统一响应)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| @RestController @RequestMapping("/api/users") public class UserController {
@Autowired private UserService userService;
@PostMapping public Result<User> register(@RequestBody User dto) { return Result.ok(userService.register(dto.getUsername(), dto.getAge())); }
@GetMapping public Result<IPage<User>> list(@RequestParam(defaultValue="1") long current, @RequestParam(defaultValue="10") long size) { return Result.ok(userService.pageList(current, size)); }
@GetMapping("/{id}") public Result<User> detail(@PathVariable Long id) { return Result.ok(userService.getById(id)); }
@PutMapping("/{id}") public Result<Boolean> update(@PathVariable Long id, @RequestBody User dto) { dto.setId(id); return Result.ok(userService.updateById(dto)); }
@DeleteMapping("/{id}") public Result<Boolean> delete(@PathVariable Long id) { return Result.ok(userService.removeById(id)); } }
|
3.7 统一响应包装(Result)
1 2 3 4 5 6 7 8 9 10 11
| public class Result<T> { private int code; private String msg; private T data; public static <T> Result<T> ok(T data) { Result<T> r = new Result<>(); r.code = 0; r.msg = "ok"; r.data = data; return r; } }
|
4. 端到端自测(curl)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| curl -X POST http://localhost:8080/api/users \ -H "Content-Type: application/json" \ -d '{"username":"zhang","age":20}'
curl "http://localhost:8080/api/users?current=1&size=10"
curl http://localhost:8080/api/users/1
curl -X PUT http://localhost:8080/api/users/1 \ -H "Content-Type: application/json" \ -d '{"age":21}'
curl -X DELETE http://localhost:8080/api/users/1
|
5. 这条链路的”全栈印证”
1 2 3
| curl ──HTTP──► Controller(路由/参数) ──► Service(业务/校验) ──► Mapper(CRUD) ──► MySQL(持久化, Part1)
|
- Part 1 的建表 → 这里
user 表
- Part 2 的分层 → Controller/Service/Mapper/Entity
- Part 3 的协议 → POST/GET/PUT/DELETE + JSON + 统一响应
- Part 4 的部署 →
mvn package 后 java -jar 即可对外服务
6. 可继续加强的方向(留给你练手)
- 加登录接口 + JWT(Part 3 认证)
- 加参数校验
@Valid + 全局异常处理器(统一错误码)
- 加分页/排序/条件查询封装
- 热点查询加 Redis 缓存(下个专题)
- 用 Docker 容器化部署
下一篇(收官):常见问题与调试技巧——把”跑不起来/调不通”的高频坑一次性列给你。