前言:
掌控是大型项目的首要条件,按照自己顶下的设计模式及编程规范编程是AI编程的基本要求。
❯ 以add user account为例子,描述程序的访问序列,比如哪个网页访问什么类,按顺序描述
● Let me explore the codebase to find the user account related components and trace the access sequence.
● Explore(Find user account components)
⎿ Done (51 tool uses · 75.6k tokens · 1m 41s)
(ctrl+o to expand)
● "Add User Account" 程序访问序列
整个流程严格遵循 Jakarta EE 11 三层架构:展示层 (JSF) → 业务逻辑层 (EJB) → 数据持久层 (JPA Entity)。
---
第一阶段:页面入口与导航
步骤 1 — 用户访问用户列表页面
┌──────┬────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────┐
│ 顺序 │ 文件 │ 说明 │
├──────┼────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ 1.1 │ src/main/webapp/app/security-console/users-list.xhtml │ 浏览器请求用户列表页面,显示所有用户表格 │
├──────┼────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ 1.2 │ src/main/webapp/app/security-console/template.xhtml │ 页面模板,提供汉堡菜单、上下文导航行、侧边栏 │
├──────┼────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────┤
│ 1.3 │ openlabx.org.cn.security.web.UserListBean (@Named @ViewScoped) │ 页面加载时调用 search() 方法,通过 UserFacade.searchUsers() 获取用户列表数据 │
└──────┴────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────┘
步骤 2 — 用户点击 "Add User Account" 按钮
┌──────┬──────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 顺序 │ 文件 │ 方法/操作 │
├──────┼──────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 2.1 │ users-list.xhtml │ │
├──────┼──────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 2.2 │ UserListBean.java │ navigateToCreateUser() 返回导航字符串 "/app/security-console/user-edit?mode=create&faces-redirect=true" │
├──────┼──────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 2.3 │ src/main/webapp/app/security-console/user-edit.xhtml │ 浏览器重定向到用户编辑页面 │
└──────┴──────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────┘
---
第二阶段:表单初始化
步骤 3 — 页面加载时初始化创建模式
┌──────┬──────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────┐
│ 顺序 │ 文件 │ 方法/操作 │
├──────┼──────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ 3.1 │ user-edit.xhtml │ 接收 mode=create 参数 │
├──────┼──────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ 3.2 │ user-edit.xhtml │ 触发加载 │
├──────┼──────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ 3.3 │ openlabx.org.cn.security.web.UserEditBean │ loadUser() 检测到 mode=create,实例化一个空的 User 对象,加载 UserCategory 列表(供下拉选择) │
├──────┼──────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ 3.4 │ openlabx.org.cn.security.ejb.UserCategoryFacade (@Stateless) │ 提供用户类别列表数据 │
└──────┴──────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────┘
---
第三阶段:用户提交表单(核心保存流程)
步骤 4 — 用户填写表单并点击 "Save"
┌──────┬────────┬─────────────────────────────────────────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 顺序 │ 层级 │ 文件 │ 方法/操作 │
├──────┼────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 4.1 │ 展示层 │ user-edit.xhtml │ │
├──────┼────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 4.2 │ 展示层 │ UserEditBean.java │ save() — 校验密码(最少8字符、两次输入一致),设置用户类别,调用 userFacade.createUser(user, password, │
│ │ │ │ currentUser) │
├──────┼────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 4.3 │ 业务层 │ openlabx.org.cn.security.ejb.UserFacade (@Stateless) │ createUser(User user, String password, String createdBy) — 外观模式入口,委托给 UserService │
├──────┼────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 4.4 │ 业务层 │ openlabx.org.cn.security.ejb.UserService (@Stateless) │ createUser() — 核心业务逻辑:校验输入参数 → 调用 PasswordHasher.hash(password) → 设置 │
│ │ │ │ pwdChangeRequired=true → 根据 UserCategory 计算密码过期时间 → em.persist(user) │
├──────┼────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 4.5 │ 业务层 │ openlabx.org.cn.security.ejb.PasswordHasher │ hash(password) — PBKDF2WithHmacSHA256 算法,迭代 600,000 次,16 字节盐值,生成格式 │
│ │ │ (@ApplicationScoped) │ ALGORITHM:ITERATIONS:BASE64_SALT:BASE64_HASH │
├──────┼────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 4.6 │ 持久层 │ openlabx.org.cn.security.entity.User (@Entity │ JPA @PrePersist 生命周期回调自动设置 createdAt、updatedAt、pwdLastChangedAt │
│ │ │ @Table(name="sec_users")) │ │
├──────┼────────┼─────────────────────────────────────────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ 4.7 │ 数据库 │ PostgreSQL sec_users 表 │ JPA 执行 INSERT INTO sec_users(...) │
└──────┴────────┴─────────────────────────────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────┘
---
第四阶段:角色分配(可选)
步骤 5 — 用户保存后,可点击 "Add Role" 分配角色
┌──────┬────────┬───────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────┐
│ 顺序 │ 层级 │ 文件 │ 方法/操作 │
├──────┼────────┼───────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
│ 5.1 │ 展示层 │ user-edit.xhtml │ 打开 "Add Role" 对话框,搜索角色 │
├──────┼────────┼───────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
│ 5.2 │ 展示层 │ UserEditBean.java │ searchAvailableRoles() → roleFacade.searchRoles(...) │
├──────┼────────┼───────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
│ 5.3 │ 展示层 │ UserEditBean.java │ addSelectedRoles() — 遍历选中的角色,调用 userFacade.assignRoleToUser(userId, roleId, │
│ │ │ │ createdBy) │
├──────┼────────┼───────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
│ 5.4 │ 业务层 │ UserFacade.java │ assignRoleToUser() — 检查是否已存在相同分配(防重复),创建 UserRole 对象 │
├──────┼────────┼───────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────┤
│ 5.5 │ 持久层 │ openlabx.org.cn.security.entity.UserRole (@Entity │ JPA em.persist(userRole) → INSERT INTO sec_user_roles │
│ │ │ @Table(name="sec_user_roles")) │ │
└──────┴────────┴───────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────┘
---
第五阶段:权限刷新
步骤 6 — 创建用户后刷新授权缓存
┌──────┬──────────────────────────────────────────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────┐
│ 顺序 │ 文件 │ 操作 │
├──────┼──────────────────────────────────────────────────────────────────────┼──────────────────────────────────────────────────────────────────────────────────┤
│ 6.1 │ openlabx.org.cn.security.web.AuthorizationCacheBean (@SessionScoped) │ invalidate() — 清除当前用户的权限缓存,下次访问时重新从 AuthorizationEngine 加载 │
└──────┴──────────────────────────────────────────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────┘
---
完整调用链总结
浏览器 → users-list.xhtml
→ UserListBean.navigateToCreateUser() [展示层 - CDI Bean]
→ 浏览器重定向 → user-edit.xhtml
→ UserEditBean.loadUser() [展示层 - CDI Bean]
→ UserCategoryFacade (加载类别列表) [业务层 - EJB]
→ UserEditBean.save() [展示层 - CDI Bean]
→ UserFacade.createUser() [业务层 - EJB Facade]
→ UserService.createUser() [业务层 - EJB Service]
→ PasswordHasher.hash() [业务层 - 密码哈希]
→ em.persist(User) [持久层 - JPA Entity]
→ INSERT INTO sec_users [数据库 - PostgreSQL]
→ UserFacade.assignRoleToUser() [业务层 - EJB Facade]
→ em.persist(UserRole) [持久层 - JPA Entity]
→ INSERT INTO sec_user_roles [数据库 - PostgreSQL]
关键文件数量:3 个 XHTML 页面 → 2 个 CDI Bean → 3 个 EJB → 3 个 JPA Entity → 2 张数据库表。
✻ Cogitated for 2m 6s