外观
快速开始
当前实现限制
WorkspaceUserServiceImpl.queryPoByUserIdAndWorkspaceId 与 queryPoByWorkspaceIdForOwner 实际调用必取接口,无结果会抛异常。因此首次加入成员会在检查阶段失败,创建空间或默认初始化可能已先写入空间记录。本文的创建、邀请、加入步骤说明接口顺序;需先修正并验证该调用链才能跑通新成员流程。isAdmin、isOwner、contains 的缺失成员情况也可能抛异常,不能统一当作 false。详见重点文件与方法。
本例完成“用户 A 创建空间 → 生成普通成员邀请码 → 用户 B 加入 → 查看成员”的流程。
前提是已有可运行的 EFC Web 应用,已经接好系统用户、登录认证、MyBatis-Plus 数据访问和框架基础 Bean。当前源码基线为 Java 25、Spring Boot 4.1.0,模块版本为 4.1.0-SNAPSHOT,需在项目 Maven 仓库或本地可用。准备两个已存在且可以登录的用户 A、B。
本例是在已有应用上增加工作空间能力。工作空间会传递依赖系统用户、系统账号和登录核心;这些模块所需的用户数据表、认证及运行环境应已就绪。
1. 添加依赖
在应用 POM 中导入 Business BOM,添加 App Controller。已有 BOM 不重复导入。
xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.own</groupId>
<artifactId>springboot-business-dependencies</artifactId>
<version>4.1.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.own.business</groupId>
<artifactId>springboot-business-workspace-controller-app</artifactId>
</dependency>
</dependencies>business 中的自动配置入口 UseBusinessWorkspace 会扫描工作空间服务、Mapper 和已引入的 Controller,无需另写一套接口,也没有 own.workspace.enabled 开关。
空间初始化、加入成员和转让所有权需要 StoreLockManager。如果应用尚未提供 Store 实现,单实例演示可在上述 dependencies 中追加:
xml
<dependency>
<groupId>com.own.component</groupId>
<artifactId>springboot-component-store-starter-local</artifactId>
</dependency>已有 Redis Store 的应用沿用原配置。多实例部署使用共享 Redis Store,不能依靠本地锁实现跨实例防重;参见成员与角色。
2. 准备数据表和配置
在应用已有的 MySQL 数据库中执行 工作空间首次建表 SQL,创建以下三张表及查询索引:
| 表 | 数据 |
|---|---|
own_workspace | 空间资料 |
own_workspace_user | 用户与空间的成员关系 |
own_workspace_user_invite | 邀请码与有效期 |
下载脚本保留当前业务源码的表结构,移除了原脚本的 DROP TABLE。它只用于尚未创建这三张表的数据库,不是已有表的增量迁移,也不会随应用启动自动执行。
沿用现有数据源;未配置时,在应用 application.yml 中按环境填写:
yaml
spring:
datasource:
url: ${WORKSPACE_JDBC_URL}
username: ${WORKSPACE_DB_USERNAME}
password: ${WORKSPACE_DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
main:
allow-circular-references: trueWORKSPACE_JDBC_URL 使用应用的 MySQL JDBC 地址,应用需已有 MySQL 驱动。当前 WorkspaceServiceImpl 与 WorkspaceUserServiceImpl 相互注入;示例允许循环引用以适配当前实现,禁止循环引用的应用应先调整装配关系。
确认已有应用注册了 MapperUtil、SystemUserInfoService、StoreLockManager,并能通过 SessionUserUtil 取得当前登录用户。仅传入请求体中的 userId 不会建立登录身份。
3. 用户 A 创建空间
启动应用,使用已经登录为 A 的 API 客户端访问下列接口。请求地址加上应用域名、端口和实际 context path,认证请求头或 Cookie 沿用应用现有登录协议。
请求:POST /api/app/workspace/,Content-Type: application/json。
json
{
"name": "协作演示空间",
"cover": ""
}使用一个尚未存在的名称。成功响应的 data 是 WorkspaceVo;记录 data.id 作为后续 workspaceId。该流程创建普通空间(isDefault=0),并将 A 加为 OWNER。
随后调用 POST /api/app/workspace/all,请求体为 {}。data 列表中应包含刚创建的空间;接口会使用 A 的会话身份过滤,不需要提交 userId。
4. 用户 A 生成邀请
请求:POST /api/app/workspace/user/invite/。将示例 10001 换成上一步返回的空间 ID。
json
{
"workspaceId": "10001",
"permission": "MEMBER"
}成功后从 data.inviteCode 取出邀请码。不填写 expiredTime 时,由服务端设置为当前时间加一天。此接口返回邀请码和邀请信息,前端自行生成分享链接。
角色在 JSON 和路径中使用枚举名,如 MEMBER、ADMIN,不要使用数据库中的 3、2 代替。
5. 用户 B 加入并核对结果
切换到已登录为 B 的 API 客户端,访问 POST /api/app/workspace/user/invite/join/{inviteCode},替换为实际邀请码,无需请求体。
成功后调用 POST /api/app/workspace/all,请求体为 {},B 应能看到该空间。A 再访问 POST /api/app/workspace/user/page/workspace/id/{workspaceId}:
json
{
"page": 1,
"rows": 10
}响应 data.list 中应有 A 的 OWNER 关系和 B 的 MEMBER 关系;成员 id 是关系记录 ID,userId 才是系统用户 ID。
上述接口同步操作数据库。成功码为 00000,加入操作没有业务数据返回;不要把 data=true 当成成功的必要条件。通用响应及 ID 约定见空间管理。
下一步
接入现有业务数据时,还需要由应用检查当前用户的空间成员关系,并用空间 ID 限定数据访问范围。