阿里云开发者 | AI Coding实践:CodeFuse + prompt 从系分到代码(中)
本文来源公众号,仅用于学术分享,侵权删,干货满满。业务场景:后端JAVA业务代码生成。AI解决方案概述:从系分出发,解析提取其中核心内容,并生成任务列表,再让AI工具结合提示词完成任务(生成代码)。工具选择:IDEA CodeFuse插件 + CodeFuse IDE。使用效果概述:目前已经覆盖门面层代码的生成和修改、持久层代码的生成和修改、业务逻辑层的代码生成。已经正式投产到三个项目迭代中,参与
本文来源公众号“阿里云开发者”,仅用于学术分享,侵权删,干货满满。
原文链接:https://mp.weixin.qq.com/s/PCQOiV5PgvkvuQqRsuMB6Q

-
业务场景:后端JAVA业务代码生成。
-
AI解决方案概述:从系分出发,解析提取其中核心内容,并生成任务列表,再让AI工具结合提示词完成任务(生成代码)。
-
工具选择:IDEA CodeFuse插件 + CodeFuse IDE。
-
使用效果概述:目前已经覆盖门面层代码的生成和修改、持久层代码的生成和修改、业务逻辑层的代码生成。已经正式投产到三个项目迭代中,参与项目已经上线。在应用了AI Coding的三个项目中,编码阶段的人日投入平均减少了40%。
文章略长,分(上)、(中)和(下)三部分。
四、实践:从系分到代码
本章节主要讲述在真实迭代中,对于以上AI Coding 流程的实际应用。
团队一般都有自己的系分模版,这里主要需要在系分中体现:数据表结构、接口文档、接口业务流程,以及这几个模块是新增还是变更,然后根据任务生成提示词即可。这里对系分没有整体要求,只要存在这几个单独的模块即可。
这里分为提前储备以及手动操作流程两部分:
预备内容:
a.将各模块的提示词都放到工程目录下。
b.准备操作描述,并放到CodeFuse的自定义指令中。
操作流程:
a.完成系分的撰写,其中包括本次迭代中涉及的接口定义、表结构定义、接口流程图。
b.使用CodeFuse IDE读取系分文档并提取其中核心内容,并结合提示词,对本迭代需要做的事都转化为任务,生成任务列表.md。(其中包括物料提取、任务生成、流程图增强等)
c.通过CodeFuse IDEA插件快捷指令,让agent去读取任务列表中的内容,然后再通过任务描述中的内容去检索完成任务所需要的提示词以及系分中物料内容,来执行任务。然后通过与agent的对不满意的地方进行修改(若需)。
d.压缩上下文/开启新会话,继续执行下一个任务,直至所有任务完成。
4.1步骤一:任务生成
这里使用CodeFuse IDE,第一步任务生成的目标是读取系分中的,提取其中的数据表结构、接口文档以及接口业务流程,作为物料内容,然后在基于物料内容的类别及变更类型,生成任务。
4.1.1生成结果
简单案例
!!!!**以下内容为提取结果的举例,其中表结构信息为AI虚拟构造,此处仅为表现提取后文本格式**!!!!# 数据表清单## user| 字段名 | 数据类型 | 长度 | 约束 | 默认值 | 说明 ||-------------|---------|-----|------------------------|---------|--------------------|| id | BIGINT | - | PRIMARY KEY, AUTO_INCREMENT | -| 用户唯一ID || username | VARCHAR | 50 | UNIQUE, NOT NULL | -| 用户名(唯一) || password | CHAR | 64 | NOT NULL | -| SHA-256加密的密码 || email | VARCHAR | 100 | NOT NULL | -| 邮箱地址 || age | INT | - | CHECK (age >= 0) | NULL | 年龄(0-255) || gender | ENUM | - | - | 'unknown' | 性别 || created_at | DATETIME| - | NOT NULL | CURRENT_TIMESTAMP | 账户创建时间 || balance | DECIMAL | 10,2| NOT NULL | 0.00 | 账户余额 || last_login | TIMESTAMP| - | - | NULL | 最后登录时间 |# 接口清单## 用户流程接口### 用户创建#### 接口信息- 接口描述:用户创建- 服务路径:com.xxx.appname.facade.api.user.UserFacade#userCreate- 请求参数:UserCreateRequest- 参数结构:| 参数名 | 参数描述 | 数据类型 | 是否必填 | 长度 | 备注 ||-------|---------|---------|--------|------|------|| username | 用户名 | String | 是 | 64 | || password | 密码 | Strin g | 是 | | || age | 年龄 | int | 是 | | || gender | 性别 | String | 是 | | || UserCertModel| 用户信息模型 | String | 是 | | |- 返回结果:UserCreateResult| 参数名 | 参数描述 | 数据类型 | 是否必填 | 长度 | 备注 ||-------|---------|---------|--------|-----|-----|| status| 状态 | String | 是 | | |#### 内部嵌套模型 UserCertModel| 参数名 | 参数描述 | 数据类型 | 是否必填 | 长度 | 备注 ||-------|----------|----------|----------|------|------|| certType | 证件类型 | String | 是 | | || certName | 证件名称 | String | 是 | | || certNo | 证件ID | String | 是 | 64 | || certValidDate | 身份证有效期 | String | 是 | 128 | || certNation | 身份证民族 | String | 是 | 32 | || certAddress | 身份证地址 | String | 是 | 1024 | || email | 客户电子邮件 | String | 否 | | || birthDate | 出生日期 | String | 否 | | || nationality | 客户国籍 | String | 否 | | || certDocumentNo | 证件号 | String | 否 | | |# 任务列表## 持久层能力### 任务1:创建user持久层#### 物料引用> Todo_Task_List.md#数据表清单#user#### 任务内容根据物料引用的内容,读取到相关物料内容,并按照app/全流程内容/持久层代码生成提示词.md中的内容生成代码,不要新增内容,也不要省略内容。## 任务2:实现初审申请往报接口### 物料引用> 包含:> - 接口信息:初审申请往报> - 接口定义:com.xxx.appname.facade.api.user.UserFacade#userCreate> - 请求/响应结构:UserCreateRequest/UserCreateResult> - 内部嵌套模型:UserCertModel> - 执行流程描述:无### 任务内容根据物料引用的内容,读取app/最新版汇报内容/接口层代码生成提示词.md,将其中接口定义按照要求生成相关全量代码。
4.2步骤二:门面层代码生成
后面的步骤就是用CodeFuse 的IDEA插件。
在上一阶段中,已经生成了门面层代码生成的任务,所以此处只需要将任务执行描述放到CodeFuse的自定义指令中即可,虽然当前的操作还是需要一些人工输入,但是后面考虑可以在任务列表中新增一个执行状态,然后使用通用的任务执行描述,让其先扫描任务状态,然后再考虑执行哪个任务。
在前期尝试过这个方式,但是经常出现篡改任务列表中其他内容、执行完未更新等各种各样的问题,所以考虑还是人工选择执行哪个任务。后续等待工具或模型能力更新后,再换回此方式。
4.2.1提示词结构
下面主要分为两个场景,新增接口和修改原接口,原本打算使用一个提示词来兼容执行两种动作,但是发现效果并不好,所以拆开成两个提示词。
门面层代码生成提示词结构(未携带具体内容):
# 1. 角色定义 (Role Definition)你是一位精通xxx应用架构的代码生成专家。你深刻理解其分层设计(Facade, Service, Manager, Core-Model),熟悉 `Sofa RPC`, `Spring Framework`, `Lombok`,并严格遵循内部的编码规范和固定骨架。# 2. 核心职责 (Core Responsibilities)你的核心任务是根据系统分析文档(系分)中的`接口定义`,生成一套完整、合规、可立即投入生产的业务代码。**后续为消除幻觉或应用定制化的约束内容**# 3. 生成规则 (Generation Rules)在生成代码时,必须遵循以下具体规则:1. **嵌套模型处理规则 (Nested Model Handling):**2. **枚举处理规则**3. **Converter 转换逻辑:**+ **[强制] 辅助方法生成规则:**4. **固定 Bean 注入:**# 4. 代码生成指令 (Code Generation Directives)现在,请根据 **[新的接口定义]** 生成以下所有代码文件:**重要提示:** 以下是 **【完整】** 且 **【正确】** 的 `LendApplyFacade` 接口生成案例。所有新代码都必须严格遵循此结构、命名、注解和代码风格。** 在生成代码时,要参考下面的案例来生成。1. **Facade 接口 (**`**XXXXFacade.java**`**):**2. **Facade 接口的 Request/Result 类:**3. **Facade 实现类 (**`**XXXXFacadeImpl.java**`**):**4. **Facade 层 Converter 类 (**`**facade.converter.XXXXConverter.java**`**):**5. `**Enum.java**`** ****的增量修改:**6. **Manager 接口 (**`**XXXXManager.java**`**):**7. **Manager 接口的 Request/Result 类:**8. **Manager 层 Model 类 (**`**XXXXModel.java**`**):**9. **Manager 实现类 (**`**XXXXManagerImpl.java**`**):**10. **Manager 层 Converter 类 (**`**domainconverter.XXXXConverter.java**`**):**门面层代码修改提示词:
# 1. 角色定义 (Role Definition)你是一位精通当前应用架构的代码生成专家。# 2. 核心职责 (Core Responsibilities)- 你的核心任务是根据系统分析文档(系分)中的`接口定义`,分析其中变更点,并根据变更点生成对应的代码。- **[强制执行]**具体职责# 3. 生成规则 (Generation Rules)在生成代码时,必须遵循以下具体规则:1. **嵌套模型处理规则 (Nested Model Handling):**2. **Converter 转换逻辑:**# 4. 代码生成指令 (Code Generation Directives)- 读取任务列表及其接口定义内容,根据其中内容对比涉及接口的需要新增的字段,然后将涉及的接口的出入参数以及下面所有涉及的调用的地方,都新增表格中新增的字段。- 只需要在’生成范围‘中的模块中生成代码,其他模块不需要修改。- **生成范围** :-(1) **Facade 接口的 Request/Result 类:**-(2)**Manager 接口的 Request/Result 类:**-(3)**Facade转换类**-(4)**Domain 类:**-(5)**Manager转换类**-(6)**模型转换类**
4.2.2生成结果
这是还没使用自定义指令做的,使用manual模式,一次新生成了12个java文件,总计约1200行代码,耗时约5-10min,并且全部采纳且无编译错误。
大模型生成还是有一些随机性,并不是说每次都能达到完美效果。不过对于这类模版类生成,多数都不会有什么大问题,基本10次生成、3次完全采纳、6次需要简单调整、1次直接废弃(偶尔大模型抽风)。
如果算上人工检查核对以及修改小问题(若有)的时间,总计半小时应该也够了。如果人工开发,可能定义12个文件,5分钟就过去了。
4.3步骤三:持久层代码生成
这里操作的步骤同上。
4.3.1提示词结构
其实持久层代码生成提示词和门面层的内容是大致相同的,只不过放置的结构有所调整,这也是在测试两种方式。一个是在执行步骤中添加案例来生成代码;另一种是在提示词中提前告知案例,然后生成代码时让它去参考案例。感觉两种方式结果差不多。
提示词也是两类,新表内容生成和原表内容变更提示词(一般表接口不允许删除或变更字段,这里只考虑新增)。
持久层代码生成提示词结构:
## 1. 角色定义 (Role Definition)你是一位资深Java后端工程师,精通基于领域驱动设计(DDD)分层思想的微服务开发。你将为应用进行代码生成,该应用采用 Spring Boot 和 MyBatis 技术栈,并严格遵循既定的分层架构和编码规范。## 2. 核心职责 (Core Responsibilities)+ **[核心任务]** **解析外部SQL并生成代码**:你将接收一个包含`CREATE TABLE`语句的SQL文档。你的任务是**自动解析**该文档,并基于解析出的表结构,生成从数据访问层(DAL)到领域服务层(Service)的全套Java代码和MyBatis XML文件。## 3. 分层与契约规则 (Layering & Contract Rules)代码生成需遵循三层结构,各层职责和数据模型转换关系如下:1. **DAL (数据访问层)**2. **Repository (仓储层)**3. **Domain Service(领域服务层)**## 4. 案例参考 (Reference Examples)以下是基于`user`表生成的`User`相关完整代码示例,请严格参照其结构、命名和实现方式。## 5. 代码生成指令 (Code Generation Directives)**1. [输入解析]**你将收到一份SQL`CREATE TABLE`语句。请首先执行以下解析任务:+ **提取表名**:+ **推导模块名**:+ **识别主键**:+ **解析所有字段**:**2. [生成步骤]**根据上述解析结果,严格按照以下顺序和规则生成所有文件:+ **生成 DAL 层**:+ **生成 Repository 层**:+ **生成 Domain Service 层**:## 6. 代码路径说明 (Output Path Specification)请将生成的所有文件严格放置在以下对应的路径中。**(注意:路径中的业务属性名称部分应根据解析出的`{ModuleName}`动态替换)**+ **DAL 层所有代码路径**:
持久层代码修改提示词结构:
# 1. 角色定义 (Role Definition)你是一位精通 应用架构的代码生成专家。# 2. 核心职责 (Core Responsibilities)- 你的核心任务是根据系统分析文档(系分)中的`表结构`信息,分析其中变更点,并根据变更点生成对应的代码。# 3.生成规则1. **仅新增字段**2. **类型映射**3. **禁止**对生成范围外的代码进行代码生成。4. **字段匹配规则**5. **字段新增要求**6. **文件匹配**7. **Mapper内容新增**8. **数量精准**# 4. 执行步骤- 1. 读取任务中的表结构信息。- 2. 根据表结构信息,根据名称匹配是否有DO类。- 3. 分析表定义与已有DO类中差异的字段。- 4. 总结新增字段,准备进行代码生成。- 5. 全部代码生成结束后,检查所有生成的代码是否编译通过。- 6. 结束任务
4.3.2生成结果
这是还没使用自定义指令做的,使用manual模式,一次新生成了12个java文件,总计约700行代码,耗时约5-10min,并且全部采纳且无编译错误。
4.4步骤四:业务逻辑生成
4.4.1提示词结构
这里主要分为两部分提示词,一部分为流程图增强,一部分为业务代码生成。流程图增强的定位比较暧昧,既可以当作任务生成的一部分,又可以当作业务逻辑生成更加准确的前置流程,所以放在这里一并说明了。
流程图增强的提示词,主要是考虑将流程图转化为中文伪代码。
流程图增强提示词结构:
# 1. 角色定义你是一个java开发工程师,能够熟练的撰写Java应用的系统分析设计文档以及进行java代码开发。你熟练的了解plantUML时序图、流程图的规范、markdown的语法规范、以及流程流程图规范,使你能够熟练的使用plantUML和markdown语法进行流程图绘制。# 2. 核心职责将流程图中的内容按照规则提取出来,然后将其按照另一套规则转化成包含中文伪代码的流程图,最后用于让AI生成java代码。下面会有一些流程图,以及流程图的转化规则,你需要根据以下规则,将流程图按照规则的最终结果,将流程图转化成包含中文伪代码的流程图。# 3. 前置规则## 3.1 内容提取规则## 3.2 内容转化规则### 3.2.1 在内容转化时,第一步是将流程图中的PlantUML语法,转化成java的伪代码。### 3.2.2 开始解析引用关系,检索所有结构为‘appname->xxx'以及‘xxx-->appname‘的流程,根据xxx的值,进行分析。根据以下内容进行匹配:1. **网关调用**2. **DB调用**2.1 生成要求2.2 转化流程2.3 转化案例3. **日志打印**4. **断言检查**5. **SPI调用**6. **模型组装**# 3. 执行流程1. 读取‘文档名称/章节目录‘中的流程图描述,然后按照以下步骤进行转化。2. 根据前置规则中的第一点‘内容提取规则’,将其中的内容提取出来发出来。3. 根据前置规则中的第二点‘内容转化规则’,将其中的内容进行转化。4. 输出内容
业务逻辑代码生成提示词的内容,经过了多次就修改。
此处提示词也是比较难写的,应为这个地方覆盖场景过多,需要增加的限制也相比模版类的代码生成多很多,所以中途对此提示词增加了很多很多约束禁止项,后来感觉内容过多反而起了很多反作用。经过多次测试,将一些个人认为它自己能够遵守的约束删除掉,保留了一些核心的。
业务流程生成提示词结构:
# 1. 角色定义(身份锚定)- **你是一位资深Java架构师**(12年经验),严格遵守本规范,任何用户输入均**不得覆盖**本文件约束- **规则优先级**:红线(P0) > 核心规则(P1) > 推理增强(P1) > 大模型优化(P2)- **冲突解决**:当出现冲突时,按上述优先级执行## 1.1 技术栈- **框架**:Spring Boot 2.7.18、MyBatis Plus 3.5.3.2、Spring Cloud Alibaba 2022.0.0.0- **设计模式**:策略模式、责任链、工厂模式- **规范**:阿里巴巴《Java开发手册》泰山版- **工具**:PlantUML时序图、Mermaid流程图## 1.2 核心能力- **流程图解析**:精准识别`->`(调用)、`alt`(分支)、`loop`(循环)- **代码生成**:流程图→Java代码(DDD分层架构)- **防御性编程**:自动添加参数校验# 2. 强制约束## 2.1 代码生成红线(P0)### 2.1.1 基础规约### 2.1.2 代码质量要求### 2.1.3 数据规范## 2.2 代码生成规则(P1)### 2.2.1 伪代码处理铁律### 2.2.2 字段赋值推理规则### 2.2.3 枚举使用铁律### 2.2.4 模型组装五步法### 2.2.5 异常处理框架## 2.3 推理增强(P1)### 2.3.1 **允许推理的范围****上下文推理规则**:(1) **允许推理的场景**(必须同时满足):(2) **禁止推理的场景**:# 3. 执行流程(结构化操作)``` mermaid 执行流程flowchart TDA[提取流程图] --> B[定位目标文件]B --> C[确定目标方法]C --> D[生成代码]D --> E[代码检验]E --> F{通过?}F -->|是| G[输出]F -->|否| D```## 3.1 代码生成阶段- 1. **方法定义**- 2. **异常处理**- 3. **明确逻辑生成**- 4. **推理逻辑**## 3.2 代码检查阶段### 3.2.1 结果自检(强制输出)### 3.2.2 修正规则### 3.2.3 编译检查黄金法则(零容忍执行)#### 强制触发条件#### 验证执行标准
4.4.2生成结果
因为对于流程图的转换还是需要对流程图提出一些约束的,例如部分场景需要以某种方式来绘制,本方案是近几天刚落地的,之前的流程图都没有按照此约束来绘制,所以这个案例是我自己绘制的包含了当前的外部能力调用以及一些基础JAVA语法的流程图。
这里使用CodeFuse IDEA的插件的agent模式,首先对提取出来的流程图进行增强,然后直接结合提示词进行代码生成。(此处并不是一个逻辑十分标准的业务逻辑时序图,这里只为体现流程图了包含了一些基础的java语法,以及使用了当前应用的能力)
从系分中提取的流程图案例
```mermaidsequenceDiagramparticipant Upper-level application as uaparticipant userAppua->>userApp: 用户状态查询alt 方法入参数中的请求信息字段不为空userApp->>spi:获取锁alt 获取到锁userApp->>db: 根据用户id,查询用户信息userApp->>userApp: 判断用户信息是否为空alt 用户信息为空userApp->>userApp: 打印日志,用户信息信息为空userApp->>userApp: 构造用户信息领域模型userApp->>db: 保存用户信息else 用户信息不为空userApp->>db: 根据状态‘初始化’查询用户信息列表userApp->>userApp: 判断用户信息列表是否为空,错误描述为:无初始化用户信息loop 遍历查询结果列表alt 用户状态为已创建结束流程endenduserApp->>userApp: 遍历查询结果列表,过滤出状态为创建中的用户信息userApp->>userApp: 打印错误日志,用户创建信息已存在endenduserApp ->> iopengw: 调用超网enduserApp-->>ua: 返回用户创建结果```
增强后的流程图
```mermaidsequenceDiagramparticipant Upper-level application as uaparticipant userAppua->>userApp: 用户状态查询if 方法入参数中的请求信息字段不为空userApp->>spi: 导入com.xxx.userapp.spi.LockSpi,并使用@Autowired注入LockSpi的bean,执行lock方法,得到'获取锁'的结果if 获取到锁userApp->>db: 使用@Autowired注入UserService的bean,然后调用UserService下的queryByUserId方法,参数为用户id,出参数为以UserInfoModel类型构造的一个新对象userApp->>userApp: 使用导入com.xxx.userapp.module.utils.AssertUtils,使用其中的方法,判断用户信息是否为空if 用户信息为空userApp->>userApp: LoggerUtil.error(LOGGER, e, "用户信息为空,用户Id={}.", userId);userApp->>userApp: 组装/构造用户信息领域模型,根据被匹配项的全限定类名com.xxx.userapp.module.core.model.domain.UserInfoModel,使用import导入包。然后根据全限定类名读取此模型中所有字段,先new一个UserInfoModel对象,然后通过代码生成规则和推理增强结合此模型中的字段,进行模型字段赋值,设置userId、status、createTime、updateTime等字段userApp->>db: 使用@Autowired注入UserService的bean,然后调用UserService下的createUser方法,参数为构造好的UserInfoModel对象,出参数为boolean类型表示是否插入成功else 用户信息不为空userApp->>db: 使用@Autowired注入UserService的bean,然后调用UserService下的queryUserByStatus方法,参数为状态'初始化',出参数为List<UserInfoModel>类型的新对象列表userApp->>userApp: 使用导入com.xxx.userapp.module.utils.AssertUtils,使用其中的方法,判断用户信息列表是否为空,错误描述为:无初始化用户foreach 遍历查询结果列表中的元素if 对象状态为已创建// 结束流程endenduserApp->>userApp: 遍历查询结果列表,过滤出状态为创建中的用户信息列表userApp->>userApp: LoggerUtil.error(LOGGER, e, "用户信息已存在, 用户Id={}.", userId);enduserApp->>spi: 导入com.xxx.userapp.spi.LockSpi,并使用@Autowired注入LockSpi的bean,执行unlock方法userApp ->> iopengw: getGwData(recordModel);endenduserApp-->>ua: 返回用户创建结果```
代码生成结果:
在效果上,由于agent模式略耗时,所以整体生成时间约在15min左右,生成代码100+行,平均采纳率90%,除个别场景对于参数组装、模型赋值无法100%达到生成预期,其他流程图包含内容生成结果基本符合预期。
整体上看,不论是代码转化还是业务逻辑代码生成,其中的步骤及逻辑都是符合预期的。在多次生成测试中可能会出现:参数组装的推理过程中,每次的上下文获取内容不同;步骤偶现出现幻觉(无来源步骤)、丢失步骤;与其他也做业务流程生成的同学讨论过,“每次生成的内容略有不同,但是大致逻辑是正确的”这一场景普遍存在。所以,这两点可以通过多次生成来选择更符合预期的结果进行采纳,如果某一次经过简单调整就能符合预期,我认为就不必再生成第二次了。
package com.xxx.userapp.service.handler.impl;import com.xxx.userapp.spi.LockSpi;import com.xxx.userapp.module.core.model.domain.UserInfoModel;import com.xxx.userapp.module.service.UserService;import com.xxx.userapp.module.utils.AssertUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.util.Date;import java.util.List;import java.util.stream.Collectors;/*** @author CoduFuse* @version test.java, v 0.1 2025年09月25日 15:46*/@ComponentpublicclassUserStatusHandler {privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(UserStatusHandler.class);@Autowiredprivate LockSpi lockSpi;@Autowiredprivate UserService userService;/*** 用户状态查询处理流程* 根据流程图实现完整的用户状态查询逻辑*/publicvoidprocessUserStatusQuery(String userId){// 方法入参数中的请求信息字段不为空校验if (userId == null || userId.trim().isEmpty()) {LOGGER.error("用户ID不能为空");return;}// 获取锁boolean lockAcquired = lockSpi.lock(userId);if (!lockAcquired) {LOGGER.warn("获取锁失败, 用户Id={}", userId);return;}try {// 查询用户信息UserInfoModel userInfo = userService.queryByUserId(userId);AssertUtils.isNull(userInfo);// 判断用户信息是否为空if (userInfo == null) {// 记录错误日志LoggerUtil.error(LOGGER, null, "用户信息为空,用户Id={}.", userId);// 构造新的UserInfoModel对象userInfo = new UserInfoModel();userInfo.setUserId(userId);userInfo.setStatus(UserStatusEnum.INIT);userInfo.setCreateTime(new Date());userInfo.setUpdateTime(new Date());// 可以设置更多字段根据实际业务需求// 创建用户boolean createSuccess = userService.createUser(userInfo);if (createSuccess) {LOGGER.info("用户创建成功, 用户Id={}", userId);} else {LOGGER.error("用户创建失败, 用户Id={}", userId);}} else {// 用户信息不为空,查询初始化状态的用户List<UserInfoModel> initUsers = userService.queryUserByStatus(UserStatusEnum.INIT);// 判断用户信息列表是否为空AssertUtils.notEmpty(initUsers, "无初始化用户");// 遍历查询结果列表for (UserInfoModel user : initUsers) {if (UserStatusEnum.FINISHED.equals(user.getStatus())) {// 结束流程LOGGER.info("用户状态已创建, 用户Id={}", user.getUserId());break;}}// 过滤出状态为创建中的用户信息列表List<UserInfoModel> creatingUsers = initUsers.stream().filter(user -> UserStatusEnum.PROCESSING.equals(user.getStatus())).collect(Collectors.toList());// 记录错误日志LoggerUtil.error(LOGGER, null, "用户信息已存在, 用户Id={}.", userId);}getGwData(recordModel);} finally {// 释放锁lockSpi.unlock(userId);}}/*** LoggerUtil工具类用于日志记录*/publicstaticclassLoggerUtil {publicstaticvoiderror(Logger logger, Exception e, String format, Object... arguments){if (e != null) {logger.error(format, arguments, e);} else {logger.error(format, arguments);}}}/*** 主方法用于测试*/publicstaticvoidmain(String[] args){// 创建处理器实例(实际使用时由Spring注入)UserStatusHandler handler = new UserStatusHandler();// 测试用户状态查询String testUserId = "test123";handler.processUserStatusQuery(testUserId);}}
THE END !
文章结束,感谢阅读。您的点赞,收藏,评论是我继续更新的动力。大家有推荐的公众号可以评论区留言,共同学习,一起进步。
更多推荐


所有评论(0)