AI从零搭建用户权限系统的完整过程记录
基于Vue、Java17、SpringBoot3和MySQL,利用AI从空白仓库搭建RBAC权限系统,涵盖用户登录、用户 角色 权限管理及审计日志。通过CLAUDE md制定技术栈和规范,分阶段生成数据模型、AOP权限拦截器、Service层和审计日志,需多次调整以对齐技术栈。
从零搭建用户权限系统:AI全流程开发实录
从一个刚完成初始化的空白代码仓库起步,借助AI完整构建一套RBAC权限管理系统。前端采用Vue,后端基于Java 17与Spring Boot 3,数据库选用MySQL,认证机制使用SaToken。功能需求涵盖:用户登录、用户管理、角色管理、权限分配、操作审计日志。

放在以往,这套任务需要手动编写好几天:设计数据库表结构、编写实体类、构建Service层与Controller层、撰写单元测试,随后进行代码审查和缺陷修复。这次决定换一种方式——让Claude从需求分析到代码生成完整走一遍,同时验证此前文章中总结的规则管理方法,在实际项目中究竟是否好用。
第一阶段:明确需求目标
接手这类需求时,一上来就让AI直接写代码是大忌。凡是涉及3个以上文件需要改动的任务,先使用/plan指令让AI输出规划方案——这是此前反复踩坑后总结出的经验。曾经因为中途发现方向偏差,整个上下文作废只能重来,这种情况至少遇到过两次。
先让Claude读取项目现有代码结构,随后明确需求:
/plan 这是一个AI开发RBAC系统的示例,目前处于刚初始化仓库、尚未进行任何开发的状态。前端使用Vue,后端采用Java 17,数据库使用MySQL。需要实现用户登录、用户管理与权限管理功能。RBAC权限系统的具体要求:
- 支持用户多角色分配
- 实现基于角色的细粒度权限控制
- 权限校验使用AOP拦截,不在每个方法中手写
- 角色和权限变更必须记录审计日志
- 数据库使用MySQL
AI给出的方案对比了三种实现路径:
- 基于角色的RBAC——用户关联角色,角色关联权限点
- 基于策略的模式——每个权限定义一个策略类
- 基于表达式语言的SpEL——使用Spring Expression Language编写权限表达式
最终选择了第一种。RBAC属于标准方案,SaToken原生支持角色与权限判断,团队接手也更容易。后两种虽然更灵活,但学习和维护成本显著增加。
方案确认后,Claude将其拆解为按依赖关系排序的任务清单:
1. 设计数据模型(User-Role-Permission 五张关系表)
2. 编写实体类和Mapper(MyBatis-Plus)
3. 编写Service层(权限校验、角色分配)
4. 编写AOP拦截器(基于注解的权限校验)
5. 编写Controller(用户/角色/权限CRUD)
6. 实现审计日志
7. 编写全局异常处理
这份任务清单,就是后续整个开发过程的“施工蓝图”。
第二阶段:制定规则
这次没有采用三层规则分层,仅使用一个CLAUDE.md文件。原因很简单——这个权限模块属于一次性开发任务,并非需要长期维护的独立子系统。专门为其建立L3文件,后期维护成本会超过收益。CLAUDE.md中的核心规则:
## 技术栈
- Java 17, Spring Boot 3.x
- MyBatis-Plus 3.5.x, SaToken 1.38.x
- Hutool 5.8.x, Lombok 1.18.x
## 代码规范
- 使用 @RequirePermission 注解 + AOP 进行权限校验
- 禁止在 Controller 方法体内编写权限判断逻辑
- 使用 BusinessException 抛出业务异常
- 统一使用 ApiResponse 包装返回结果
## 查询规范
- 使用 MyBatis-Plus LambdaQueryWrapper
- 禁止手写 SQL 字符串拼接
核心原则只有一条:如果你不把规则说清楚,AI就会按照它的训练数据来生成代码。而训练数据来源于全网代码的平均水平,并非你团队的规范。
第三阶段:正式编写代码
数据模型设计
先运行/init让Claude确认项目结构,然后从任务1开始。RBAC的标准数据模型包含5张表:
┌─────────┐┌──────────────┐ ┌─────────┐
│t_user │ ────▶│ t_user_role│◀────│ t_role│
│(用户)││(用户-角色)│ │(角色)│
└─────────┘└──────────────┘ └────┬────┘
│
┌─────────────────┐
│t_role_permission│
│ (角色-权限)│
└─────────────────┘
│
┌──────┴─────┐
│t_permission│
│ (权限)│
└────────────┘
Claude生成的实体类采用MyBatis-Plus注解,而非JPA——这也得益于在CLAUDE.md中提前明确了技术栈:
@Data
@TableName("user_role")
public class UserRole {
@TableId(type = IdType.AUTO)
private Long id;
@TableField("user_id")
private Long userId;
@TableField("role_id")
private Long roleId;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
}
使用MyBatis-Plus的好处在于无需操心EAGER/LAZY等JPA加载策略——每次查询都是主动调用,N+1问题通过手动优化查询逻辑来避免。
AOP权限拦截器
这一部分是权限系统的核心。@RequirePermission注解的设计十分简洁:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequirePermission {
/** * 权限标识,格式为 "resource:action" */
String value();
}
切面实现:
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class PermissionAspect {
private final PermissionService permissionService;
@Around("@annotation(requirePermission)")
public Object checkPermission(ProceedingJoinPoint joinPoint,
RequirePermission requirePermission) throws Throwable {
if (!StpUtil.isLogin()) {
throw new PermissionDeniedException("未登录或登录已过期");
}
String permissionCode = requirePermission.value();
long userId = StpUtil.getLoginIdAsLong();
boolean hasPermission = permissionService.hasPermission(userId, permissionCode);
if (!hasPermission) {
log.warn("用户 {} 尝试访问权限 {} 被拒绝", userId, permissionCode);
throw new PermissionDeniedException("没有权限执行此操作");
}
return joinPoint.proceed();
}
}
使用方法就是在Controller方法上添加注解:
@RequirePermission("role:create")
@PostMapping
public ApiResponse createRole(@Valid @RequestBody CreateRoleRequest request) {
Role role = roleService.createRole(request);
auditLogService.logAudit(...);
return ApiResponse.success(role);
}
这一部分Claude生成的质量非常高——AOP结合自定义注解是Spring生态中的标准模式,训练数据中的样本充足。而且使用了SaToken的StpUtil.isLogin()进行登录检查,说明AI确实读取了项目中的依赖配置。
权限校验的Service层
这里是第一个值得深入讨论的地方。AI生成的hasPermission方法:
@Override
public boolean hasPermission(Long userId, String permissionCode) {
// 获取用户所有角色
List roleCodes = userRoleService.getUserRoleCodes(userId);
if (roleCodes.isEmpty()) {
return false;
}
// 获取用户所有角色的权限
List userPermissions = getUserPermissionCodes(userId);
return userPermissions.contains(permissionCode);
}
接着是getUserPermissionCodes的具体实现:
@Override
public List getUserPermissionCodes(Long userId) {
List roles = userRoleService.getUserRoles(userId);
if (CollUtil.isEmpty(roles)) {
return List.of();
}
Set permissions = new HashSet<>();
for (Role role : roles) {
if (role.getStatus() != 1) continue;
List permissionIds = rolePermissionService.getPermissionIdsByRoleId(role.getId());
if (!permissionIds.isEmpty()) {
List perms = listByIds(permissionIds);
perms.stream().filter(p -> p.getStatus() == 1)
.map(Permission::getCode)
.forEach(permissions::add);
}
}
return List.copyOf(permissions);
}
这段代码实际上存在N+1查询问题。对每个角色都会调用getPermissionIdsByRoleId,再对每个角色调用listByIds批量查询权限。如果用户有3个角色,就需要执行6次数据库查询(3次查询权限ID + 3次批量查询权限详情)。不过这个项目属于个人演示性质,数据量较小,暂时无需优化。如果放到真实生产环境,应当改为一次JOIN查询或使用IN子句批量查询——这也印证了此前文章中提到的观点:AI不会主动考虑数据量增长后的性能问题。
审计日志
关于审计日志,AI最初的方案是使用AOP切面自动记录,后来改为在Controller中手动调用auditLogService.logAudit()。原因在于:AOP切面虽然看起来省事,但很难记录变更前后的具体数值。例如“将用户从'普通用户'改为'管理员'”这类信息,AOP只能获取方法名和参数,无法拿到变更前的数据。手动调用虽然多写几行代码,但记录的精准度更高。审计日志使用的AuditLog实体:
@Data
@TableName("audit_log")
public class AuditLog {
@TableId(type = IdType.AUTO)
private Long id;
@TableField("operator_id")
private Long operatorId;
@TableField("operator_name")
private String operatorName;
@TableField("action")
private String action;
@TableField("target_type")
private String targetType;
@TableField("target_id")
private Long targetId;
@TableField("detail")
private String detail;
@TableField("ip_address")
private String ipAddress;
@TableField(value = "create_time", fill = FieldFill.INSERT)
private LocalDateTime createTime;
}
Controller中的调用方式:
auditLogService.logAudit(
StpUtil.getLoginIdAsLong(),
StpUtil.getLoginIdAsString(),
AuditAction.CREATE_ROLE.name(),
"role",
role.getId(),
"创建角色: " + role.getName(),
null
);
AI开发很少一次通过
这套权限模块的代码,从写完到能正常运行,中间经过了多个回合的调整。这其实很正常——使用AI编写代码时,一次需求描述清楚、AI一次写完、一次审查通过的情况非常罕见。原因也很简单:AI不会主动考虑边界场景。你让它“做一套RBAC权限系统”,它会给出一个标准RBAC实现,但标准实现并不一定适合你的具体场景。
本次主要的反复集中在以下几个问题上:
技术栈对齐
最初AI生成的代码混用了JPA和MyBatis-Plus两种ORM——部分实体使用了@Entity,部分使用了@TableName。原因是在最初的CLAUDE.md中没有明确说明技术栈,AI按照训练数据的默认倾向选择了JPA(Spring Boot教程中JPA出现频率较高)。后来在CLAUDE.md中补充了“使用MyBatis-Plus 3.5.x,禁止使用JPA”的规则,之后生成的代码就统一了。
审计日志的记录方式
如前所述,AI最初使用AOP切面自动记录审计日志。看起来省事,但实际效果是记录的信息过于粗糙——只能获取方法名,无法拿到变更前后的具体值。后来改为在Controller中手动调用auditLogService.logAudit(),虽然多写几行代码,但每条审计日志的detail字段都能清晰描述具体操作内容。
异常处理统一化
AI生成的Controller中,有些地方抛出RuntimeException,有些地方返回null。后来在CLAUDE.md中增加了“使用BusinessException抛出业务异常”的规则,同时编写了GlobalExceptionHandler进行统一处理:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public ApiResponse handleBusinessException(BusinessException e) {
return ApiResponse.error(e.getCode(), e.getMessage());
}
@ExceptionHandler(PermissionDeniedException.class)
public ApiResponse handlePermissionDenied(PermissionDeniedException e) {
return ApiResponse.error(403, e.getMessage());
}
}
需求越精细,返工越少
回顾这三个问题,它们都不是技术难题,而是“初始需求描述不够细致”所导致的。因此现在养成了一个习惯:让AI编写代码之前,先花10分钟把需求细化到“不需要追问”的程度。不是写冗长的文档,而是在对话中把关键点表达清楚:
/implement 按照任务清单实现权限模块,注意以下要点:
1. 使用 MyBatis-Plus,禁止使用 JPA
2. 权限校验采用 @RequirePermission 注解 + AOP 拦截
3. 统一使用 BusinessException 抛出业务异常
4. 审计日志在 Controller 中手动调用 logAudit 记录
5. 所有返回结果使用 ApiResponse 包装
这几条看似都是常识(“使用MyBatis-Plus”、“抛出BusinessException”谁都知道),但你不说AI就不会主动执行。AI并非不了解MyBatis-Plus,而是不知道你的项目已经确定了技术栈,需要它主动遵守。需求描述得越精细,返工次数就越少,上下文token的浪费也越少。这个道理与带新人其实一致——交代任务时不说清楚,新人做出来的结果肯定不是你要的,随后反复沟通,双方都疲惫。
完成后的几点体会
这次全流程走下来,AI真正发挥价值的环节包括:
表现优异的方面:
- 数据模型设计——标准RBAC模型,AI生成的表结构和关联关系没有出现错误
- 实体类和Mapper——MyBatis-Plus代码是AI最擅长的领域,生成质量与手写相当
- AOP拦截器——标准模式,训练数据充足,一次编写正确
- 全局异常处理——RestControllerAdvice模板代码,AI生成得非常完整
需要人工介入的部分:
- 方案选择(RBAC vs 策略 vs SpEL)——这属于架构判断,AI只能列出选项
- 技术栈对齐——AI默认混用JPA和MyBatis,需要人工提前明确
- 审计日志的记录方式——AOP自动记录还是手动调用,需要根据业务场景判断
- 异常类型的统一化——AI会混用RuntimeException和自定义异常,需要人工规范
结论是:AI能够把标准工作完成得又快又好,但非标准的坑需要你自己去填补。踩过坑之后把经验写回规则文件,下次AI就不会再犯同样的错误。这个闭环一旦运转顺畅,开发效率确实比以往提升了不少。
本文对应的代码仓库已在Gitee开源:gitee.com/tangyuewei/…,包含RBAC权限系统的完整实现、CLAUDE.md规则文件以及开发过程中的提示词记录,可以直接拉取运行。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
跨境物流AI Agent感知决策全链路自动化技术拆解
2026年,跨境物流领域正迎来一场根本性变革——从“被动记录”全面迈向“主动执行”,AI智能体正在重塑整个行业格局。 你可能已经深有体会:每天一到岗,光是后台处理货件创建、物流追踪等重复操作,就要耗费数小时之久。行业调研数据显示,超过60%的运营人员每天至少花费2小时在这些机械性劳动上,而手动操作引
天学会AI应用开发第十二课:从PDF、Word和网页构建RAG
上一篇文章介绍了如何从TXT文件中读取文本内容,但在日常办公场景中,纯文本文件的使用频率并不高。更常见的需求是处理PDF、Word等文档格式,同时还需要从网页中提取知识信息。 因此,本篇文章将重点讲解如何从PDF、Word以及网页中提取内容,并将其应用于RAG(检索增强生成)系统。 一、从PDF文件
Hy3+WorkBuddy组合国产顶级Agent附完整提示词
五个 Case 跑完,总结一下整体体验。工具使用能力:能不能自己开网页、找信息、标出处。规划能力:能不能把多约束需求拆成可执行步骤。长程执行能力:跨多步任务时会不会丢状态。复杂推理能力:能不能先推导、再写代码、再执行验证。WorkBuddy+Hy3 的表现完全符合预期。趁着 WorkBuddy 里的
AI Agent是什么?一文理解大语言模型、记忆、技能、工具、MCP、工作流与上下文
智能体并非单一模型,而是由大语言模型、记忆、工具、工作流等模块协同构成的自主系统。它通过理解目标、检索记忆、调用工具、构建上下文、推理决策,并基于反馈闭环持续迭代,最终自主完成复杂任务。
DeepSeek决定自研芯片打造人工智能全新算力芯脏
被“逼”出来的第三条路。 一直以模型技术见长的DeepSeek,这次在算力供应链上迈出了让所有人侧目的一步。 2026年7月7日,路透社援引三位知情人士消息,DeepSeek正在悄然开发自有AI芯片。值得玩味的是,这颗芯片的定位非常精准——专攻推理,不涉足训练。消息人士称,项目大约启动于一年前,目前
- 热门数据榜
相关攻略
2026-07-11 16:50
2026-07-11 16:50
2026-07-11 16:50
2026-07-11 16:50
2026-07-11 16:28
2026-07-11 16:28
2026-07-11 14:38
2026-07-11 14:38
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

