mcpField
D
dto-creator

dto-creator

github.com/amplicode开发134441 次安装7 周前更新
代码仓库

关于 dto-creator

dto-creator 是 Spring Agent Toolkit 中用于为实体生成 DTO 的技能,面向 Spring 项目开发者。它支持 Java 类、record、Lombok 和 Kotlin data class,并要求依据示例生成代码。

主要功能

  1. 01为实体创建 DTO
  2. 02支持 Java 类与 record
  3. 03支持 Lombok 和 Kotlin data class
  4. 04可配置字段、校验与关联 DTO
  5. 05需要 Spring MCP 工具及代码示例

适用场景

  1. 01为实体生成 API 数据传输对象
  2. 02选择实体字段并配置关联 DTO
  3. 03按项目语言和依赖确定 DTO 形式

MCP 相关

依赖 Amplicode IntelliJ 插件提供的 Spring MCP 服务,使用其项目摘要、依赖和实体信息工具。若工具不可用,技能要求先安装插件并连接 MCP。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/amplicode/spring-skills --skill dto-creator

安装后在 Claude Code 中输入/dto-creator确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/_fragments/constructor/java/
all-args.md
examples/_fragments/equals-hashcode/java/
equals-hashcode-hibernate.md
equals-hashcode.md
examples/_fragments/fields/
java-lombok.md
java-record.md
java.md
kotlin.md
examples/_fragments/fluent-setters/java/
fluent-setters.md
examples/_fragments/getters-setters/java/
getters.md
setters.md
examples/_fragments/javadoc/java/
javadoc.md
examples/_fragments/json-ignore/java/
json-ignore.md
examples/_fragments/lombok/
lombok.md
examples/_fragments/nested-class/java/
nested-class.md
examples/_fragments/nested-class/kotlin/
nested-class.md
examples/_fragments/serializable/java/
serializable.md
examples/_fragments/serializable/kotlin/
serializable.md
examples/_fragments/tostring/java/
tostring.md
examples/_skeletons/java/
class.md
record.md
examples/_skeletons/kotlin/
class.md
data-class.md
references/
java-lombok.md
java-plain.md
java-record.md
kotlin.md
sub-dto.md
validation.md

详细介绍

预检:Spring MCP

此技能属于 Spring Agent Toolkit,旨在与 Spring MCP 服务(由 Amplicode IntelliJ 插件提供)配合使用。在进行任何操作之前,请检查工具列表中是否有 Spring MCP 工具——这些工具通过 amplicode MCP 服务提供(例如,get_project_summary、list_module_dependencies、get_entity_details);将 MCP 工具扁平化到工具列表中的运行环境,会在相同名称前使用 mcp__amplicode__ 前缀。

  • 如果至少有一个 Amplicode 工具可用——MCP 已连接。继续执行以下技能。
  • 如果没有可用工具——停止并调用 amplicode-install 技能(随 Spring Agent Toolkit 一同提供)。它会安装 Amplicode 插件,并引导用户点击欢迎屏幕上的 «Настроить Spring Agent» 按钮,然后重启 MCP 客户端。完成后,MCP 工具即可使用——继续执行此技能。
  • 如果技能列表中未注册 amplicode-install,请用用户使用的语言告知用户:"此技能需要 Amplicode IntelliJ 插件及其 MCP 服务。请从 https://amplicode.ru/marketplace 将其安装到 IntelliJ IDEA Ultimate/Community 或 GigaIDE 中,打开任意项目,点击 Amplicode 欢迎屏幕上的 «Настроить Spring Agent»,然后重启 MCP 客户端。"

DTO 创建器

为实体创建 DTO 类(Java 类、Java record、Java+Lombok 或 Kotlin 数据类),可包含选定属性、构造函数、getter/setter、equals/hashCode、toString 及可选功能。


重要:只能使用 examples/ 文件中的代码。如果没有匹配的示例——停止并询问用户。 重要:对于有固定选项的问题,优先使用 AskUserQuestion > 其同类工具 > 纯文本列表。没有交互式工具时,纯编号文本列表才是最后的选择。 **重要:运行步骤 1 之前,先阅读对话上下文。**步骤 2–7 中有一半的问题可能已在用户提示和之前的对话中得到回答。重复询问已说明的内容,是此技能显得缓慢的首要原因。 **步骤 7(mapper)在需要转换时自动执行。**如果根据上下文可以确定 DTO 将用于把实体转换为 DTO 或从 DTO 转换回实体的代码中(如 controller、service、端点替换等),此技能必须委托给 mapper-creator——绝不能在代码中内联编写手动映射代码。mapper-creator 技能负责决定实现方式(MapStruct、Custom、添加依赖);此技能只需进行委托。


默认值

选项默认值总是询问?备注
entity--YES主要分支:要为哪个实体创建 DTO
attributes实体的所有字段YES要包含哪些字段
className{EntityName}DtoNO提出建议,仅需确认
language来自 get_project_summaryNO自动检测
variant根据语言和依赖自动确定YESJava 类 / Java record / Java+Lombok / Kotlin
mutablefalseNO除非用户想要自定义,否则跳过
allArgsConstructortrueNO仅适用于纯 Java
equalsHashCodetrueNO仅适用于纯 Java
toStringtrueNO仅适用于纯 Java
fluentSettersfalseNO仅当 mutable=true 时适用,仅适用于 Java
jsonIgnoreUnknownPropertiesfalseNO仅适用于 Java,且类路径中存在 Jackson 时
serializableTypeNoSerializableNO很少需要
packageName与实体相同的包NO自动检测
subDtoType(每个 ToOne 关联)带有仅含 id 的子项的 FLATYES提供四种选项:New Class / New Nested Class / Existing Class / Flat。“Only ID”并非单独的选项——它是只勾选子实体 id 的 Flat。参见 references/sub-dto.md。
subDtoType(每个 ToMany / 集合)NEW_NESTED_CLASSYES与 ToOne 相同的四种选项。集合也支持 Flat,并会生成复合复数形式字段,例如 Set<Integer> specialtyIds——参见 references/sub-dto.md。
fieldNameOverride(每个字段)无NO按字段重命名
extraValidations(每个字段)无NO用户添加的 jakarta 验证器,附加在继承的验证器之上
removedValidations(每个字段)无NO从实体继承、但用户希望移除的约束
indent来自 .editorconfig(回退为 4 个空格)NO参见下文 § 缩进

智能默认值: 如果用户说“使用默认值”“全部使用默认值”“默认设置” 或类似表述,则跳过所有“总是询问?”为 NO 的问题。仅询问必答问题。

智能答案识别: 当用户提供一个值而非从编号列表中选择时,直接接受该值。例如:

  • 问题“哪个实体?” -> 用户回答“Order” -> 这就是实体,无需再次询问
  • 问题“变体?” -> 用户回答“record” -> 这就是 Java record,无需显示选项
  • 如果用户在一条消息中提供多个答案 -> 全部接受,并跳过已回答的问题
  • 绝不询问用户已经回答过的问题(即使是隐含回答)

批量提问: 当以下条件成立时,将紧密相关的问题合并到一次 AskUserQuestion 调用中(每次最多 4 个问题):

  • 属于同一逻辑部分(例如,都是 Java 方法生成设置)
  • 彼此之间不依赖答案
  • 用户可以跳过,且有明显的默认值

规则:

  • 每次 AskUserQuestion 调用最多 3-4 个问题
  • 将推荐选项标记为“(推荐)”并置于首位
  • 绝不合并来自不同决策分支的问题
  • 主要分支问题(实体选择、变体)始终单独提问
  • 有选项时优先使用 AskUserQuestion;仅当该工具不可用时,才回退到纯文本列表

决策原则——先看上下文,再提问

在向用户提出任何问题之前,先尝试从已收集的上下文中推导答案:项目摘要、模块依赖、实体详情、软件包中的现有文件、本次对话的先前轮次,以及用户的原始提示。只有当上下文无法得出明确的默认选项,或选择确实取决于用户个人偏好时(例如选择哪个实体、哪些字段),才提问。

决策层级:

  1. 上下文明确无歧义 → 静默决定,切勿提问。 示例:从 get_project_summary 获取语言和 JDK;从 list_module_dependencies 获取 Lombok / Jackson / Hibernate Validator;根据实体 FQN 确定软件包;根据 {Entity}Dto 确定 className;过滤反向引用 @ManyToOne;自动选择子实体标量字段;当 JDK ≥ 16、没有 Lombok 且用户没有另行要求时,选择 record 而非普通类。 例外:绝不能静默决定 subDtoType——除非 USER 在自己的消息中明确说明了结构(而不是在 ARGUMENTS 中),否则至少必须遵循原则 2(单行确认)。

  2. 上下文有明显倾向 → 用一行说明决定和备选项,让用户选择更改或不作回应。 格式:

    Will create `ScheduleTemplateDto` as a Java record with nested `SlotDto` (record).
    Alternatives: plain class, Lombok, separate file for SlotDto. OK?
    

    用户可以回答“ok” / “yes”或不作回应 → 接受;也可以指定其他选项 → 切换。这不同于编号问题格式——它是一条单独的确认语句。

  3. 上下文无法得出明确的默认选项 → 使用 AskUserQuestion(首选)或其同类工具提问,并将推荐选项放在首位。 如果可以使用 AskUserQuestion,请使用带有 preview 字段的选项,让用户看到每个选项对应的具体代码结构。将推荐选项标记为 (Recommended),并放在首位。如果没有可用的交互式选择工具,则改用纯文本列表。 绝不要迭代式提问(“要哪种变体?”→ 用户选择 → “要哪些字段?”→ ……),只要一次批量调用就能解决的问题就不要拆开问。

  4. 关键输入的上下文完全为空 → 直接提问。 适用于:选择哪个实体、选择哪些字段(当不是“全部”时)、用户本身的意图。

如何提问——优先使用 AskUserQuestion

必须提问时,优先使用 AskUserQuestion 工具(或其同类工具),而不是在响应正文中编写编号列表。仅当没有可用的交互式选择工具时,才改用纯文本。

此技能中 AskUserQuestion 调用的规则:

  • 每次调用最多可包含 4 个彼此独立的问题(工具会将它们一并显示)。利用这一点,在一次往返中批量处理相关决策。
  • 每个问题有 2–4 个选项。工具会自动添加一个供自由输入的“Other”选项——切勿手动添加。
  • 将推荐选项放在首位,并在标签末尾添加 (Recommended)。
  • 对“要包含哪些字段”或“要添加哪些验证器”等允许多个答案的问题,使用 multiSelect: true。
  • header 是一个 12-char 的标签(例如“Variant”“Sub-DTO”“Fields”)。
  • 每个选项都应有一条说明,解释该选项的含义或后果(用一个简短句子)。

以下情况不应使用 AskUserQuestion:

  • 没有可枚举选项的自由输入(例如任意类名、任意字段重命名)——使用纯文本提问。
  • 原则 2 中的“单行确认”形式——这是一个有明确是/否答案的问题,不是枚举选项。

下面步骤 2–5 中基于界面的提问列表仅适用于情况 4,是一种后备方案,并非必须从头到尾执行的脚本。如果某个问题的答案已由原则 1–3 确定,就跳过该问题。忠实还原插件向导并非目标;确保生成正确才是目标。插件的 UI 能一次显示许多控件,而聊天界面做不到,因此此技能必须通过自行做出更多决定来弥补。


步骤 0 —— 优先查看对话上下文(必需,不调用工具)

在进行任何 MCP 调用、提出任何问题之前,重新阅读用户的提示和本次对话的先前消息,并提取其中已经说明的内容。此步骤无需耗费任何成本,却能避免此技能最常见的失败模式——询问用户已经提供过的信息。

在心中列出输入检查清单,并勾选用户已经明确或隐含提供的所有内容:

输入在提示 / 上下文中查找
实体类名(Vet、Owner、ScheduleTemplate);“用于 X”;IDE 中打开的文件;文件路径;本次对话中最近讨论的实体
用途“用于 REST”“用于 controller”“用于 API”“用于映射”“投影”“用于 service”——这会影响字段选择和是否询问映射器
字段“所有字段”“仅 id 和 name”“不含密码”“包含关联”“扁平”
变体“record”“普通类”“Lombok”“data class”——也可由语言隐含:Kotlin → data class,无需提问
映射器“还要映射器”“带映射器”“仅 DTO”“不要映射器”
className“命名为 OwnerSummaryDto”“类 Foo”
package“放在 … 包中”“放在 controller 旁边”
智能默认值“使用默认值”“全部使用默认设置”“默认设置”“照常”
子 DTO 结构“嵌套”“单独的类”“仅 id”“扁平”
项目先前信息语言、JDK、依赖——如果本次对话中已经讨论过,就已知;无需重新获取

对于每个已明确或强烈隐含回答的输入:标记为已确定,并跳过步骤 2–7 中对应的问题。如果用户写了“为 Vet 创建 DTO”,就不要问“什么实体?”——答案是 Vet。如果用户写了“创建 record DtoX”,就不要问“Java record 还是 class?”——答案是 record。

对于每个尚未回答的输入:遵循下方的决策原则——先尝试从项目上下文中推断(步骤 1),然后再提问。

重要:参数 ≠ 用户意图。 提示底部的 ARGUMENTS 区块由调用助手编写,不是用户提供的内容。它可能包含助手自身的分析、假设或用户从未说明的字段级细节。判断用户“已经说过什么”时,只查看对话记录中的实际用户消息——绝不能把 ARGUMENTS 当作用户输入的替代品。特别是,不要仅仅因为 ARGUMENTS 描述了子 DTO 的结构,就跳过关于子 DTO 结构的问题。

步骤 0 是在心中完成的,不是工具调用。不要向用户宣布此步骤。不要写“步骤 0 已完成”。开始步骤 1 之前,只需在心中牢记用户已经提供的信息。


步骤 1 —— 收集最少的项目上下文(自动执行,不提问)

仅调用其结果会被后续步骤实际使用的 MCP 工具。不要“以防万一”而提前获取数据——这里的每个变量都必须有明确的下游用途。

工具变量用途
get_project_summarylanguage、jdkVersion、moduleNamelanguage → 选择变体(步骤 4)和参考文件(java 或 kotlin);jdkVersion → canUseRecords = jdkVersion >= 16;moduleName → 消除多模块歧义 + 作为 list_module_dependencies 的参数
list_module_dependencies(moduleName)presentDeps派生下方的标志——Lombok/Jackson/Validation 功能门控

步骤 1 到此为止。不要获取:

  • springBootVersion / bootMajor —— 没有分支逻辑依赖它们
  • buildFile —— DTO 生成不会修改构建文件(无需添加依赖);DTO 只需要语言构造
  • mainPackage —— DTO 的包名从实体的 FQN 派生,而不是从项目根目录派生
  • list_application_properties_files / propsFile —— DTO 不会写入 application.properties
  • list_all_domain_entities —— 仅当用户未在提示词中指定实体时才需要。作为惰性回退,延后到步骤 2。
  • get_entity_details / list_entity_dtos —— 需要先知道实体,而这会在步骤 2 中确定。延后到步骤 2。

派生变量(均来自 presentDeps 和 get_project_summary):

  • hasLombok = presentDeps 包含 lombok
  • hasJackson = presentDeps 包含 jackson-databind 或 jackson-core
  • hasValidation = presentDeps 包含 hibernate-validator、jakarta.validation-api 或 spring-boot-starter-validation
  • canUseRecords = language == JAVA 且 jdkVersion >= 16

如果是多模块项目(get_project_summary 中有多个模块): 询问要使用哪个模块。然后针对该模块重新调用 list_module_dependencies。


步骤 2 —— 选择实体

到步骤 0 时,你应该已经知道实体(如果用户提到了它)。 最常见的情况:用户写道“为 Vet 创建 DTO” → 实体为 Vet,跳过提问,直接进行下面的并行获取。

**惰性回退——仅当实体未知时:**调用 list_all_domain_entities(moduleName) → entities,然后通过 AskUserQuestion 提问(选项 = 列表中的实体名称,最多 4 个;如果实体超过 4 个,根据上下文选择最可能的 4 个,并注明用户可通过“Other”输入其他名称)。

这是唯一应调用 list_all_domain_entities 的地方。如果用户在提示词中指定了实体,不要调用它。

确定实体 FQN 后,并行调用:

工具变量用途
get_entity_details(entityFqn)entityDetails步骤 3 的属性选择、关联分析、验证继承,以及每个变体参考中的生成顺序

此处不调用父实体的 list_entity_dtos(entityFqn)——它没有下游用途。子实体调用(list_entity_dtos(subEntityFqn))仍用于在 references/sub-dto.md 中检测 EXIST_CLASS,但属于惰性调用,按关联逐项执行,且仅在向用户提供 EXIST_CLASS 选项时触发。具体位置请参见 references/sub-dto.md。

DTO 名称冲突通过另一个惰性调用处理——list_existing_classes(package)——在步骤 6 的生成前立即触发(参见防幻觉检查清单)。它不属于步骤 2。


步骤 3 —— 选择属性

默认:包含每个标量属性和每个关联(采用 references/sub-dto.md 中的子 DTO 默认设置)。仅当上下文表明用户想要更精简的内容时才提问。

根据上下文做出决定(优先于提问)

使用第 0 步中记录的用途来选择合理的默认字段集:

用途信号默认字段集
“用于 REST”“用于 controller”“用于 API”所有标量字段 + 展开所有关联(ToMany 使用 NEW_NESTED_CLASS,ToOne 使用 FLAT id)——用户需要响应结构,包括关联数据
“投影”“摘要”“列表视图”“用于列表”仅标量字段,ToOne 关联使用 Flat id,排除 ToMany
“用于映射”“用于 service”“用于存储的 DTO”所有标量字段 + 展开所有关联
“仅 id 和 name” / 明确列出字段仅包含用户指定的字段,不包含其他字段
没有用途信号所有标量字段 + 展开所有关联(合理范围内最丰富的默认选项)

如果所选默认选项符合用户的明显意图,不要提问。 直接生成。最多只能使用一句式确认格式(原则 2)说明所做的选择。

何时提问

仅在以下情况下提问:

  • 用户明确表示“选择字段”/“询问字段”/“微调设置”,或
  • 实体有很多字段,且用途信号模糊,同时用户没有说“使用默认设置”。

提问时,使用 AskUserQuestion,并设置 multiSelect: true:

问题标题选项(第一项为推荐选项)
DTO {Entity}Dto 应包含哪些字段?字段所有字段 + 关联(推荐)/ 仅标量字段 / 仅 id 和 name / 手动指定

对每个包含的关联,应用 references/sub-dto.md 中的子 DTO 默认设置。除非用户明确要求精细控制,否则不要逐个关联提问。


第 4 步——选择变体

遵循上文的决策原则。通常可根据上下文推断变体——主动提问应是例外,而非常规做法。

**如果 language=KOTLIN:**转至 references/kotlin.md。不要提问。

**如果 language=JAVA:**按以下方式决定。

上下文操作变体
hasLombok = true 且用户的提示明确提到 Lombok静默决定references/java-lombok.md
canUseRecords = true 且 hasLombok = false,且用户没有要求可变性/setter/Lombok静默决定,并在原则 2 的一句式确认中说明references/java-record.md
canUseRecords = false 且 hasLombok = false静默决定references/java-plain.md
hasLombok = true 且 canUseRecords = true,且用户没有给出偏好使用原则 2 的一句式确认格式:“将创建为 Java record(JDK ≥ 16,不使用 Lombok)。其他选项:普通类、Lombok。可以吗?”取决于回答
用户明确说“普通类”/“可变”/“带 setter”静默决定references/java-plain.md
用户明确说“record”静默决定references/java-record.md
用户明确说“Lombok”静默决定(仅当 hasLombok = true;否则发出警告并使用备用方案)references/java-lombok.md

仅当以上各行均不匹配,且用户没有说“使用默认设置”时,才退回到完整编号问题。即便如此,也优先采用原则 3 中“标明默认选项的所有变体”格式,而不是迭代提问。

将回答映射到变体:

  • plain → references/java-plain.md
  • record → references/java-record.md
  • Lombok → references/java-lombok.md

第 5 步——特定变体的问题

遵循所选参考文件中的特定变体问题。 仅当用户没有说“全部使用默认设置”时才提问。

步骤 6 -- 生成代码

  1. 确定目标路径: src/main/{java|kotlin}/{packagePath}/{className}.{java|kt}

  2. 遵循所选参考文件中的 生成顺序。

  3. 对于每个步骤:

    如果是骨架(新文件):

    • 读取 examples/_skeletons/ 中的骨架 .md
    • 应用变量替换
    • 使用 Write 工具创建文件

    如果是片段:

    • 读取 examples/_fragments/ 中的片段 .md
    • 阅读插入点,了解应插入的位置
    • 使用 Edit 工具在指定位置插入代码
    • 应用变量替换
  4. 变量替换规则:

    • {packageName} -> 来自实体包或用户选择
    • {className} -> 来自用户或默认值 {EntityName}Dto
    • 字段级变量 -> 来自实体详情
    • 绝不替换 Variables 中未列出的内容
    • 绝不添加示例中没有的导入、方法或代码
    • FQN 处理(重要): 示例中包含 FQN(例如 java.util.Objects、 java.util.List、jakarta.validation.constraints.NotNull)。编写 最终文件时,必须:
      1. 将类主体中的每个 FQN 替换为其短名称 (例如,java.util.Objects.hash(...) -> Objects.hash(...), java.util.List<Integer> -> List<Integer>, @jakarta.validation.constraints.NotNull -> @NotNull)。
      2. 收集所有已缩短的 FQN,并在 package 语句之后为其添加对应的 import 行,按字母顺序排序,不得重复。
      3. java.lang 中的类型(String、Integer、Object 等)不得导入,且必须使用短名称。
      4. 与 DTO 位于同一包中的类不得导入。
      5. Javadoc {@link ...} 引用——统一处理: 对所有形式的实体引用,在 {@link …} 中生成短名称 + import:顶层 Java 类、顶层 Java record、嵌套静态类、嵌套 record,以及独立文件中的子 DTO(NEW_CLASS)。不得区别处理。始终缩短实体引用,并始终添加对应的 import 行(除非实体位于同一包中)。
      6. 对导入分组为两个代码块,中间隔一个空行:
        • 代码块 1 — 将所有第三方 / 项目导入放在一起: jakarta.*、com.fasterxml.*、org.springframework.*、 org.hibernate.*、项目包等(块内按字母顺序排列)。
        • (空行)
        • 代码块 2 — java.* 和 javax.*(按字母顺序排列)。 不要将代码块 1 按包拆分为多个子块。 最终文件的主体中必须使用短名称(包括每个 Javadoc {@link …}),且顶部必须包含整洁、分组的导入块。
  5. 对于子 DTO(subDtoType=NEW_CLASS):通过为子实体递归重复步骤 6.1-6.4,创建单独的文件。

  6. 对于嵌套类(subDtoType=NEW_NESTED_CLASS):在父 DTO 文件中添加内部类,然后按照相同的片段规则补全。

  7. 嵌套在 record 父类中 — 必须遵守: 当父 DTO 是 Java record 时,每个 NEW_NESTED_CLASS 关联都必须在父 record 的主体中生成为嵌套的 public record。技能不得仅仅因为 record 形式的片段看起来更短,就悄悄改用 NEW_CLASS(单独文件)。完整流程见 references/java-record.md 步骤 6,以及 examples/_fragments/nested-class/java/nested-class.md(“Java record” 变体)。如果这些说明看起来含糊不清,那是技能本身的问题——请修正文档,不要通过更改 subDtoType 来规避。

Step 7 -- Mapper(需要转换时自动执行)

根据上下文判断是否需要 Mapper,然后执行相应操作:

信号操作
用户说了“only DTO”/“no mapper”/“without mapper”完全跳过 Step 7。不要提及 Mapper。
用户明确要求创建 Mapper(“and mapper”、“with mapper”、“create mapper too”)立即委派给 mapper-creator。
从上下文可以明确看出会进行实体↔DTO 转换(例如,用户要求在控制器/服务/端点中用 DTO 替换实体,或要求转换/映射/变换,DTO 用于 REST API 等)立即委派给 mapper-creator。转换不可避免;不创建 Mapper 就会被迫编写手动内联映射代码,这是绝不允许的。
上下文没有明确说明 DTO 的用途跳过 Step 7。不要提及 Mapper。

重要: 绝不要编写手动映射代码(在控制器、服务或其他任何位置编写内联的 toDto/fromDto 方法)。如果需要转换,始终委派给 mapper-creator。该技能会决定实现策略(MapStruct、自定义 Mapper、添加依赖);此技能只负责委派。

绝不要因 Mapper 而调用 AskUserQuestion。如果需要委派,直接向 mapper-creator 技能提供 DTO 和实体信息—— 不要询问用户是否确认委派。


缩进

该技能 MUST 检测项目的缩进风格,绝不要硬编码制表符 或空格。检测顺序:

  1. 项目根目录中的 .editorconfig(或目标文件所在目录的任意上级目录中的文件)。对于 Java 文件,查找 [*.java] 或 [*] 部分,并读取 indent_style(tab 或 space)以及 indent_size / tab_width。
  2. 同一包中的现有 Java 文件样本(或包含 Java 文件的最近 上级包)。检测缩进行的前导空白使用的是 \t 还是空格,以及空格数量。
  3. 如果以上来源都无法得出明确结论,默认使用 4 个空格。(如果开发者明确偏好制表符,也可以默认使用制表符,但技能绝不能在没有说明的情况下擅自假定其中一种。)

无论选择哪种风格,都必须将其统一应用于每个生成代码片段的每一行(字段、构造函数、getter/setter、equals/hashCode、 toString、嵌套类/记录)。同一文件中绝不能混用制表符和空格。

按字段配置的选项

该技能必须支持以下按字段配置的选项:

  • 重命名字段(fieldNameOverride):DTO 字段名可以不同于 实体属性名。Mapper 仍会从原始属性映射。
  • 添加校验(extraValidations):用户可以在从实体继承的校验基础上,添加 jakarta/hibernate-validator 约束。允许的约束列表取决于字段类型——参见 references/validation.md。
  • 移除继承的校验(removedValidations):用户可以移除来自实体字段的任意约束。
  • 编辑注解参数(message、min、max、regexp 等):每个约束的所有参数都可以编辑。

除非用户明确要求“fine-tune field settings”、“per-field validation”或类似内容,否则绝不会出现这些选项。默认情况下,该技能只继承实体中的所有配置。

防幻觉检查清单

编写任何代码之前,请确认:

  • 代码来自某个 examples/ 文件(注明具体文件)
  • 仅替换了已声明的变量
  • 未凭“已有知识”添加任何框架 API 调用
  • 导入列表与示例完全一致
  • 方法签名与示例完全一致
  • 未添加注释或便捷方法
  • 示例中的 FQN 在正文中已缩写,且在 package 后添加了对应的 import 行
  • 所有 Javadoc 格式——顶层类、顶层 record、嵌套静态类、嵌套 record、单独文件中的子 DTO——均使用短名称 {@link Pet},并添加匹配的 import(除非实体位于同一包中)。规则统一,不得区别对待。
  • 如果子 DTO 名称(单独文件或嵌套类)与目标包中已有的类冲突,自动添加数字后缀(例如 PetDto1)。该技能也必须这样做——生成前调用 list_existing_classes(package),并依次追加 1、2……直到名称不冲突。
  • 生成 Java record 时,任何 NEW_NESTED_CLASS 关联的内部类也必须是 record(而非静态类)。所有组件验证注解都应内联到 record 组件参数上(例如 @NotBlank String firstName),而不是写在单独的字段声明上。
  • 当 isJavaRecord = true 时,该技能不得生成 equals()、hashCode()、toString()、可变 setter 或链式 setter——record 会自动生成这些内容,且 record DTO 不应提供这些选项。
  • 类级 Javadoc 必须是多行格式(/**\n * DTO for {@link …}\n */),不得压缩为单行。
  • Getter 和 setter 必须是多行格式(签名行、缩进的主体、结束花括号),不得写成单行。
  • 在 mutable=true && fluentSetters=false 模式下,getter 和 setter 必须交替排列(getX, setX, getY, setY, …),不得分组排列。
  • 在 mutable=true 模式下,必须同时生成无参构造函数和全参构造函数。
  • 该技能不得将“仅 ID”作为单独选项提供——此选项不存在(ToOne 和 ToMany 均如此)。“仅关联 ID”的效果应通过**选择 Flat,并且仅勾选子实体的 id**来实现;该技能必须采用这种方式。
  • 对于集合关联(List<X>、Set<X>),必须提供 Flat,并生成复合复数形式的字段(Set<Integer> specialtyIds、List<Integer> petIds),前提是该技能会自动勾选子实体的标量字段。
  • 从属性列表中过滤掉反向引用的 @ManyToOne 字段(例如,创建 PetDto 时不提供 Pet.owner)。
  • 导入项按 jakarta.* / com.* / org.* / java.* 分组,各组之间以空行分隔。
  • 缩进应遵循项目检测到的样式(优先检查 .editorconfig,其次参照同一包中的现有文件,最后默认使用 4 个空格)。不得将制表符或空格写死。文件中的每个代码片段都必须统一应用该样式。
  • Kotlin 不得添加 @JsonIgnoreProperties(仅适用于 Java)
  • Kotlin 中的验证注解使用 @field: 前缀
  • Kotlin DTO 中的 Java 类型必须转换为 Kotlin 类型

评论

支持 Markdown