当前位置: 首页 > news >正文

UserController类讲解

用户管理控制器,实现了用户CRUD操作的RESTful API:

1. 类结构与核心注解

1.1 控制器声明

@RestController
@RequestMapping("/api/users")
public class UserController

@RestController 深度解析:

  • 组合注解@Controller + @ResponseBody
  • 自动序列化:返回的对象自动转换为JSON
  • Spring MVC集成:无需手动配置JSON转换器
  • RESTful设计:专为API接口设计

@RequestMapping(“/api/users”) 路径设计:

  • 统一前缀:所有用户相关接口以/api/users开头
  • 版本控制:便于后续添加/api/v2/users
  • 语义清晰:一看就知道是用户管理接口

1.2 依赖注入与日志

private static final Logger log = LoggerFactory.getLogger(UserController.class);@Autowired
private UserService userService;

日志配置:

  • SLF4J框架:统一的日志接口
  • 类级别Logger:每个类有独立的日志记录器
  • 静态final:性能优化,避免重复创建

依赖注入优势:

  • 松耦合:Controller不直接依赖具体实现
  • 易测试:可以注入Mock对象进行单元测试
  • 配置驱动:Spring容器管理对象生命周期

2. RESTful API设计解析

2.1 HTTP方法与URL映射

功能HTTP方法URL说明
创建用户POST/api/users创建资源
删除用户DELETE/api/users/{id}删除指定资源
更新用户PUT/api/users/{id}完整更新资源
查询单个用户GET/api/users/{id}获取指定资源
查询所有用户GET/api/users获取资源列表
分页查询GET/api/users/page分页获取资源

RESTful设计优点:

  • 语义明确:HTTP方法表达操作意图
  • URL简洁:资源导向的路径设计
  • 标准化:遵循HTTP协议规范

3. 核心接口详细解析

3.1 创建用户接口

@PostMapping
public Result<User> createUser(@RequestBody User user) {try {User createdUser = userService.createUser(user);return Result.success(createdUser);} catch (Exception e) {log.error("创建用户失败", e);return Result.<User>error(e.getMessage());}
}

@PostMapping 解析:

  • HTTP POST:用于创建资源
  • 无路径参数:直接映射到类路径/api/users

@RequestBody 详解:

  • JSON反序列化:自动将请求体JSON转换为User对象
  • Content-Type要求:前端需设置application/json
  • 参数验证:可结合Bean Validation进行参数校验

前端请求示例:

// 前端请求
fetch('/api/users', {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify({username: 'newuser',password: '123456',email: 'newuser@example.com'})
})

3.2 删除用户接口

@DeleteMapping("/{id}")
public Result<Void> deleteUser(@PathVariable Long id) {try {boolean success = userService.deleteUser(id);if (success) {return Result.success();} else {return Result.<Void>error("用户不存在");}} catch (Exception e) {log.error("删除用户失败", e);return Result.<Void>error(e.getMessage());}
}

@PathVariable 详解:

  • 路径参数提取:从URL/api/users/123中提取id=123
  • 类型转换:自动将字符串转换为Long类型
  • 参数验证:Spring自动处理类型转换异常

业务逻辑处理:

  • 存在性检查:先检查用户是否存在
  • 状态反馈:根据删除结果返回不同信息
  • 幂等性:多次删除同一资源结果一致

3.3 更新用户接口

@PutMapping("/{id}")
public Result<User> updateUser(@PathVariable Long id, @RequestBody User user) {try {user.setId(id);  // 关键:设置ID确保更新正确的用户User updatedUser = userService.updateUser(user);return Result.success(updatedUser);} catch (Exception e) {log.error("更新用户失败", e);return Result.<User>error(e.getMessage());}
}

设计要点:

  • PUT语义:完整替换资源
  • ID一致性:URL中的ID覆盖请求体中的ID
  • 返回更新后数据:便于前端同步最新状态

前端使用示例:

// 更新用户信息
fetch('/api/users/123', {method: 'PUT',headers: { 'Content-Type': 'application/json' },body: JSON.stringify({username: 'updateduser',email: 'updated@example.com'})
})

3.4 查询接口设计

单用户查询
@GetMapping("/{id}")
public Result<User> getUserById(@PathVariable Long id)
用户名查询
@GetMapping("/username/{username}")
public Result<User> getUserByUsername(@PathVariable String username)
邮箱查询
@GetMapping("/email/{email}")
public Result<User> getUserByEmail(@PathVariable String email)

URL设计模式:

  • RESTful风格/资源/查询条件/值
  • 语义明确:URL即文档
  • 易于理解:符合直觉的路径结构

3.5 分页查询核心实现

@GetMapping("/page")
public Result<Map<String, Object>> getUsersByPage(@RequestParam(defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "10") Integer pageSize,@RequestParam(required = false) String username) {

@RequestParam 详解:

  • defaultValue:提供默认值,提升用户体验
  • required = false:可选参数,支持条件查询
  • 类型转换:自动将字符串转换为Integer

分页逻辑:

// 条件分支:搜索 vs 普通分页
if (username != null && !username.trim().isEmpty()) {users = userService.searchUsersByUsername(username, pageNum, pageSize);total = userService.getSearchTotalCount(username);
} else {users = userService.getUsersByPage(pageNum, pageSize);total = userService.getTotalCount();
}

返回数据结构:

Map<String, Object> data = new HashMap<>();
data.put("list", users);           // 当前页数据
data.put("total", total);          // 总记录数
data.put("pageNum", pageNum);      // 当前页码
data.put("pageSize", pageSize);    // 每页大小
data.put("pages", (total + pageSize - 1) / pageSize); // 总页数

前端调用示例:

// 普通分页
fetch('/api/users/page?pageNum=1&pageSize=10')// 搜索分页
fetch('/api/users/page?pageNum=1&pageSize=10&username=zhang')

3.6 密码修改接口

@PutMapping("/{id}/password")
public Result<Void> changePassword(@PathVariable Long id, @RequestBody Map<String, String> passwordData)

设计特点:

  • 专用接口:密码修改独立于普通更新
  • 安全考虑:需要提供原密码验证
  • Map参数:灵活接收键值对数据

请求体格式:

{"oldPassword": "123456","newPassword": "newpass123"
}

安全验证流程:

// 1. 参数验证
if (oldPassword == null || newPassword == null) {return Result.<Void>error("密码不能为空");
}// 2. 用户存在性检查
User user = userService.getUserById(id);
if (user == null) {return Result.<Void>error("用户不存在");
}// 3. 原密码验证
if (!oldPassword.equals(user.getPassword())) {return Result.<Void>error("原密码错误");
}

4. 异常处理机制

4.1 统一异常处理模式

try {// 业务逻辑
} catch (Exception e) {log.error("操作失败", e);return Result.<Type>error(e.getMessage());
}

异常处理优势:

  • 用户友好:返回可读的错误信息
  • 系统稳定:防止异常导致系统崩溃
  • 便于调试:记录详细的错误日志

4.2 改进

// 更细粒度的异常处理
try {// 业务逻辑
} catch (BusinessException e) {// 业务异常log.warn("业务异常: {}", e.getMessage());return Result.error(e.getMessage());
} catch (DataAccessException e) {// 数据访问异常log.error("数据库操作失败", e);return Result.error("系统繁忙,请稍后重试");
} catch (Exception e) {// 未知异常log.error("系统异常", e);return Result.error("系统错误");
}

5. 响应格式统一

5.1 成功响应

{"code": 200,"message": "操作成功","data": {"id": 1,"username": "admin","email": "admin@example.com"}
}

5.2 失败响应

{"code": 500,"message": "用户不存在","data": null
}

5.3 分页响应

{"code": 200,"message": "操作成功","data": {"list": [...],"total": 50,"pageNum": 1,"pageSize": 10,"pages": 5}
}
  1. RESTful标准:符合HTTP协议语义

  2. 统一响应格式:便于前端处理

  3. 完整CRUD操作:功能齐全

  4. 异常处理机制:提升系统稳定性

  5. 日志记录:便于问题排查

  6. 参数验证:基础的输入校验

  7. 参数验证增强:使用Bean Validation

  8. 权限控制:添加认证授权

  9. 接口文档:使用Swagger注解

  10. 批量操作:支持批量删除/更新

  11. 缓存策略:添加查询缓存

  12. 限流控制:防止接口被恶意调用

7.1 参数验证增强

@PostMapping
public Result<User> createUser(@RequestBody @Valid User user, BindingResult bindingResult) {if (bindingResult.hasErrors()) {return Result.error("参数验证失败:" + bindingResult.getFieldError().getDefaultMessage());}// 业务逻辑...
}

7.2 权限控制

@GetMapping("/{id}")
@PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
public Result<User> getUserById(@PathVariable Long id) {// 业务逻辑...
}

7.3 API文档

@GetMapping("/{id}")
@ApiOperation(value = "根据ID查询用户", notes = "返回用户详细信息")
@ApiParam(name = "id", value = "用户ID", required = true)
public Result<User> getUserById(@PathVariable Long id) {// 业务逻辑...
}
http://www.lryc.cn/news/619090.html

相关文章:

  • Milvus入门:开源向量数据库,解锁大模型时代的高效检索
  • iptables -L 显示无目标链规则,但是iptables-save显示仍存在链规则原因分析
  • LeetCode189~191、198~214题解
  • 力扣top100(day01-05)--矩阵
  • Golang 语言中 Context 的使用方式
  • 【Python 爬虫】Playwright 多浏览器支持(Chromium/Firefox/WebKit)
  • 云原生高级——nginx
  • Nginx 高级配置
  • 明远智睿T113-i核心板:工业设备制造的“破局者”
  • 10-docker基于dockerfile自动制作镜像
  • 机器学习——DBSCAN
  • imx6ull-驱动开发篇20——linux互斥体实验
  • [TryHackMe]Relevant(smb+windows令牌提权)
  • HarmonyOS元服务开发系列教程(三):实现音乐播放和封面旋转
  • 【问题解决】从Anaconda环境迁移到miniforge并在IDEA中完成环境配置
  • 【数据分享】2020-2022年我国乡镇的逐日最高气温数据(Shp/Excel格式)
  • C++动态代理技术详解:实现原理与应用场景
  • beacon-dongle系统(二)AP及Server建立
  • 双十一美妆数据分析:洞察消费趋势与行业秘密
  • 电商双 11 美妆数据分析学习报告
  • MyBatis持久层实现
  • 【前端Vue】log-viewer组件的使用技巧
  • Qwen-Image(阿里通义千问)技术浅析(一)
  • 物联网、大数据与云计算持续发展,楼宇自控系统应用日益广泛
  • [Robotics_py] 路径规划算法 | 启发式函数 | A*算法
  • Linux系统编程Day13 -- 程序地址空间
  • Seata深度剖析:微服务分布式事务解决方案
  • 微服务ETCD服务注册和发现
  • 力扣经典算法篇-50-单词规律(双哈希结构+正反向求解)
  • SQL 合并两个时间段的销售数据:FULL OUTER JOIN + COALESCE