# JeePlus Cloud v9.0 — 项目架构百科 (Repo Wiki) > **项目名称**: jeeplus cloud > **组织**: org.jeeplus > **版本**: 9.0 > **架构模式**: Spring Cloud 微服务 + 多模块 Maven 工程 > **JDK**: 1.8 > **构建工具**: Maven --- ## 目录 1. [项目总览与拓扑结构](#1-项目总览与拓扑结构) 2. [Maven 模块全景图](#2-maven-模块全景图) 3. [基础设施与中间件](#3-基础设施与中间件) 4. [各微服务详细分析](#4-各微服务详细分析) - [4.1 jeeplus-gateway — API 网关](#41-jeeplus-gateway--api-网关) - [4.2 jeeplus-auth — 认证中心](#42-jeeplus-auth--认证中心) - [4.3 jeeplus-api — 接口定义层](#43-jeeplus-api--接口定义层) - [4.4 jeeplus-common — 公共组件层](#44-jeeplus-common--公共组件层) - [4.5 jeeplus-modules — 业务模块层](#45-jeeplus-modules--业务模块层) 5. [核心基类体系](#5-核心基类体系) 6. [常用工具类](#6-常用工具类) 7. [服务间调用与依赖关系](#7-服务间调用与依赖关系) 8. [接口规范](#8-接口规范) 9. [权限控制逻辑](#9-权限控制逻辑) 10. [关键常量与缓存设计](#10-关键常量与缓存设计) --- ## 1. 项目总览与拓扑结构 ``` ┌──────────────────────────────────────────────────────────┐ │ Nacos (8848) │ │ 服务注册/发现 + 配置中心 │ └──────────────────────┬───────────────────────────────────┘ │ ┌──────────────────────┴───────────────────────────────────┐ │ Sentinel (8858) │ │ 流量控制 + 熔断降级 │ └──────────────────────┬───────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────┐ │ jeeplus-gateway (:8088) │ │ Spring Cloud Gateway + WebFlux │ │ 路由转发 / JWT鉴权 / Swagger聚合 │ └──────────────────────┬───────────────────────────────────┘ │ ┌────────────┼────────────┬──────────────┐ ▼ ▼ ▼ ▼ ┌──────────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ jeeplus-auth │ │jeeplus- │ │jeeplus- │ │ jeeplus-modules │ │ (:9211) │ │ system │ │ flowable │ │ (assess, finance, │ │ 登录/认证 │ │ │ │ 工作流 │ │ human, ccpm …) │ └──────────────┘ └──────────┘ └──────────┘ └──────────────────┘ │ ▼ ┌──────────────────┐ │ Spring Boot │ │ Admin (:8989) │ │ 服务监控 │ └──────────────────┘ ``` **请求链路**: ``` 客户端请求 → Gateway(:8088) → JWTFilter 鉴权 → 路由转发 → 目标微服务 │ Redis (token 校验/刷新) ``` --- ## 2. Maven 模块全景图 ``` jeeplus (POM, parent) ├── jeeplus-gateway [网关服务 - Spring Boot] ├── jeeplus-auth [认证服务 - Spring Boot] ├── jeeplus-api (POM) [接口定义聚合] │ ├── jeeplus-system-api [系统API: IUserApi, ITenantApi, BaseDTO, TreeDTO] │ ├── jeeplus-public-modules-api [公共模块API: IWorkAttachmentApi] │ ├── jeeplus-finance-api [财务API: ICwProjectReportApi] │ └── jeeplus-file-api [文件API: IFileApi] ├── jeeplus-common (POM) [公共组件聚合] │ ├── jeeplus-common-core [核心: Entity/DTO基类, Redis, Excel, Query, 常量] │ ├── jeeplus-common-log [日志: AOP切面, @ApiLog注解] │ ├── jeeplus-common-mybatis-plus [ORM: MyBatis-Plus配置, 分页, 多租户] │ ├── jeeplus-common-security [安全: JWT, Spring Security, TokenProvider] │ └── jeeplus-common-swagger [文档: Knife4j/Swagger配置] └── jeeplus-modules (POM) [业务模块聚合] ├── jeeplus-system [★核心: 用户/角色/菜单/租户/部门/数据权限] ├── jeeplus-flowable [★工作流: Flowable引擎] ├── jeeplus-file [文件存储: MinIO/OSS] ├── jeeplus-finance [财务管理] ├── jeeplus-assess [评估考核] ├── jeeplus-human [人力资源管理] ├── jeeplus-ccpm [项目管理] ├── jeeplus-consult [培训咨询] ├── jeeplus-public-modules [公共功能: 收藏/合同/知识库/会议室/抽奖/物料等] ├── jeeplus-centrecareful [中审管理] ├── jeeplus-psi-management [PSI管理] ├── jeeplus-devtools [开发工具] ├── jeeplus-ureport [报表引擎] ├── jeeplus-wps [WPS集成] ├── jeeplus-xxl-job-admin [XXL-Job调度中心] ├── jeeplus-xxl-job-executor-sample [XXL-Job执行器] ├── jeeplus-admin-server [Spring Boot Admin监控] └── jeeplus-test [测试模块] ``` --- ## 3. 基础设施与中间件 | 组件 | 版本 | 用途 | |------|------|------| | Spring Boot | 2.4.4 | 微服务基础框架 | | Spring Cloud | 2020.0.2 (Ilford) | 微服务治理 | | Spring Cloud Alibaba | 2021.1 | 阿里云微服务生态 | | Nacos | 2.0.0 | 服务注册/发现 + 配置中心 | | Sentinel | 2.2.5.RELEASE | 流量防卫兵(限流/熔断) | | Spring Cloud Gateway | — | API 网关 | | MyBatis-Plus | 3.4.2 | ORM 增强框架 | | Druid | 1.2.8 | 数据库连接池 | | dynamic-datasource | 3.5.1 | 多数据源 | | Redis (Spring Data) | — | 分布式缓存(token/字典/菜单) | | MinIO | 8.0.3 | 对象存储(自建) | | Aliyun OSS | 3.13.1 | 对象存储(阿里云) | | Flowable | 6.7.2 | 工作流引擎 | | Liquibase | 4.3.5 | 数据库版本管理 | | XXL-Job | 2.3.1 | 分布式定时任务 | | Knife4j (Swagger) | 2.0.8 | API 文档 | | MapStruct | 1.4.2 | 对象映射转换 | | Lombok | 1.18.24 | 代码简化 | | Hutool | 5.7.13 | Java 工具包 | | Guava | 29.0-jre | 集合/缓存工具 | | EasyExcel | 3.1.1 | Excel 读写 | | Auth0 JWT | 3.4.0 | JWT Token 处理 | | Spring Boot Admin | 2.5.1 | 服务监控 | | UReport | 2.2.9 | 报表引擎 | | CAS Client | 3.5.1 | 单点登录客户端 | | Easypoi | 4.3.0 | POI 工具 | --- ## 4. 各微服务详细分析 ### 4.1 jeeplus-gateway — API 网关 **端口**: 8088 **服务名**: `jeeplus-gateway` **技术栈**: Spring Cloud Gateway + WebFlux + Spring Security Reactive #### 目录结构 ``` jeeplus-gateway/src/main/java/com/jeeplus/gateway/ ├── JeeplusGatewayApplication.java # 启动类 (排除DataSource/MyBatisPlus自动配置) ├── config/ │ ├── SecurityConfiguration.java # WebFlux安全配置 (白名单/认证规则) │ └── SwaggerProvider.java # Swagger资源聚合 ├── controller/ │ └── SwaggerResourceController.java # Swagger文档入口 ├── filter/ │ └── JWTFilter.java # WebFlux JWT过滤器 (Order=-300) ├── handler/ │ └── GatewayExceptionHandler.java # 统一异常处理 (ErrorWebExceptionHandler) ├── security/ │ └── TokenProvider.java # 网关层Token生成/校验/刷新 ├── service/ │ └── ... # 网关业务服务 └── excepiton/ ├── JwtAccessDeniedHandler.java └── JwtAuthenticationEntryPoint.java ``` #### 核心机制 **SecurityConfiguration** 安全规则: - 使用 `@EnableWebFluxSecurity` + `@EnableReactiveMethodSecurity` - 从 `ignore.whiteList` 配置读取白名单 URL - `/api/**` 路径需要认证 - `/management/**` (健康检查) 放行 - OPTIONS 预检请求放行 **JWTFilter** (网关层): - 从请求中解析 token (query param > header > cookie) - 从 Redis `user:cache:token` 校验 token - Token 过期时 **自动刷新** (重新生成 accessToken 并更新 Redis) - 刷新 Redis 中 token 和在线用户的过期时间 - 将认证信息注入 `ReactiveSecurityContextHolder` **GatewayExceptionHandler**: - 统一处理: `NotFoundException`, `ConnectTimeoutException`, `AccessDeniedException` - 参数校验异常: `MethodArgumentNotValidException`, `BindException` - 返回 JSON 格式错误信息 **依赖**: ``` spring-cloud-starter-gateway # 网关核心 spring-cloud-starter-alibaba-nacos-discovery # Nacos注册 spring-cloud-starter-alibaba-nacos-config # Nacos配置 spring-cloud-starter-alibaba-sentinel # Sentinel spring-cloud-alibaba-sentinel-gateway # Sentinel网关 spring-boot-starter-security # 安全 spring-boot-starter-actuator # 监控端点 springfox-boot-starter # Swagger kaptcha # 验证码 hutool-all # 工具 jeeplus-system-api # 系统API(Feign) ``` --- ### 4.2 jeeplus-auth — 认证中心 **端口**: 9211 **服务名**: `jeeplus-auth` **技术栈**: Spring Boot + Spring Security + JWT #### 目录结构 ``` jeeplus-auth/src/main/java/com/jeeplus/auth/ ├── JeeplusAuthApplication.java # 启动类 (@EnableCaching) ├── config/ │ └── DingTalkProperties.java # 钉钉多租户配置 ├── controller/ │ ├── LoginController.java # 登录核心控制器 (694行) │ └── app/ # 移动端控制器 ├── model/ │ └── LoginForm.java # 登录表单 └── service/ └── DingTalkAuthService.java # 钉钉AuthCode授权服务 ``` #### 登录方式汇总 | 接口 | 路径 | 说明 | |------|------|------| | 账号密码登录 | `POST /user/login` | 标准账号密码 + 验证码 + 单一登录校验 | | 微信登录 | `POST /user/sys/wxLogin` | 通过 openId 免密登录 | | 钉钉免登 | `POST /user/sys/ddLogin` | 钉钉 ddId 免密登录 | | 钉钉授权登录 | `POST /user/sys/dingtalk/login` | 钉钉 authCode OAuth2 登录 | | 钉钉绑定登录 | `POST /user/sys/dingtalk/bindLogin` | 首次钉钉用户绑定系统账号 | | CAS单点登录 | `GET /user/casLogin` | CAS ticket 验证 | | 退出登录 | `GET /user/logout` | 清除 Redis token + 钉钉解绑 | | 获取验证码 | `GET /user/getCode` | Hutool 图形验证码 | #### 登录流程 ``` 1. 客户端提交 LoginForm (username/password/code/uuid) 2. 检查 Redis 登录失败次数 (超过5次需要验证码, 超过10次禁止登录) 3. Spring Security AuthenticationManager.authenticate() 4. 调用 IUserApi.getByLoginName() 获取用户信息 5. 单一登录检查: IUserApi.isEnableLogin() 6. 特殊规则: 樊莉↔黄玮 互斥登录 7. 生成 JWT Token → 存入 Redis (user:cache:token) 8. 在线用户列表存入 Redis (user:cache:online:users) 9. 更新用户最后登录信息 (IP/时间) ``` **依赖**: ``` jeeplus-system-api # 系统API(Feign调用User/Tenant) jeeplus-common-security # 公共安全模块(JWT/SecurityUtils) jeeplus-common-swagger # Swagger文档 jeeplus-common-log # 日志AOP spring-boot-starter-web # Web MVC nacos-discovery/nacos-config # Nacos sentinel # Sentinel actuator + admin-client # 监控 cas-client-core # CAS单点登录 ``` --- ### 4.3 jeeplus-api — 接口定义层 所有微服务间的 **Feign 调用契约** 都定义在此层。每个 API 模块包含: - `feign/` — FeignClient 接口 - `factory/` — FallbackFactory 降级工厂 - `domain/` — 共享领域对象 - `service/dto/` — DTO 传输对象 #### API 模块清单 | 模块 | 核心 Feign 接口 | 服务提供者 | 主要功能 | |------|----------------|-----------|---------| | jeeplus-system-api | IUserApi, ITenantApi | jeeplus-system | 用户CRUD, 权限查询, 租户 | | jeeplus-system-api | (flowable工厂) | 各业务模块 | FlowableApi, AssessApi, CcpmApi, FinanceApi, HumanApi, ConsultApi, PsiManagementApi, ZsApi | | jeeplus-file-api | IFileApi | jeeplus-file | 文件上传下载 | | jeeplus-finance-api | ICwProjectReportApi | jeeplus-finance | 财务项目报告 | | jeeplus-public-modules-api | IWorkAttachmentApi | jeeplus-public-modules | 工作附件 | #### IUserApi 核心方法 (FeignClient) ``` FeignClient(name = "jeeplus-system", path = "/feign/sys/user") ├── 用户查询: getByLoginName(), getByOpenId(), getByDdId(), getById(), getUserDTOByName() ├── 权限查询: getPermissions(), getDataRuleList() ├── 在线管理: isEnableLogin(), getOnLineUserList() ├── 用户更新: updateUser(), saveOrUpdate(), updateUserById(), updateUserUpPassword() ├── 短信发送: sendRandomCodes(), sendEntryRandomCodes() ├── 文件操作: getFileDir(), delFile() ├── 认证相关: getCertListByUserId(), addDefaultSignatureCount() └── 批量查询: findListByPostId(), findListByRoleId(), findListByOfficeId(), findListByCompanyId() ``` #### ITenantApi ``` FeignClient(name = "jeeplus-system") └── getCurrentTenantId() → 从请求上下文获取当前租户ID ``` #### 核心 DTO 基类 **BaseDTO** (`jeeplus-system-api`): ``` 字段: taskId, procInsId, processDefinitionId (流程相关) id, createTime, createBy(UserDTO), updateTime, updateBy(UserDTO) delFlag, tenantDTO(TenantDTO) ``` **TreeDTO** extends BaseDTO: ``` 字段: parent(T), children(List), parentIds, name, sort 方法: getParentId(), getParentName(), getRootId()="0" ``` --- ### 4.4 jeeplus-common — 公共组件层 #### 4.4.1 jeeplus-common-core — 核心模块 **目录结构**: ``` jeeplus-common-core/src/main/java/com/jeeplus/ ├── core/ │ ├── annotation/JeeplusCloudApplication.java # 组合注解(@EnableDiscoveryClient+@EnableFeignClients+@EnableAsync) │ ├── domain/BaseEntity.java # 实体基类 │ ├── domain/TreeEntity.java # 树形实体基类 │ ├── domain/TreeMapper.java # 树形Mapper基类 │ ├── dto/DragNode.java # 拖拽排序DTO │ ├── mapstruct/EntityWrapper.java # MapStruct DTO↔Entity映射 │ ├── mapstruct/TreeWrapper.java # 树形映射(含parent转换) │ ├── query/Query.java # @Query 查询注解 │ ├── query/QueryType.java # 查询类型枚举 │ └── query/QueryWrapperGenerator.java # 动态查询条件构建器 ├── common/ │ ├── constant/AppNameConstants.java # 服务名常量 │ ├── constant/CacheNames.java # 缓存Key常量 │ ├── constant/ErrorConstants.java # 错误消息常量 │ ├── constant/CommonConstants.java # 通用常量 │ ├── excel/EasyExcelUtils.java # EasyExcel工具 │ ├── excel/ExcelListener.java # Excel读取监听器 │ ├── excel/annotation/ # Excel注解(@ExcelField等) │ ├── redis/RedisUtils.java # Redis工具(1439行, 完整API) │ ├── redis/RedisConfig.java # Redis配置 │ ├── utils/Collections3.java # 集合工具 │ ├── utils/CommonUtils.java # 通用工具 │ ├── utils/RequestUtils.java # 请求工具(token解析) │ ├── utils/ResponseUtil.java # 响应构建器 │ └── converter/StringToDateConverter.java # 日期转换器 ├── config/ │ ├── AppInit.java # 启动信息打印(CommandLineRunner) │ ├── DomainFeignConfig.java # Feign配置 │ ├── ExceptionHandlingAsyncTaskExecutor.java # 异步任务异常处理 │ └── properties/JeePlusProperties.java # 全局配置(token过期时间/文件路径) └── aop/demo/ # AOP示例 ``` **@JeeplusCloudApplication** 组合注解: ```java @EnableAsync @EnableDiscoveryClient @EnableFeignClients({"com.jeeplus.*"}) @SpringBootApplication(scanBasePackages = {"com.jeeplus", "cn.hutool.extra.spring"}, exclude = {SecurityAutoConfiguration.class}) ``` #### 4.4.2 jeeplus-common-log — 日志模块 **LoggingAspect** AOP 切面: - 切点: `@annotation(com.jeeplus.logging.annotation.ApiLog)` - `@Around`: 记录方法执行时间 → AsyncLogService 异步保存日志 - `@AfterThrowing`: 记录异常日志 - 支持 `LogTypeEnum` (LOGIN, ACCESS 等) #### 4.4.3 jeeplus-common-mybatis-plus — ORM 配置 ``` ├── config/ # MyBatis-Plus 分页插件、多租户插件、自动填充 └── database/ # 数据源配置、动态数据源 ``` #### 4.4.4 jeeplus-common-security — 安全模块 **核心类**: | 类名 | 说明 | |------|------| | `WebSecurityConfig` | Spring Security 配置 (BCrypt编码, 无状态Session, 白名单) | | `TokenProvider` | JWT 生成/解析/校验 (Auth0 JWT, HMAC256, SIGN_CODE=`@#&#$^JWE@#$F123`) | | `JWTFilter` | Token 过滤器 (GenericFilterBean) | | `JWTConfigurer` | 将 JWTFilter 注册到 Security 链 | | `SecurityUtils` | 安全工具 (获取当前用户/Token/密码加密) | | `CustomUserDetailsService` | 自定义用户详情服务 | | `DaoAuthenticationProvider` | 自定义认证提供者 | | `JwtAuthenticationEntryPoint` | 未认证处理 | | `JwtAccessDeniedHandler` | 权限不足处理 | | `ExceptionTranslator` | 异常翻译器 | | `WebConfig` | Web 配置 (CORS/拦截器) | **工具类** (`utils/`): - `Encodes.java` — 编码工具 - `Exceptions.java` — 异常工具 - `SecuritySpringContextHolder.java` — Spring上下文持有者 - `StringUtils.java` — 字符串工具 (22.9KB) #### 4.4.5 jeeplus-common-swagger — API 文档 - `SwaggerConfig.java` — Knife4j 配置 (分组/认证头) - `TypeNameIndexingAdapter.java` — 类型命名适配 --- ### 4.5 jeeplus-modules — 业务模块层 #### 4.5.1 jeeplus-system — ★核心系统服务 **启动类**: `JeeplusSystemApplication` (使用 `@JeeplusCloudApplication` + `@EnableCaching`) **分层结构**: ``` jeeplus-system/src/main/java/com/jeeplus/ ├── sys/ │ ├── controller/ # REST 控制器 │ │ ├── UserController.java (93KB) # 用户管理 │ │ ├── RoleController.java # 角色管理 │ │ ├── MenuController.java # 菜单管理 │ │ ├── OfficeController.java # 组织机构 │ │ ├── PostController.java # 岗位管理 │ │ ├── AreaController.java # 区域管理 │ │ ├── DictController.java # 字典管理 │ │ ├── TenantController.java # 租户管理 │ │ ├── LogController.java # 日志管理 │ │ ├── DataRuleController.java # 数据权限 │ │ ├── ConfigController.java # 系统配置 │ │ ├── DeskController.java # 桌面配置 │ │ ├── LanguageController.java # 国际化 │ │ └── app/ # 移动端控制器 │ ├── service/ # 业务逻辑 │ │ ├── UserService.java (36KB) │ │ ├── OfficeService.java (31KB) │ │ ├── MenuService.java │ │ ├── RoleService.java │ │ ├── TenantService.java │ │ ├── DictTypeService.java │ │ ├── DataRuleService.java │ │ ├── AreaService.java │ │ └── dto/ + mapstruct/ │ ├── domain/ # 实体 (User, Role, Menu, Office, Post, Area, DictType, DictValue, Log...) │ ├── mapper/ # MyBatis Mapper │ ├── feign/ # Feign 接口实现 (供其他服务调用) │ ├── model/ # 页面VO/Model │ ├── sms/ # 短信服务 │ └── utils/ # 系统专用工具 ├── calendar/ # 日历 ├── database/ # 数据库管理 ├── datav/ # 数据可视化 ├── echarts/ # 图表 ├── form/ # 表单设计 ├── mail/ # 邮件 ├── monitor/ # 监控 ├── notify/ # 通知 └── tools/ # 工具 ``` #### 4.5.2 jeeplus-flowable — 工作流服务 ``` jeeplus-flowable/src/main/java/com/jeeplus/ ├── flowable/ │ ├── controller/ # 流程控制器 (8个) │ ├── service/ # 流程服务 (7个) │ ├── model/ # 流程模型 (11个) │ ├── mapper/ # 流程Mapper │ ├── listener/ # 流程监听器 │ ├── utils/ # 流程工具 (13个) │ ├── vo/ # 视图对象 │ ├── common/ # 公共流程工具 │ └── constant/ # 流程常量 ├── centerservice/ # 中心服务 ├── extension/ # 扩展 ├── modules/ # 模块 └── weChat/ # 微信集成 ``` #### 4.5.3 jeeplus-file — 文件服务 存储支持: MinIO / 阿里云 OSS ``` jeeplus-file/src/main/java/com/jeeplus/file/ ├── JeeplusFileApplication.java ├── controller/ # 文件上传/下载/预览 ├── repository/ # 存储仓库 (5种) ├── config/ # 存储配置 ├── model/ # 文件模型 └── utils/ # 文件工具 ``` #### 4.5.4 其他业务模块一览 | 模块 | 包路径 | 功能描述 | |------|--------|---------| | jeeplus-finance | `com.jeeplus.finance` | 财务管理 (15个子包) | | jeeplus-assess | `com.jeeplus.assess` | 评估考核 (10个子包) | | jeeplus-human | `com.jeeplus.human` | 人力资源管理 (5个子包) | | jeeplus-ccpm | `com.jeeplus.ccpm` | 项目管理 (3个子包) | | jeeplus-consult | `com.jeeplus.consultancy` | 培训咨询 (4个子包) | | jeeplus-public-modules | `com.jeeplus.pubmodules` | 公共功能: 收藏/合同/知识库/会议室/抽奖/物料/供应商/仓库/采购/序列号/OOS/假期/编辑器/附件 | | jeeplus-centrecareful | — | 中审管理 | | jeeplus-psi-management | — | PSI管理 | | jeeplus-devtools | — | 代码生成等开发工具 | | jeeplus-ureport | — | UReport 报表引擎 | | jeeplus-wps | — | WPS 文档在线编辑 | | jeeplus-xxl-job-admin | — | XXL-Job 调度中心 | | jeeplus-xxl-job-executor-sample | — | XXL-Job 执行器 | | jeeplus-admin-server | — | Spring Boot Admin 监控服务 | | jeeplus-test | — | 测试模块 | --- ## 5. 核心基类体系 ### 5.1 实体基类 (Entity) ``` BaseEntity (jeeplus-common-core) ├── id: String @TableId ├── createTime: Date @TableField(fill=INSERT) ├── createById: String @TableField(fill=INSERT) ├── updateTime: Date @TableField(fill=INSERT_UPDATE) ├── updateById: String @TableField(fill=INSERT_UPDATE) ├── delFlag: Integer @TableLogic, @TableField(fill=INSERT) └── tenantId: String @TableField(fill=INSERT), @Query(type=EQ) │ └── TreeEntity extends BaseEntity ├── parentId: String ├── parentIds: String # 所有父级ID路径 ├── name: String ├── sort: Integer └── children: List @TableField(exist=false) ``` ### 5.2 传输对象基类 (DTO) ``` BaseDTO (jeeplus-system-api) ├── taskId: String # 流程任务ID ├── procInsId: String # 流程实例ID ├── processDefinitionId: String # 流程定义ID ├── id: String ├── createTime: Date ├── createBy: UserDTO ├── updateTime: Date ├── updateBy: UserDTO ├── delFlag: Integer └── tenantDTO: TenantDTO │ └── TreeDTO extends BaseDTO ├── parent: T ├── children: List ├── parentIds: String ├── name: String └── sort: Integer ``` ### 5.3 MapStruct 映射器 ``` EntityWrapper ├── toEntity(D dto) → E # @Mapping: tenantDTO.id→tenantId, createBy.id→createById ├── toDTO(E entity) → D # @Mapping: tenantId→tenantDTO.id, createById→createBy.id ├── toEntity(List) → List ├── toDTO(List) → List ├── toEntity(Page) → Page └── toDTO(Page) → Page TreeWrapper extends EntityWrapper ├── toEntity/toDTO (继承 + parent.id↔parentId 映射) ├── copyEntity / copyDTO └── toEntity(DragNode) → DragNode # 拖拽排序支持 ``` ### 5.4 服务基类 ``` TreeService, T extends TreeEntity> extends ServiceImpl ├── saveOrUpdate(T) # 自动维护 parentIds 路径 ├── sortList(DragNode) # 拖拽排序 ├── getChildren(T) # 查询子节点 ├── removeWithChildrenById() # 级联删除 ├── treeData() # 获取完整树 └── formatListToTree() # 列表→树形转换 (Map分组+递归) ``` --- ## 6. 常用工具类 ### 6.1 RedisUtils (jeeplus-common-core) > 位置: `com.jeeplus.common.redis.RedisUtils` (1439行) **推荐API** (带 cacheName 前缀): ```java RedisUtils.getInstance().get(cacheName, key) // 读取 RedisUtils.getInstance().set(cacheName, key, value) // 写入 RedisUtils.getInstance().delete(cacheName, key) // 删除 RedisUtils.getInstance().expire(cacheName, key, t) // 过期 RedisUtils.getInstance().keys(cacheName, pattern) // 模糊匹配 ``` `@Deprecated` 标记的直接操作方法 (不带 cacheName) 不推荐使用,因为会使 `@CacheEvict`/`@Cacheable` 注解无效。 ### 6.2 ResponseUtil (jeeplus-common-core) ```java ResponseUtil.newInstance() .add("key", value) // 链式添加响应字段 .ok() // 返回 ResponseEntity (200) .ok("message") // 返回带消息的 ResponseEntity ``` ### 6.3 RequestUtils (jeeplus-common-core) ```java RequestUtils.getRequest() // 获取 HttpServletRequest RequestUtils.getHeader("headerName") // 获取请求头 RequestUtils.resolveToken(request, "token") // 解析token (param > header > cookie) ``` ### 6.4 SecurityUtils (jeeplus-common-security) ```java SecurityUtils.getLoginName() // 当前登录用户名 SecurityUtils.getCurrentUserDTO() // 当前用户完整信息 SecurityUtils.getToken() // 当前Token SecurityUtils.getAuthentication() // 认证信息 SecurityUtils.login(username, password, authMgr) // 手动登录 SecurityUtils.encryptPassword(password) // BCrypt加密 SecurityUtils.validatePassword(plain, encoded) // 密码验证 ``` ### 6.5 QueryWrapperGenerator (jeeplus-common-core) 基于 `@Query` 注解动态构建 MyBatis-Plus `QueryWrapper`: ```java QueryWrapper qw = QueryWrapperGenerator.buildQueryCondition(searchObj, Entity.class); ``` 支持查询类型: EQ, NE, GT, GE, LT, LE, BETWEEN, NOTBETWEEN, LIKE, NOTLIKE, LIKELEFT, LIKERIGHT ### 6.6 EasyExcelUtils (jeeplus-common-core) EasyExcel 读写封装,支持自定义 `@ExcelField` 注解的列转换。 ### 6.7 TokenProvider (jeeplus-common-security) ```java TokenProvider.createAccessToken(username) // 生成JWT TokenProvider.validateToken(token) // 校验JWT TokenProvider.getLoginName(token) // 从Token中获取用户名 TokenProvider.getAuthentication(token) // 获取认证对象(含权限) TokenProvider.resolveToken(request) // 从请求中解析Token TokenProvider.getCurrentToken() // 获取当前请求的Token ``` JWT 签名: `Algorithm.HMAC256("@#&#$^JWE@#$F123")` Token 中包含: `username` claim + `expiresAt` ### 6.8 JeePlusProperties ```java JeePlusProperties.newInstance().getEXPIRE_TIME() // Token过期时间(秒) JeePlusProperties.newInstance().getUserfilesBaseDir() // 文件存储根目录 ``` --- ## 7. 服务间调用与依赖关系 ### 7.1 服务注册名 (Nacos) | 服务名 | 端口 | 模块 | |--------|------|------| | `jeeplus-gateway` | 8088 | 网关 | | `jeeplus-auth` | 9211 | 认证 | | `jeeplus-system` | — | 系统核心 | | `jeeplus-flowable` | — | 工作流 | | `jeeplus-file` | — | 文件 | | `jeeplus-finance` | — | 财务 | | `jeeplus-assess` | — | 评估 | | `jeeplus-human` | — | 人事 | | `jeeplus-ccpm` | — | 项目管理 | | `jeeplus-public-modules` | — | 公共模块 | | `jeeplus-centrecareful` | — | 中审 | | `jeeplus-consultancy` | — | 培训 | | `jeeplus-psi-management` | — | PSI | ### 7.2 Feign 调用关系图 ``` jeeplus-auth ──Feign──▶ jeeplus-system (IUserApi, ITenantApi) jeeplus-gateway ──Feign──▶ jeeplus-system (IUserApi) jeeplus-flowable ──Feign──▶ jeeplus-system ──▶ jeeplus-assess ──▶ jeeplus-finance ──▶ jeeplus-human ──▶ jeeplus-ccpm ──▶ jeeplus-consult ──▶ jeeplus-psi-management ──▶ jeeplus-centrecareful 各业务模块 ──Feign──▶ jeeplus-system (获取用户/权限/租户) ──▶ jeeplus-file (文件存储) ──▶ jeeplus-public-modules (工作附件) ``` ### 7.3 Fallback 降级策略 所有 Feign 接口都配置了 `fallbackFactory`,当服务不可用时返回默认值或空对象: | API | FallbackFactory | |-----|----------------| | IUserApi | UserApiFallbackFactory | | ITenantApi | TenantApiFallbackFactory | | IFileApi | FileApiFallbackFactory | | IWorkAttachmentApi | WorkAttachmentApiFallbackFactory | | ICwProjectReportApi | CwProjectReportApiFallbackFactory | | FlowableApi | FlowableApiFallbackFactory | | AssessApi | AssessApiFallbackFactory | | 等... | | --- ## 8. 接口规范 ### 8.1 RESTful URL 规范 ``` /模块名/资源名/操作 用户管理: /sys/user/** 角色管理: /sys/role/** 菜单管理: /sys/menu/** 部门管理: /sys/office/** 岗位管理: /sys/post/** 字典管理: /sys/dict/** 租户管理: /sys/tenant/** 流程管理: /flowable/** 文件管理: /file/** Feign内部调用: /feign/模块名/资源名/** ``` ### 8.2 Swagger 规范 - 所有 Controller 使用 `@Api(tags="xxx")` 标注分组 - 接口方法使用 `@ApiOperation("xxx")` 标注说明 - DTO 字段使用 `@ApiModelProperty` 标注 - 隐藏字段: `@IgnoreSwaggerParameter`, `@ApiModelProperty(hidden=true)`, `@ExcelIgnore` - 文档入口: `http://{ip}:{port}/doc.html` - Gateway 聚合了所有子服务的 Swagger 文档 ### 8.3 DTO ↔ Entity 转换规范 - 使用 MapStruct 自动映射 (`EntityWrapper`, `TreeWrapper`) - DTO 中关联对象使用完整实体 (如 `UserDTO createBy`),Entity 中只存 ID (如 `String createById`) - 通过 `@Mapping` 注解声明映射关系 - 前端交互统一使用 DTO,禁止直接暴露 Entity ### 8.4 分页规范 使用 MyBatis-Plus `IPage` 作为分页返回类型,MapStruct 提供 `Page ↔ Page` 自动转换。 ### 8.5 响应格式 ```json { "token": "xxx", "oldLoginDate": "2026-01-01 12:00:00", "oldLoginIp": "192.168.1.1" } ``` 通过 `ResponseUtil` 链式构建响应,最终返回 `ResponseEntity`。 --- ## 9. 权限控制逻辑 ### 9.1 认证流程架构 ``` ┌─────────────┐ │ 客户端 │ └──────┬──────┘ │ 用户名/密码 ▼ ┌─────────────────┐ │ jeeplus-auth │ │ LoginController │ └────────┬────────┘ │ SpringSecurity.authenticate() ▼ ┌─────────────────┐ │ DaoAuthentication│ │ Provider │ └────────┬────────┘ │ BCrypt密码校验 ▼ ┌─────────────────┐ │ IUserApi │──▶ jeeplus-system │ getByLoginName()│ 查询用户 └────────┬────────┘ │ ┌────────▼────────┐ │ 生成JWT Token │ │ 存入 Redis │ │ user:cache:token │ └────────┬────────┘ │ 返回 Token ▼ ┌─────────────┐ │ 客户端 │ 携带 Token └──────┬──────┘ │ 每次请求带 Token ▼ ┌─────────────────┐ │ jeeplus-gateway │ │ JWTFilter │ └────────┬────────┘ │ 校验Redis中的Token │ 过期自动刷新 ▼ ┌─────────────────┐ │ 路由到目标服务 │ └────────┬────────┘ │ ┌────────▼────────┐ │ 微服务内部 │ │ WebSecurityConfig │ │ JWTFilter(common) │ └────────┬────────┘ │ @PreAuthorize 方法级权限 ▼ ┌─────────────────┐ │ 执行业务逻辑 │ └─────────────────┘ ``` ### 9.2 权限模型: RBAC ``` 用户(User) ──多对多──▶ 角色(Role) ──多对多──▶ 菜单权限(Menu/permission) │ │ │ └── 数据权限(DataRule) │ └── 多对一 ──▶ 部门(Office) └── 多对多 ──▶ 岗位(Post) └── 多对一 ──▶ 租户(Tenant) ``` ### 9.3 方法级权限 (`@PreAuthorize`) `WebSecurityConfig` 开启 `@EnableGlobalMethodSecurity(prePostEnabled = true)`,支持: ```java @PreAuthorize("hasAuthority('sys:user:edit')") @PreAuthorize("hasRole('admin')") ``` 权限标识通过 `IUserApi.getPermissions(loginName)` 获取,注入到 `Authentication.authorities`。 ### 9.4 数据权限 (DataRule) - 通过 `IUserApi.getDataRuleList(userDTO)` 获取用户数据权限规则 - 缓存: `user:cache:dataRuleList` - 在 MyBatis 查询时动态追加数据过滤条件 ### 9.5 多租户隔离 - `BaseEntity.tenantId` 自动填充 (`@TableField(fill=INSERT)`) - `@Query(type=EQ)` 默认按租户等值查询 - `ITenantApi.getCurrentTenantId()` 从请求上下文获取当前租户 - 缓存 Key 自动包含租户上下文 ### 9.6 Token 生命周期 ``` 登录 → createAccessToken() → Redis.set(token, ttl=EXPIRE_TIME) → Redis.set(onlineUsers, ttl=EXPIRE_TIME) 请求 → JWTFilter(Gateway): 1. 从Redis校验token 2. 若accessToken过期 → 自动生成新token → 更新Redis 3. 刷新Redis过期时间 4. 注入SecurityContext 退出 → LoginController.logout(): 1. Redis.delete(token) 2. Redis.delete(onlineUsers) 3. 清除Spring Security上下文 4. 同用户名所有设备下线 5. 钉钉解绑 ``` ### 9.7 Gateway 白名单 (`ignore.whiteList`) 通过 Nacos 配置动态管理,支持通配符路径。示例中允许: - `/**` (全局) - `/*/public-modules-server/luckyDraw/events/**` (抽奖活动) - Swagger 静态资源 (`/doc.html`, `/swagger-ui.html`, `/webjars/**`) - 管理端点 (`/management/**`) - OPTIONS 预检请求 --- ## 10. 关键常量与缓存设计 ### 10.1 服务名常量 (AppNameConstants) | 常量 | 值 | |------|-----| | APP_AUTH_SERVICE | `jeeplus-auth` | | APP_SYSTEM_SERVICE | `jeeplus-system` | | APP_FILE_SERVICE | `jeeplus-file` | | APP_FLOWABLE_SERVICE | `jeeplus-flowable` | | APP_PUBLIC_MODULES | `jeeplus-public-modules` | | APP_ASSESS_MODULES | `jeeplus-assess` | | APP_FINANCE_MODULES | `jeeplus-finance` | | APP_HUMAN_MODULES | `jeeplus-human` | | APP_CCPM_MODULES | `jeeplus-ccpm` | | APP_CENTRECAREFUL_MODULES | `jeeplus-centrecareful` | | APP_CONSULT_MODULES | `jeeplus-consultancy` | | APP_PSI_MANAGEMENT_MODULES | `jeeplus-psi-management` | ### 10.2 Redis 缓存 Key 设计 (CacheNames) ``` sys:cache:code # 验证码 sys:cache:config # 系统配置 sys:cache:areaList # 区域列表 sys:cache:dictMap # 字典映射 sys:cache:tenant # 租户信息 sys:cache:menu # 菜单 sys:cache:languageMap # 语言国际化 user:cache:topMenu # 用户顶部菜单 user:cache:menuList # 用户左侧菜单 user:cache:dataRuleList # 用户数据权限规则 user:cache:roleList # 用户角色列表 user:cache:userId # 用户ID→用户信息 user:cache:loginName # 登录名→用户信息 user:cache:token # Token存储 user:cache:online:users # 在线用户列表 user:cache:user:all:info # 所有用户信息 user:assess:cache:code:loginName # 登录失败次数 ccpm:is:connect # CCPM系统连接状态 user:cache:dataRuleExists # 数据权限存在标记 ``` ### 10.3 错误消息常量 (ErrorConstants) ``` LOGIN_ERROR_NOT_LOGIN_IN "您尚未登录,请登录后操作!" LOGIN_ERROR_FORBIDDEN "该帐号已经被禁止登录!" LOGIN_ERROR_INCORRECT "用户名或者密码错误!" LOGIN_ERROR_NOTFOUND "用户名不存在!" LOGIN_ERROR_EXPIRED "您的登录已过期,请重新登录!" LOGIN_ERROR_FORBID_LOGGED_IN_ELSEWHERE "您的账号已在其它地方登录,您被禁止登录!" LOGIN_ERROR__KICK_OUT_LOGGED_IN_ELSEWHERE "您的账号在另一台设备上登录..." LOGIN_ERROR_ERROR_VALIDATE_CODE "您输入的验证码不正确,请重新输入!" LOGIN_CODE "请输入验证码进行登录!" LOGIN_MAX_COUNT "今天登录次数已达最大,请明天再登录!" LOGIN_ERROR "您目前无法登录!" ``` --- ## 附录: 关键配置项 ### Nacos 配置 (bootstrap.yml) ```yaml spring.cloud.nacos: discovery.server-addr: 127.0.0.1:8848 discovery.namespace: ${spring.profiles.active} config.server-addr: 127.0.0.1:8848 config.file-extension: yml config.shared-configs: [application.yml] sentinel.transport.dashboard: 127.0.0.1:8858 ribbon.ReadTimeout: 600000 ribbon.ConnectTimeout: 600000 hystrix.command.default.execution.isolation.thread.timeoutInMillisecond: 60000 ``` ### JWT 配置 ```yaml jwt.accessToken.expireTime: (在Nacos中配置, 单位秒) ``` ### 文件存储配置 ```yaml userfiles.basedir: (文件存储根目录) ``` --- > **生成时间**: 2026-06-01 > **索引范围**: xg_total_process_master_cloud 全部模块 (5个顶层模块, 27个子模块) > **Java源文件**: 覆盖 jeeplus-gateway, jeeplus-auth, jeeplus-api, jeeplus-common, jeeplus-modules 五大模块