Appearance
hc-hire-center 项目结构与新手上手指南
适用项目:
/Users/admin/code/hc-project/api-java/hc-hire-center
分析日期:2026-07-16
项目规模:649 个有效项目文件,其中 573 个代码文件、57 个配置文件、18 个 SQL 文件、1 个说明文档
说明:当前目录不是 Git 仓库,因此本文无法关联具体提交号;内容以分析当日的本地源码为准。
1. 先用一句话理解项目
hc-hire-center 是欢创招聘中心后端服务,围绕以下三条业务主线展开:
candidate:候选人简历、人才库、导入、检索、权限、版本与附件。position:职位、职位参与人、供应商、登记、申请审批与职位下推荐。reco:候选人推荐后的跟进流程,包括沟通、面试、Offer、入职和过保。
它不是一个可以脱离公司基础设施独立运行的演示项目。项目依赖欢创内部 hc-* starter、Maven 私服、配置中心、租户和用户上下文,以及 PostgreSQL、Redis、Elasticsearch、XXL-Job、OSS 和多个内部微服务。
2. 技术栈速览
| 类别 | 项目中的实际技术 |
|---|---|
| 语言与构建 | Java 8、Maven 多模块 |
| Web 框架 | Spring Boot、Spring MVC、Spring Cloud 服务发现、内部 hc-starter-web |
| 持久化 | PostgreSQL、MyBatis-Plus、内部 IHcService / IHcServiceImpl |
| 对象转换 | MapStruct、Lombok |
| 搜索 | Spring Data Elasticsearch、内部 hc-starter-es |
| 缓存与锁 | Redis、内部 hc-starter-cache、RedisLockUtil |
| 调度 | XXL-Job、Spring Scheduling |
| 文件 | 租户动态 OSS |
| 远程调用 | 内部 Feign、租户中心、项目中心、流程中心等 API Client |
| 接口文档 | Swagger 2 注解 |
| 其他 | PDFBox、简历解析第三方 API、邮件和浏览器插件导入 |
3. Maven 模块
text
hc-hire-center/
├── pom.xml
├── hc-hire-center-api/
│ └── pom.xml
└── hc-hire-center-service/
├── pom.xml
└── src/main/
├── java/com/hc/hire/
└── resources/3.1 根模块 hc-hire-center
根 pom.xml 的 packaging 是 pom,负责聚合两个子模块,并统一指定 Java 8。它继承内部父 POM:
text
com.hcframework.boot:hc-boot-starter:1.0.0-SNAPSHOT这个父 POM 在公司 Maven 私服中。没有私服凭证时,Maven 在读取项目模型的第一步就会失败。
3.2 hc-hire-center-api
按命名习惯,这个模块应承载可供其他服务依赖的 Feign Client、Form、DTO、VO 或接口契约。但在当前源码快照中,它只有 pom.xml,没有 Java 源码。
新人需要注意:不要因为模块名中有 api,就去这里寻找当前系统的 Controller 或请求对象。现有业务代码全部在 hc-hire-center-service 中。
3.3 hc-hire-center-service
这是实际可运行模块,包含:
- Spring Boot 启动类;
- Web Controller;
- 业务 Service;
- Entity、Mapper 和 SQL;
- Elasticsearch Document 与 Repository;
- XXL-Job 任务;
- OSS、Feign 和第三方 API 适配;
- HTTP 手工调试请求。
4. 运行时架构
mermaid
flowchart LR
Client[前端或外部调用方] --> Gateway[网关与认证]
Gateway --> Controller[Controller]
Controller --> Service[业务 Service]
Service --> Permission[数据权限服务]
Service --> Mapper[MyBatis Mapper]
Mapper --> PG[(PostgreSQL)]
Service --> ES[(Elasticsearch)]
Service --> Redis[(Redis)]
Service --> OSS[(租户 OSS)]
Service --> Remote[内部 Feign/API Client]
Remote --> Tenant[租户中心]
Remote --> PMS[项目中心]
Remote --> Process[流程中心]
Job[XXL-Job] --> Service大多数同步 HTTP 请求遵循下面的调用方向:
text
Controller -> Service 接口 -> ServiceImpl -> Mapper -> PostgreSQL
| |
| +-> Elasticsearch / Redis / OSS
+------------> 内部服务网关或第三方 APIController 不直接写数据库。跨系统调用通常再包一层项目内 Gateway Service,以免核心业务代码直接依赖外部系统的 Form 和 VO。
5. 业务包怎么读
hc-hire-center-service/src/main/java/com/hc/hire 下有 5 个一级区域:
| 包 | 规模 | 主要职责 |
|---|---|---|
candidate | 251 个 Java 文件 | 候选人主数据、简历、人才库、导入、ES 检索、权限和版本 |
position | 203 个 Java 文件 | 职位主数据、项目关联、参与人、供应商、登记、审批和职位推荐 |
reco | 90 个 Java 文件 | 推荐记录、跟进状态机、面试、Offer、入职、保证期和业绩拆分 |
common | 11 个 Java 文件 | 公共常量、第三方策略框架、通用 OSS 文件服务 |
config | 3 个 Java 文件 | 业务编码、Elasticsearch 扩展和 RestTemplate 配置 |
5.1 candidate:候选人领域
主要能力包括:
- 手工录入和编辑候选人;
- 批量、Excel、扫码、邮箱、浏览器插件和外部接口导入;
- 候选人工作、项目、教育、语言、技能等简历板块;
- 候选人查重、完整度、保护期、版本快照和回滚;
- 人才库、我的候选人、收藏、预览、备注、标签和黑名单;
- 供应商维度的数据权限;
- PostgreSQL 到 Elasticsearch 的同步、失败记录和补偿任务;
- 简历附件上传 OSS、预览和下载;
- 候选人加入职位并生成推荐记录。
阅读起点:
text
candidate/controller/web/client/CandidateManualController.java
candidate/service/CandidateManualService.java
candidate/service/impl/CandidateManualServiceImpl.java
candidate/service/impl/CandidateLifecycleServiceImpl.java
candidate/entity/HireCandidate.java5.2 position:职位领域
主要能力包括:
- 职位新增、编辑、详情、暂停、结束、显示和置顶;
- 职位与外部项目、客户、产品、项目人员的关联;
- 招聘负责人、交付负责人、顾问等职位参与人;
- 职位供应商、供应商管理人转移和保证期配置;
- 申请加入职位及流程中心审批;
- 面试登记配置、扫码令牌和登记结果;
- 职位附件、备注和职位下的候选人推荐;
- 简历下载、导出、面试结果导入等异步任务。
阅读起点:
text
position/controller/web/client/PositionController.java
position/service/PositionService.java
position/service/impl/PositionServiceImpl.java
position/service/PositionDataPermissionService.java
position/service/impl/PositionDataPermissionServiceImpl.java
position/entity/HirePosition.java5.3 reco:推荐跟进领域
reco 不是“推荐算法”模块,而是候选人被推荐到某个职位之后的业务过程。核心记录是 HireReco,跟进阶段大致为:
text
初步沟通
-> 推荐
-> 预约面试
-> 到场
-> 面试通过
-> 接 Offer
-> 入职
-> 过保每一步都存在否决、放弃、不到场、不通过、不过保或回退等分支。合法流转由 RecoFollowStateServiceImpl 校验,不应在 Controller 或其他 Service 中自行拼接状态编码。
阅读起点:
text
reco/controller/web/client/RecoController.java
reco/service/RecoService.java
reco/service/impl/RecoServiceImpl.java
reco/service/RecoFollowStateService.java
reco/service/impl/RecoFollowStateServiceImpl.java
reco/enums/HireFollowStageEnum.java
reco/enums/HireFollowActionEnum.java6. 每个业务包内部的技术分层
| 目录 | 放什么 | 新手常见误区 |
|---|---|---|
controller | HTTP 路由、参数接收、校验、统一结果封装 | 不要在这里写事务和复杂业务 |
form | 新增、编辑、查询等入参 | 它不是数据库 Entity |
dto | 服务间或内部步骤的数据载体 | DTO 不一定直接返回给前端 |
vo | 返回前端的展示对象 | 不要直接把 Entity 当完整响应 |
service | 业务接口、领域能力定义 | 接口用于表达能力,不只是为形式而存在 |
service/impl | 事务、编排、权限、状态变化和外部调用 | 复杂度主要集中在这里 |
entity | MyBatis-Plus 数据库实体 | 字段和表结构必须保持一致 |
mapper | 数据访问接口 | 简单 CRUD 通常继承基础 Mapper,不需要 XML SQL |
converter | MapStruct 的 Form/DTO/Entity/VO 转换 | 新字段增加后要检查映射是否被忽略 |
document | Elasticsearch 索引文档 | 与数据库 Entity 不是同一个一致性边界 |
repository | Elasticsearch Repository | 不是 PostgreSQL Mapper |
enums | 稳定业务编码与状态 | 不要在调用处散落魔法数字 |
constants | 业务常量、状态流转表、路径等 | 修改会影响多个流程,应搜索全部引用 |
task | XXL-Job 任务 | 多实例执行时需要分布式锁或幂等 |
processor | 导入框架处理器 | 由内部导入 SDK 的工厂发现和调用 |
7. 项目特有的框架约定
项目大量能力来自私有 hc-* starter。只熟悉标准 Spring Boot 时,下面这些类型最容易让人困惑。
7.1 Controller 约定
java
@WebClientRestController("/candidate/manual")
public class CandidateManualController
extends BaseController<HireCandidate, CandidateManualService> {
}@WebClientRestController是内部路由注解,承担标准@RestController加客户端路由语义。BaseController<E, S>提供统一 Service 注入等基础能力。- 返回值统一使用
Result<T>。 - 列表分页常使用
@QueryPage、QueryModel和QueryResultModel<T>。 - 外部开放接口可以直接使用标准
@RestController,例如CandidateExternalPushController。
注解中声明的是服务内路由。线上完整 URL 还可能包含网关前缀,必须以网关配置或实际 Swagger 为准。
7.2 Service 与 Mapper 约定
常见继承关系是:
java
public interface XxxService extends IHcService<XxxEntity> {
}
public class XxxServiceImpl
extends IHcServiceImpl<XxxMapper, XxxEntity>
implements XxxService {
}它们在 MyBatis-Plus 的基础上提供公司统一能力。因此:
- 常规
save、updateById、getById、list不需要重复写 Mapper 方法; - 复杂联表查询会使用
MPJLambdaWrapper或HcMPJLambdaWrapper; - 少量定制 SQL 放在
resources/mapper/*.xml; - 当前多数 Mapper XML 只是空骨架,SQL 主要来自基础 Mapper 和 Wrapper。
7.3 用户和租户上下文
业务代码通过以下上下文获取当前身份:
text
UserContext.getOpenId()
UserContext.getUser()
TenantContextHolder.getTenantId()这意味着直接调用 Service、用普通 MockMvc 发请求或绕过公司网关时,如果没有构造用户和租户上下文,常见结果是“当前用户未登录”或“租户信息不能为空”。不要为了本地跑通而删除这些校验。
8. 三条最值得跟读的调用链
8.1 手工录入候选人
入口:POST /candidate/manual/save
text
CandidateManualController.saveCandidate
-> CandidateManualService.saveCandidate
-> CandidateManualServiceImpl.saveCandidate
1. CandidateDuplicateService:手机号/邮箱查重
2. CandidateLifecycleService.initializeForCreate:租户、创建人、保护期、默认值、候选人编号
3. 保存 HireCandidate 主表
4. 保存残障、意向、工作、项目、教育、语言、技能等子表
5. CandidateLifecycleService.afterCreated
-> 刷新简历完整度
-> 创建版本快照
-> 同步 Elasticsearch
6. 特殊候选人按规则自动推荐这个流程能一次看懂项目中的 Form、Converter、Entity、事务、子表 Service、生命周期和 ES 同步。
8.2 候选人 PostgreSQL 与 Elasticsearch 一致性
text
业务事务修改 PostgreSQL
-> CandidateLifecycleService.afterChanged
-> CandidateSyncService.incrementalSync / syncAfterCommit
-> CandidateDocumentConverter
-> CandidateSearchRepository
-> Elasticsearch同步失败时不会回滚已经提交的 PostgreSQL 主事务,而是记录到 hire_candidate_es_sync_fail。EsSyncCompensateTask 通过 XXL-Job 定期补偿,并使用 Redis 分布式锁避免多个实例重复执行。
理解这个边界很重要:
- PostgreSQL 是候选人主数据源;
- Elasticsearch 是查询索引,不应被当作唯一数据源;
- 新增候选人字段后,要同步检查 Entity、Document、Converter、查询条件和全量同步;
- 修改事务代码时,要注意同步是在提交前还是提交后触发。
8.3 推荐跟进状态机
text
RecoController.submitFollow
-> CandidateFollowService.submitFollow
-> RecoFollowStateService.validateStageTransfer
-> RecoFollowStateService.resolveAction
-> RecoFollowBusinessService.saveBusinessData
-> 保存 HireFollowRecord
-> 更新 HireReco 当前阶段和状态核心规则分散在:
HireFollowStageEnum:有哪些阶段,哪些是结束阶段,哪些允许再次推荐;HireFollowActionEnum:有哪些动作;CandidateFollowConstant:前进和回退阶段映射;RecoFollowStateServiceImpl:合法性校验和动作解析;RecoFollowBusinessServiceImpl:不同动作产生的面试、Offer、入职、保证期等业务明细。
修改流程时不能只改一个枚举。至少要同时核对状态映射、业务明细、列表展示、ES 文档和历史数据兼容性。
9. 职位模块的外部系统边界
职位并不拥有所有相关主数据。项目、客户、产品、部门成员、供应商和审批流来自其他中心。项目通过 Gateway Service 把外部类型隔离在边界处:
| 项目内边界 | 外部依赖 |
|---|---|
PositionProjectGatewayService | 项目中心、部门成员 API |
PositionApplyApprovalGatewayService | 流程中心流程模型、实例和审批详情 API |
ExternalSupplierGatewayService | 租户中心供应商与成员 API |
PositionProjectManageService | 项目中心招聘入口项目管理 Feign Client |
新增跨服务逻辑时,优先扩展 Gateway 接口和默认实现,不要让核心 PositionServiceImpl 到处直接引用外部系统 Form/VO。这样更容易测试,也能避免外部契约变化污染整个领域。
10. 数据层与表结构
主数据库是 PostgreSQL,数据库名配置为 hc_hire_center。Entity 使用 @TableName 显式映射,核心表可按领域理解:
候选人
text
hire_candidate
hire_candidate_work
hire_candidate_project
hire_candidate_education
hire_candidate_language
hire_candidate_skill
hire_candidate_intention
hire_candidate_file
hire_candidate_version
hire_candidate_collection
hire_candidate_remark
hire_candidate_blacklist
hire_candidate_es_sync_fail职位
text
hire_position
hire_position_person
hire_position_supplier
hire_position_supplier_warranty
hire_position_apply
hire_position_file
hire_position_remark
hire_position_register
hire_position_register_submit
hire_position_scan_token
hire_position_reco_task
hire_position_reco_result推荐跟进
text
hire_reco
hire_follow_record
hire_interview_arrangement
hire_offer
hire_onboarding
hire_guarantee_period
hire_supplier_guarantee_period
hire_performance_splitting
hire_reco_commsrc/main/resources/sql 中只有 2026 年 5 月的一组增量脚本,不包含完整基线建库脚本。新人本地建库前必须向团队确认:
- 基线数据库从哪里初始化;
- 这些 SQL 是否由 Flyway、发布平台还是人工按顺序执行;
- 当前环境已经执行到哪个版本;
- 租户字段、逻辑删除字段和审计字段的统一约定。
不要看到 CREATE TABLE IF NOT EXISTS 就默认这些文件足以创建完整数据库。
11. 配置文件怎么理解
11.1 application.yml
主要包含:
- 服务端口
7007; - Maven 过滤后的应用名;
- 动态租户数据源;
- PostgreSQL 连接占位符;
- Elasticsearch;
- Swagger;
- XXL-Job;
- SaaS 多租户;
- 简历解析和浏览器插件配置。
11.2 nacos-application.yml
内容与运行时业务配置高度重合,表明项目配置可能通过 Nacos 或公司配置体系下发。启动前要向团队确认实际加载顺序和环境 Data ID,不能只修改本地 YAML 后就认为配置一定生效。
11.3 当前配置的安全与正确性注意事项
当前源码配置中存在明文敏感信息或带默认值的凭证。本文不会记录这些值。正确做法是:
- 把密钥放到环境变量、Nacos Secret 或发布系统密文变量;
- 不在文档、日志和截图中传播真实值;
- 如果这些值已经进入版本历史,应按安全流程轮换,而不是只删除当前文件内容;
- 本地调试使用独立的开发环境凭证。
另外,当前 application.yml 中出现重复的顶级 spring 节点。不同 YAML 解析策略可能覆盖前一个节点或直接报重复 key,修改配置前应先确认最终生效结果并合并节点。
Swagger 配置的扫描包是 com.hc.hire.controller,但实际 Controller 位于 com.hc.hire.candidate.controller、com.hc.hire.position.controller 和 com.hc.hire.reco.controller。如果 Swagger 页面为空,首先检查这个 base-package 是否覆盖实际包路径。
12. 本地环境准备
12.1 必需软件
| 软件或服务 | 建议/项目要求 |
|---|---|
| JDK | Java 8;当前项目编译目标为 1.8 |
| Maven | 3.8+;本次验证使用 3.9.9 |
| IDE | IntelliJ IDEA,并启用 Lombok annotation processing |
| Maven 私服 | 需要访问公司阿里云 Maven 仓库并配置凭证 |
| PostgreSQL | 需要可用的 hc_hire_center 基线库 |
| Redis | 动态租户、缓存和分布式锁依赖 |
| Elasticsearch | 候选人和推荐搜索依赖 |
| Nacos/注册中心 | 服务发现和环境配置依赖 |
| XXL-Job | 补偿任务等调度依赖 |
| OSS | 简历和职位附件依赖 |
12.2 先解决 Maven 私服
根 POM 的仓库 ID 是 hcjt。请从团队获取正确的 Maven settings.xml,并确保 <server> 的 <id> 与 POM 一致:
xml
<settings>
<servers>
<server>
<id>hcjt</id>
<username>由团队提供</username>
<password>由团队提供或使用加密配置</password>
</server>
</servers>
</settings>不要把个人账号和密码写进项目 POM。
检查环境:
bash
java -version
mvn -version
mvn -DskipTests package本次实际构建在解析 hc-boot-starter:1.0.0-SNAPSHOT 时收到私服 401,因此没有完成编译。这不是 Java 源码编译错误,而是当前机器缺少有效的私服授权。
12.3 准备环境配置
至少确认以下配置由本地环境、Nacos 或发布平台提供:
text
spring.application.name
spring.database.host
spring.database.port
spring.database.username
spring.database.password
spring.redis.host
spring.redis.port
spring.elasticsearch.rest.*
XXL-Job 执行器配置
OSS 租户配置
内部 SDK/Feign 地址和认证配置还要确认依赖的租户中心、项目中心和流程中心在当前环境可访问。
12.4 启动方式
私服、数据库和中间件准备完成后,可从根目录尝试:
bash
mvn -pl hc-hire-center-service -am spring-boot:run也可以在 IDEA 中运行:
text
com.hc.hire.HireApplication启动类启用了:
text
@SpringBootApplication
@EnableScheduling
@EnableHcFeign
@EnableAsync
@EnableDiscoveryClient
@ComponentScan("com.hc")默认服务端口是 7007。看到“招聘中心启动成功”只说明 Spring 容器完成启动,不代表数据库、ES、Redis、Feign 和 XXL-Job 的全部业务链路都已经验证。
13. 如何调接口
src/main/resources/http 下有一组 IntelliJ HTTP Client 文件,覆盖:
- 候选人邮箱;
- 外部推送;
- 候选人附件;
- 候选人跟进与操作;
- 浏览器插件;
- 人才库和我的候选人;
- 报告;
- 简历导入;
- 第三方 API 策略框架。
这些是手工调试样例,不是自动化测试。使用前要:
- 替换环境地址;
- 使用开发环境的认证信息;
- 补齐网关要求的租户和用户上下文;
- 避免把真实手机号、简历和 Token 提交到仓库;
- 核对 URL 是否还需要网关前缀。
当前项目没有 src/test 下的自动化测试。修改核心状态流转、权限或同步逻辑时,不能只依赖这些 .http 文件,至少应补充 Service 单元测试或集成测试。
14. 新增一个功能时的标准落点
假设要给候选人增加一个可编辑字段,建议按下面顺序检查:
- 数据库:新增有序、幂等的 SQL 迁移,确认类型、默认值、索引和注释。
- Entity:更新对应
Hire*实体。 - Form:在新增/编辑请求对象中增加字段和校验注解。
- VO/DTO:确认列表、详情、导出或跨服务对象是否需要该字段。
- Converter:检查 MapStruct 映射,尤其项目普遍配置了
unmappedTargetPolicy = IGNORE,漏映射不会总是编译失败。 - Service:把业务规则、权限和事务写在 ServiceImpl,不放进 Controller。
- Mapper/查询:确认 Wrapper、联表查询和 XML 是否需要选择该字段。
- Elasticsearch:如果字段参与搜索,更新 Document、Converter、索引 mapping、查询和全量同步。
- 版本快照:候选人编辑是否要生成版本记录、支持比较和回滚。
- 数据权限:是否受创建人、保护人、供应商或职位角色约束。
- 接口样例和测试:更新
.http,并为核心规则补自动化测试。 - 发布清单:写明 SQL、配置、索引重建、任务和回滚步骤。
15. 复杂度热点
下面这些文件行数大、依赖多或处于关键一致性边界,新人第一次改动前应先画出调用链:
| 文件 | 约行数 | 为什么复杂 |
|---|---|---|
position/service/impl/PositionServiceImpl.java | 891 | 职位主流程、多个子表、权限和外部项目数据编排 |
candidate/service/impl/CandidateManualServiceImpl.java | 841 | 候选人主表和大量简历子表的创建、编辑与替换 |
candidate/service/impl/ResumeImportServiceImpl.java | 732 | 多种导入来源、解析、查重、附件和失败处理 |
position/service/impl/PositionRecoServiceImpl.java | 728 | 职位下候选人加入、推荐、批量动作和任务 |
position/service/impl/PositionPersonServiceImpl.java | 701 | 多角色参与人、权限和转移规则 |
candidate/service/impl/CandidateRecommendServiceImpl.java | 603 | 推荐资格、重复推荐、职位和候选人联动 |
position/service/impl/PositionApplyServiceImpl.java | 567 | 本地申请状态与外部流程中心状态一致性 |
candidate/service/CandidateSyncService.java | 501 | PostgreSQL、ES、失败补偿和事务提交边界 |
reco/service/impl/RecoFollowBusinessServiceImpl.java | 412 | 一个状态动作可能写入多类业务明细 |
position/service/impl/PositionDataPermissionServiceImpl.java | 392 | 管理员、职位角色、项目角色和供应商角色组合权限 |
修改这些文件时优先使用以下办法降低风险:
- 从 Controller 或任务入口反向确定真实调用者;
- 搜索接口和实现的全部引用;
- 列出事务内外的数据库、ES、OSS 和远程调用;
- 明确失败后的补偿或回滚策略;
- 对状态和权限建立表驱动测试;
- 避免在已有大类中继续堆叠无关职责。
16. 常见问题排查
16.1 Maven 一开始就报 Non-resolvable parent POM 或 401
原因通常不是代码,而是没有正确配置 hcjt 私服凭证、账号无权限或公司网络不可达。先解决 settings.xml 和仓库访问,再看编译错误。
16.2 spring.application.name 显示成 @artifactId@
这是 Maven resource filtering 占位符。确认从 Maven 构建后的资源启动,或确认 IDE 已执行 Maven 资源过滤。不要把错误的应用名注册到服务发现。
16.3 启动时报数据库或 Redis 占位符无法解析
本地 YAML 依赖环境配置。确认 Nacos 加载、环境变量和启动 profile,而不是在源码中硬编码生产连接信息。
16.4 接口总是提示未登录、无租户或无权限
请求没有经过正确网关,或没有建立 UserContext、TenantContextHolder。也可能是当前用户不在数据权限服务计算出的可见范围内。
16.5 Swagger 页面没有接口
先检查 Swagger base-package 是否覆盖实际的三个业务 Controller 包,再检查内部 @WebClientRestController 是否被 Swagger 配置识别。
16.6 数据库有数据,但列表搜索不到
候选人和推荐列表可能走 Elasticsearch。检查:
- PostgreSQL 事务是否成功;
- 增量同步是否触发;
hire_candidate_es_sync_fail是否有失败记录;- XXL-Job 补偿任务是否启用;
- ES 索引和 mapping 是否与 Document 一致;
- 当前租户和数据权限过滤条件。
16.7 修改状态后出现“不允许流转”
不要直接改数据库状态。检查当前阶段、目标阶段、前进/回退/停留方向,以及 CandidateFollowConstant 和 RecoFollowStateServiceImpl 的映射。
17. 推荐的新手阅读路线
第 1 阶段:先看项目怎么启动
text
pom.xml
hc-hire-center-service/pom.xml
HireApplication.java
application.yml
nacos-application.yml目标:知道项目依赖什么、配置从哪里来、为什么不能脱离公司环境直接运行。
第 2 阶段:跟一条最典型的 CRUD 加业务规则链路
text
CandidateManualController
CandidateManualService
CandidateManualServiceImpl
HireCandidateConverter
HireCandidate
HireCandidateMapper目标:分清 Form、Entity、VO、Converter、Service 和 Mapper。
第 3 阶段:理解横切规则
text
CandidateLifecycleServiceImpl
CandidateDataPermissionServiceImpl
PositionDataPermissionServiceImpl
CommonFileStorageServiceImpl目标:理解租户、用户、数据权限、版本、完整度和 OSS。
第 4 阶段:理解搜索一致性
text
CandidateDocument
CandidateDocumentConverter
CandidateSearchService
CandidateSyncService
CandidateEsSyncFailServiceImpl
EsSyncCompensateTask目标:知道 PostgreSQL 和 Elasticsearch 各自负责什么,以及失败如何补偿。
第 5 阶段:理解核心业务状态机
text
HireFollowStageEnum
HireFollowActionEnum
CandidateFollowConstant
RecoFollowStateServiceImpl
RecoFollowBusinessServiceImpl目标:能够判断一次跟进动作是否合法、会更新哪些数据。
第 6 阶段:理解跨服务边界
text
PositionProjectGatewayService
DefaultPositionProjectGatewayServiceImpl
PositionApplyApprovalGatewayService
DefaultPositionApplyApprovalGatewayServiceImpl
ExternalSupplierGatewayService目标:知道招聘中心拥有的数据和外部中心拥有的数据分别是什么。
18. 接手第一个需求前的检查清单
- [ ] Maven 私服依赖能够完整解析。
- [ ] 明确当前环境的 Nacos、数据库、Redis、ES、XXL-Job 和 OSS 配置来源。
- [ ] 获得完整基线数据库及 SQL 执行规则。
- [ ] 知道请求如何经过网关并建立用户、租户上下文。
- [ ] 能从一个 Controller 跟到 ServiceImpl、Mapper 和 Entity。
- [ ] 能说明目标接口是否查询 ES。
- [ ] 能说明目标操作是否需要数据权限校验。
- [ ] 能说明目标操作是否涉及远程服务、OSS 或异步任务。
- [ ] 核对状态枚举和流转表,避免散落魔法数字。
- [ ] 为修改准备自动化测试或至少可重复的验证步骤。
- [ ] 发布说明包含 SQL、配置、索引、任务和回滚方案。
19. 当前项目值得优先补齐的工程基础
从新手可上手性和变更安全性看,以下事项优先级较高:
- 在仓库根目录补正式
README.md,说明私服、配置中心、依赖服务和启动方式。 - 给
hc-hire-center-api明确定位:补充公共契约,或在暂不使用时说明原因。 - 增加
src/test自动化测试,优先覆盖推荐状态机、候选人查重、数据权限和 ES 补偿。 - 建立完整、可追踪的数据库迁移机制,而不是只保留零散 SQL。
- 清理源码中的明文敏感配置并完成密钥轮换。
- 合并
application.yml中重复的spring节点,并校验 Swagger 扫描包。 - 为超过 500 行的核心 Service 逐步提取领域服务和外部适配器。
- 补充本地开发环境或容器化依赖说明,降低对口头交接的依赖。
完成前 5 个阅读阶段后,再接一个影响范围小、无需状态流转和跨服务一致性的查询类需求,会比直接修改 PositionServiceImpl 或推荐状态机稳妥得多。
