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.pswp.cn/pingmian/92908.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92908.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【剑指offer】搜索算法

目录 &#x1f4c1; JZ53 数字在升序数组中出现的次数​编辑 &#x1f4c1; JZ4 二维数组中的查找​编辑 &#x1f4c1; JZ11 旋转数组的最小数字 &#x1f4c1; JZ38 字符串的排列​编辑 &#x1f4c1; JZ53 数字在升序数组中出现的次数 这就是一道简单的模板题&#xff0…

ETLCloud批流一体化体现在哪

ETLCloud批流一体化体现在哪 企业对数据处理的实时性、高效性和准确性的要求越来越高。批流一体化作为一种先进的数据处理理念&#xff0c;逐渐被企业所采用。 目前许多国产化ETL工具也装配了十分强大的批流一体化能力&#xff0c;ETLCoud就是一个很好的代表&#xff0c;它能够…

Mybatis学习之缓存(九)

这里写目录标题一、MyBatis的一级缓存1.1、工作原理1.2、一级缓存失效的四种情况1.3、不同的SqlSession对应不同的一级缓存1.4、同一个SqlSession但是查询条件不同1.5、同一个SqlSession两次查询期间执行了任何一次增删改操作1.6、同一个SqlSession两次查询期间手动清空了&…

windows10装Ubuntu22.04系统(双系统)

参考链接&#xff1a;Windows和Linux双系统的保姆级安装教程&#xff0c;新手小白跟着也能装_windows安装linux双系统-CSDN博客 1 前期准备 1.下载Ubuntu22.04.5 的iso镜像文件&#xff1a;Download Ubuntu Desktop | Ubuntu 2.准备一个U盘&#xff08;空&#xff0c;已有文…

Pandas数据处理与分析实战:Pandas数据清洗与处理入门

数据清洗&#xff1a;Pandas数据处理入门 学习目标 本课程将引导学员了解数据清洗的基本概念&#xff0c;掌握使用Pandas库处理数据集中的缺失值、重复数据和异常值的方法&#xff0c;确保数据的质量&#xff0c;为后续的数据分析和机器学习任务打下坚实的基础。 相关知识点 Pa…

Python爬虫实战:研究ScrapyRT框架,构建图书商城数据采集系统

1. 引言 1.1 研究背景 在当今数字化时代,互联网已成为全球最大的信息库,蕴含着海量的有价值数据,涵盖商业、教育、科研、医疗等各个领域。根据 IDC(国际数据公司)预测,到 2025 年全球数据圈将增长至 175ZB,其中网络数据占比超过 60%。这些数据不仅是企业制定商业策略、…

springboot接口请求参数校验

参数校验 参数校验可以防止无效或错误的数据进入系统。通过校验前端输入的参数&#xff0c;可以确保数据的完整性&#xff0c;避免因为缺少必要的信息而导致程序错误或异常。例如&#xff0c;对于密码字段&#xff0c;可以通过校验规则要求用户输入至少8个字符、包含字母和数字…

Docker部署 Neo4j 及集成 APOC 插件:安装与配置完整指南(docker-compose)

Docker部署 Neo4j 及集成 APOC 插件&#xff1a;分步骤指南 摘要 &#xff1a;本文将分两部分详细介绍相关内容。第一部分讲解如何使用 Docker Compose 部署 Neo4j 图数据库&#xff0c;提供完整配置文件及常见问题解决方案&#xff1b;第二部分在前者基础上&#xff0c;介绍 A…

TLSv1.2协议与TCP/UDP协议传输数据内容差异

一、Wireshark中常见的TLSv1.2在用Wireshark抓包时&#xff0c;除了看到课堂上教过的经典的TCP/UDP协议&#xff0c;还有一个协议经常出现——TLSv1.2。并且这个协议的Info解释是Application data&#xff0c;其实看到这个解释&#xff0c;我大概猜出来了TLSv1.2是用来给用户数…

51c自动驾驶~合集14

自己的原文哦~ https://blog.51cto.com/whaosoft/11707335 #Text2LiDAR 文本引导的无条件点云生成新SOTA 论文题目&#xff1a;《Text2LiDAR: Text-guided LiDAR Point Cloud Generation via Equirectangular Transformer》 论文地址&#xff1a;https://arxiv.o…

k8s基本概念

k8s 的基本概念 Kubernetes是一个可以移植、可扩展的开源平台&#xff0c;使用 声明式的配置 并依据配置信息自动地执行容器化应用程序的管理。在所有的容器编排工具中&#xff08;类似的还有 docker swarm / mesos等&#xff09;&#xff0c;Kubernetes的生态系统更大、增长更…

Easysearch 数据迁移之数据比对

上一篇我们通过 INFINI Gateway 进行了索引数据迁移&#xff0c;对索引迁移结果进行了初步且直观的校验--对比索引的文档数是否一致。今天介绍个实实在在的数据比对方法&#xff0c;通过网关对比索引文档的内容在两个集群是否一致。话不多说&#xff0c;就拿上次迁移的两个索引…

Codeforces Round 1042 (Div. 3)

ABCD 略E注意到每个操作最多执行一次&#xff0c;ifa[i]!b[i]&#xff0c;要么a[i]^a[i1]要么a[i]^b[i1]G设消除1~i的数的操作次数为f[i]&#xff0c;可以推出f[i]2*f[i-1]1&#xff0c;那么消除1~i的数的分数乘的数为g[i]&#xff0c;g[i]g[i-1]*g[i-1]*i s虽然很大&#xff0…

AJAX:让你的网页“静悄悄”变聪明,体验丝滑升级

大家好&#xff0c;今天想聊聊一个让网页“活”起来的小秘密——AJAX。你可能遇到过这种情况&#xff1a;点个按钮&#xff0c;页面就刷新&#xff0c;等得心急火燎。但用了AJAX的网站&#xff0c;比如购物车更新或搜索建议&#xff0c;数据嗖嗖就来了&#xff0c;整个页面却纹…

【iOS】Block基础知识和底层探索

文章目录前言Block的声明和创建问题引入Block的底层结构Block的执行流程Block的创建与存储Block的传递与调用Block的捕获机制捕获局部变量捕获全局变量小结Block的类型__block修饰符__block变量的包装结构体block的实例结构体block的执行逻辑Block循环引用造成的原因解决方法小…

1.Ansible 自动化介绍

1-Ansible 自动化介绍 Ansible 自动化介绍 手动执行任务和自动化执行任务 手动执行任务的麻烦事&#xff1a; 很容易漏掉某个步骤&#xff0c;或者不小心执行错步骤&#xff0c;而且很难验证每个步骤是不是真的按预期完成了。管理一大堆服务器时&#xff0c;很容易出现配置…

2025年云手机场景适配的行业观察

2025年的市场中&#xff0c;云手机品牌百花齐放&#xff0c;不同品牌在性能、功能和场景适配性上的差异日益显著。随着云计算技术的快速发展&#xff0c;云手机已从 尝鲜工具 演变为游戏、办公、企业运营等场景的刚需工具。现市面上也有着更多的云手机品牌&#xff0c;结合实测…

Date/Calendar/DateFormat/LocalDate

作用说明Date用于定义时间&#xff0c;提供date对象间的比较方法Calendar(日历类),提供对时间的运算方法DateFormat是接口&#xff0c;它的实现类SimpleDateFormat用来规范时间输出形式LocalDate&#xff0c;在JDK1.8之后引入&#xff0c;方便了对时间的运算方法介绍Date常用方…

在Python 3.8环境中安装Python 3.6兼容包的方法

在Python 3.8环境中安装Python 3.6兼容包的方法 用户的需求是&#xff1a;在Python 3.8环境中重新安装原本为Python 3.6设计的包。这通常涉及兼容性问题&#xff0c;因为Python 3.8可能引入了一些语法或API变更&#xff0c;导致旧包无法直接运行。以下是逐步解决方案&#xff…

三种DuckDB电子表格插件的union all查询性能对比

我选取了最稳定、兼容性最好的三种&#xff1a;官方excel对应函数read_xlsx()、官方spatial对应函数st_read()、rusty_sheet对应函数read_sheet。 1.建立两个包含前50万和后54万的xlsx文件&#xff0c;用于比较。利用官方excel的copy()to进行。 D copy (from v1 order by l_ord…