crud-rest-controller

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Preflight: Spring MCP

前置检查:Spring MCP

This skill is part of the Spring Agent Toolkit and is designed to work with the Spring MCP server (provided by the Amplicode IntelliJ plugin). Before doing anything else, check your tool list for any Spring MCP tool — they are exposed under the
amplicode
MCP server (e.g.
get_project_summary
,
list_module_dependencies
,
get_entity_details
); harnesses that flatten MCP tools into the tool list use the
mcp__amplicode__
prefix on the same names.
  • If at least one Amplicode tool is available — MCP is connected. Proceed with the skill below.
  • If none are available — stop and invoke the
    amplicode-install
    skill (bundled with the Spring Agent Toolkit). It installs the Amplicode plugin and walks the user through the «Настроить Spring Agent» welcome-screen button + MCP-client restart. After it completes, the MCP tools become available — resume this skill.
  • If
    amplicode-install
    is not registered in your skill list, tell the user (in their language): "This skill needs the Amplicode IntelliJ plugin and its MCP server. Install it from https://amplicode.ru/marketplace into IntelliJ IDEA Ultimate/Community or GigaIDE, open any project, click «Настроить Spring Agent» on the Amplicode welcome screen, then restart your MCP client."

此技能是Spring Agent Toolkit的一部分,旨在与Spring MCP server(由Amplicode IntelliJ插件提供)配合使用。在进行任何操作之前,请检查你的工具列表中是否有Spring MCP工具——它们在
amplicode
MCP服务器下暴露(例如
get_project_summary
list_module_dependencies
get_entity_details
);将MCP工具扁平化到工具列表的工具会在相同名称前添加
mcp__amplicode__
前缀。
  • 如果至少有一个Amplicode工具可用——MCP已连接。继续使用下方的技能。
  • 如果没有可用的Amplicode工具——停止操作并调用**
    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客户端。"

CRUD REST Controller

CRUD REST控制器

Generates a
@RestController
class with standard CRUD endpoints for an entity, using a Spring Data repository, optional DTO mapping, pagination, filtering, and patch support.

CRITICAL: Code ONLY from examples/ files. If no matching example -- STOP and ask user. CRITICAL: For questions with a fixed set of choices, prefer
AskUserQuestion
> its analogue > plain text list. Plain numbered text lists are the last resort when no interactive tool is available.
CRITICAL: Read the conversation context BEFORE running Step 1. Half the questions in Steps 2–4 may already be answered by the user's prompt and prior turns. Re-asking what was already said is the #1 reason this skill feels slow.

生成一个
@RestController
类,为实体提供标准CRUD接口,使用Spring Data仓库、可选的DTO映射、分页、过滤和补丁支持。

重要提示:仅从examples/文件中生成代码。如果没有匹配的示例——停止操作并询问用户。 重要提示:对于有固定选项的问题,优先使用
AskUserQuestion
工具 > 类似工具 > 纯文本列表。只有在没有交互式工具可用时,才将纯编号文本列表作为最后手段。
重要提示:在运行步骤1之前,请阅读对话上下文。步骤2-4中的一半问题可能已经由用户的提示和之前的对话回合回答过。重复询问已回答的问题是此技能显得缓慢的首要原因。

Defaults

默认设置

The options below are grouped by topic.
language
and
bootVersion
are auto-detected; all other options are resolved via the Decision-making principle (derive from context → confirm → ask).
以下选项按主题分组。
language
bootVersion
会自动检测;所有其他选项通过决策原则解决(从上下文推导 → 确认 → 询问)。

Block 1 — Entity & repository

模块1 — 实体与仓库

OptionDefaultNotes
entity--which entity to create controller for
repositoryfirst existing for entitywhich repository to use
选项默认值说明
entity--要为其创建控制器的实体
repository实体对应的第一个现有仓库使用哪个仓库

Block 2 — DTO mode

模块2 — DTO模式

OptionDefaultNotes
DTO modeDTO (recommended)if no existing DTO for entity, delegate to
dto-creator
; user can opt out to use entity directly
选项默认值说明
DTO模式DTO(推荐)如果实体没有现有DTO,委托给
dto-creator
技能;用户可以选择直接使用实体

Block 3 — Controller naming & paths

模块3 — 控制器命名与路径

OptionDefaultNotes
controllerName
{EntityName}Controller
suggest based on project naming convention
controllerPackagesame as existing controllers or mainPackageauto-detected from project
basePath
/rest
persistent base path
resourcePath
/{pluralizedEntityName}
auto from entity name
选项默认值说明
controllerName
{EntityName}Controller
根据项目命名约定建议
controllerPackage与现有控制器相同或主包从项目中自动检测
basePath
/rest
持久化基础路径
resourcePath
/{pluralizedEntityName}
从实体名称自动生成

Block 4 — Pagination & filtering

模块4 — 分页与过滤

OptionDefaultNotes
paginationtrueenable pagination for GET_LIST
paginationTypePAGEPAGE or WINDOW (WINDOW requires filter to be selected; avoids count query overhead)
filterNoneJPA Specification filter for GET_LIST
选项默认值说明
paginationtrue为GET_LIST启用分页
paginationTypePAGEPAGE或WINDOW(WINDOW需要选择过滤器;避免计数查询开销)
filterNone用于GET_LIST的JPA Specification过滤器

Auto-detected (no questions)

自动检测(无需询问)

OptionSource
patchStrategyObjectMapper
language
get_project_summary
bootVersion
get_project_summary
Smart defaults: If user says "use defaults", "all defaults", "default settings", or similar -- skip ALL questions where "Always ask?" = NO. Only ask mandatory questions.
Smart answer recognition: When user provides a value instead of choosing from a numbered list, accept it directly. Examples:
  • Question "Which entity?" --> user answers "Product" --> this IS the entity, don't re-ask
  • Question "Repository?" --> user answers "ProductRepository" --> this IS the choice
  • If user provides multiple answers in one message --> accept all, skip answered questions
  • NEVER ask a question that the user already answered (even implicitly)
Batch questions: When multiple questions must be asked (i.e. cannot be resolved by principles 1–2 of the Decision-making principle), group them into a single
AskUserQuestion
call (up to 4 questions per call) when they:
  • Belong to the same logical section
  • Don't depend on each other's answers
Rules:
  • Maximum 3-4 questions per
    AskUserQuestion
    call
  • Mark the recommended option with
    (Recommended)
    and place it first
  • Never batch questions from DIFFERENT decision branches
  • The primary branching question (entity selection) is always asked ALONE
  • Prefer
    AskUserQuestion
    for choices; fall back to plain text lists only if the tool is unavailable

选项来源
patchStrategyObjectMapper
language
get_project_summary
bootVersion
get_project_summary
智能默认值: 如果用户说"使用默认值"、"全部默认"、"默认设置"或类似表述——跳过所有"是否始终询问?"为NO的问题。仅询问必填问题。
智能答案识别: 当用户提供一个值而不是从编号列表中选择时,直接接受该值。示例:
  • 问题"选择哪个实体?" → 用户回答"Product" → 这就是实体,不要再询问
  • 问题"选择哪个仓库?" → 用户回答"ProductRepository" → 这就是选择项
  • 如果用户在一条消息中提供多个答案 → 全部接受,跳过已回答的问题
  • 永远不要询问用户已经回答过的问题(即使是隐含回答)
批量问题: 当必须询问多个问题(即无法通过决策原则1-2解决)时,将它们分组到一个
AskUserQuestion
调用中(每次调用最多4个问题),前提是:
  • 属于同一逻辑部分
  • 彼此的答案不依赖
规则:
  • 每次
    AskUserQuestion
    调用最多包含3-4个问题
  • (推荐)
    标记推荐选项,并将其放在首位
  • 永远不要批量处理不同决策分支的问题
  • 主要分支问题(实体选择)始终单独询问
  • 优先使用
    AskUserQuestion
    进行选择;只有在工具不可用时才回退到纯文本列表

Decision-making principle — context first, then ask

决策原则 — 优先上下文,再询问

Before asking the user any question, attempt to derive the answer from the context already gathered: project summary, module dependencies, entity details, existing files in the package, prior turns of this conversation, and the user's original prompt. Only ask when the context yields no clear default or when the choice is genuinely user-specific (e.g. which entity, which repository).
Hierarchy of decisions:
  1. Context is unambiguous → decide silently, do NOT ask. Examples: language and JDK from
    get_project_summary
    ; repository when there is exactly one for the entity; controller package from existing controllers; basePath from existing endpoints; Jackson version from
    list_module_dependencies
    ; pagination type when project already uses one consistently.
  2. Context gives a strong signal → state the decision + alternatives in one line, let the user override or stay silent. Format:
    Will create `ProductController` at `/rest/products` with Page pagination, no DTO.
    Alternatives: use DTO, Window pagination, custom paths. OK?
    The user can answer "ok" / "yes" / silence → accept; or name an alternative → switch. This is not the same as the numbered question format — it is a single confirmation line.
  3. Context yields no clear default → ask with
    AskUserQuestion
    (preferred) or its analogue, with the recommended option first.
    When
    AskUserQuestion
    is available, use it with the recommended option marked
    (Recommended)
    and placed first. If no interactive choice tool is available, fall back to a plain text list. Never ask iteratively ("which entity?" → user picks → "repository?" → …) when one batched call would do.
  4. Context is fully empty for a critical input → ask plainly. This applies to: which entity (when not mentioned), the user's intent itself.
在向用户询问任何问题之前,尝试从已收集的上下文(项目摘要、模块依赖、实体详情、包中的现有文件、本次对话的先前回合以及用户的原始提示)中推导答案。只有当上下文没有明确默认值或选择确实由用户决定(例如选择哪个实体、哪个仓库)时,才进行询问。
决策层级:
  1. 上下文明确 → 静默决定,不询问。 示例:来自
    get_project_summary
    的语言和JDK;实体只有一个仓库时的仓库选择;从现有控制器获取的控制器包;从现有端点获取的basePath;从
    list_module_dependencies
    获取的Jackson版本;项目已一致使用的分页类型。
  2. 上下文给出强烈信号 → 陈述决定 + 替代方案,让用户覆盖或保持沉默。 格式:
    将创建`ProductController`,路径为`/rest/products`,使用Page分页,不使用DTO。
    替代方案:使用DTO、Window分页、自定义路径。是否确认?
    用户可以回答"ok" / "yes" / 保持沉默 → 接受;或指定替代方案 → 切换。这与编号问题格式不同——它是单行确认语句。
  3. 上下文没有明确默认值 → 使用
    AskUserQuestion
    (优先)或类似工具询问,推荐选项放在首位。
    AskUserQuestion
    可用时,使用该工具,推荐选项标记为
    (推荐)
    并放在首位。如果没有交互式选择工具可用,回退到纯文本列表。 永远不要在一次批量调用可以完成的情况下迭代询问("哪个实体?" → 用户选择 → "哪个仓库?" → …)
  4. 关键输入的上下文完全为空 → 直接询问。 适用于:未提及的实体选择、用户本身的意图。

How to ask — prefer
AskUserQuestion

询问方式 — 优先使用
AskUserQuestion

When a question must be asked, prefer the
AskUserQuestion
tool (or its analogue) over writing a numbered list in the response body. Fall back to plain text only if no interactive choice tool is available.
Rules for
AskUserQuestion
calls in this skill:
  • Each call may contain up to 4 questions that are independent of each other (the tool will render them together). Use this to batch related decisions in one round-trip.
  • Each question has 2–4 options. The tool auto-adds an "Other" choice for free-form input — never include it manually.
  • Mark the recommended option by putting it first with
    (Recommended)
    appended to the label.
  • header
    is a 12-char chip label (e.g. "Entity", "DTO mode", "Paths").
  • Each option has a
    description
    explaining what the choice means.
When
AskUserQuestion
is not the right tool:
  • Free-form input where there is no enumerable set of options (e.g. arbitrary class name, arbitrary path) — ask in plain text.
  • The "single confirmation line" form from principle 2 — that is a plain question with an obvious yes/no, not an enumerated choice.
The screen-driven question lists in Steps 2–4 below are a fallback for case 4. They are NOT a script to execute top-to-bottom. If a question's answer is already determined by principles 1–3, skip the question.

当必须询问问题时,优先使用**
AskUserQuestion
**工具(或类似工具),而不是在响应正文中编写编号列表。只有在没有交互式选择工具可用时才回退到纯文本。
此技能中
AskUserQuestion
调用的规则:
  • 每次调用可包含最多4个相互独立的问题(工具会将它们一起呈现)。用此将相关决策批量处理在一次往返中。
  • 每个问题有2-4个选项。工具会自动添加"其他"选项用于自由输入——不要手动添加。
  • 通过将推荐选项放在首位并在标签后附加
    (推荐)
    来标记它。
  • header
    是12字符以内的标签(例如"实体"、"DTO模式"、"路径")。
  • 每个选项都有
    description
    解释选择的含义。
AskUserQuestion
不是合适工具的情况:
  • 没有可枚举选项的自由输入(例如任意类名、任意路径)→ 用纯文本询问。
  • 原则2中的"单行确认语句"形式——这是带有明显是/否的简单问题,不是枚举选择。
以下步骤2-4中的屏幕驱动问题列表是回退方案,适用于情况4。它们不是从上到下执行的脚本。如果问题的答案已通过原则1-3确定,跳过该问题

Step 0 -- Conversation context first (REQUIRED, no tool calls)

步骤0 -- 先查看对话上下文(必填,无需调用工具)

Before any MCP call, before any question, re-read the user's prompt and the prior turns of this conversation and extract whatever is already stated. This step costs nothing and prevents the most common failure mode of this skill — asking the user something they already said.
Build a mental checklist of inputs and tick off everything the user has already provided, explicitly or implicitly:
InputLook for in the prompt / context
entitya class name (
Product
,
Order
,
Vet
); "for X"; an open file in the IDE; a file path; a recently discussed entity in this conversation
repository"use
ProductRepository
", "with
OrderRepo
"; or implied — if only one repository exists for the entity
DTO mode"with DTO", "without DTO", "use entity directly", "map to
ProductDto
"
controller name"name it
ProductResource
", "class
FooController
"
paths"at
/api/products
", "base path
/rest
", "resource path
/items
"
pagination"with pagination", "no pagination", "use Window", "use Page"
filter"with filter", "no filter", "use JPA Specification"
methods"all CRUD", "only read", "read-only", "without delete", "GET + CREATE", "full CRUD"
smart defaults"use defaults", "all defaults", "default settings", "as usual"
prior project factslanguage, JDK, dependencies — already known if discussed earlier in this conversation; do not re-fetch
For every input that is explicitly or strongly implicitly answered: mark it as decided and skip the corresponding question in Steps 2–4. Do NOT ask "which entity?" if the user wrote "create CRUD controller for Product" —
Product
is the answer. Do NOT ask "which repository?" if there is exactly one repository for the entity.
For every input that is not answered: defer to the Decision-making principle above — try to derive it from project context first (Step 1), and only then ask.
Step 0 is mental, not a tool call. Do not announce it to the user. Do not write "Step 0 done". Just internalize what the user already said before proceeding to Step 1.

在调用任何MCP工具、询问任何问题之前,重新阅读用户的提示和本次对话的先前回合,提取已陈述的所有信息。此步骤没有成本,可避免此技能最常见的失败模式——询问用户已经说过的内容。
构建输入清单,勾选用户已明确或隐含提供的所有内容:
输入在提示/上下文中查找
entity类名(
Product
Order
Vet
);"为X创建";IDE中打开的文件;文件路径;本次对话中最近讨论的实体
repository"使用
ProductRepository
"、"搭配
OrderRepo
";或隐含——如果实体只有一个仓库
DTO mode"使用DTO"、"不使用DTO"、"直接使用实体"、"映射到
ProductDto
"
controller name"命名为
ProductResource
"、"类
FooController
"
paths"路径为
/api/products
"、"基础路径
/rest
"、"资源路径
/items
"
pagination"带分页"、"无分页"、"使用Window"、"使用Page"
filter"带过滤器"、"无过滤器"、"使用JPA Specification"
methods"完整CRUD"、"仅只读"、"只读"、"不带删除"、"GET + CREATE"、"全CRUD"
smart defaults"使用默认值"、"全部默认"、"默认设置"、"照常"
prior project facts语言、JDK、依赖——如果在本次对话之前讨论过则已了解;不要重新获取
对于每个明确或强烈隐含回答的输入:标记为已决定,跳过步骤2-4中对应的问题。如果用户写了"为Product创建CRUD控制器",不要询问"哪个实体?"——
Product
就是答案。如果实体只有一个仓库,不要询问"哪个仓库?"。
对于每个未回答的输入:遵循上述决策原则——先尝试从项目上下文推导(步骤1),然后再询问。
步骤0是心理步骤,不是工具调用。不要向用户宣布。不要写"步骤0完成"。只需在继续步骤1之前内化用户已经说过的内容。

Step 1 -- Gather minimal project context (automatic, no questions)

步骤1 -- 收集最少的项目上下文(自动,无需询问)

Call only the MCP tools whose result is actually consumed by a later step. Do not pre-fetch "in case we need it" — every variable here must have a concrete downstream user.
ToolVariableUsed for
get_project_summary
language
,
bootMajor
,
moduleName
,
buildFile
,
mainPackage
language → reference file selection (java vs kotlin); bootMajor → jakarta vs javax, Jackson version; moduleName → multi-module disambiguation; buildFile → Step 6 dependency injection; mainPackage → controller package fallback
list_module_dependencies(moduleName)
presentDeps
derived flags below — SpringDoc/Validation/Jackson feature gates, Step 6 dependency check
list_project_endpoints
endpoints
Step 4 path conflict detection, existing basePath/naming convention detection
That is the entire Step 1. Do NOT fetch:
  • list_all_domain_entities
    — needed only if the user did not name an entity in their prompt. Defer to Step 2 as a lazy fallback.
  • list_entity_repositories
    — depends on knowing the entity, which happens in Step 2. Defer to Step 3 as a lazy fallback.
  • get_entity_details
    — depends on knowing the entity. Defer to Step 2.
  • list_entity_dtos
    /
    list_entity_mappers
    — depend on knowing the entity AND the DTO decision. Defer to Step 4.
After calling
get_project_summary
, determine:
  • language
    : Java or Kotlin
  • bootMajor
    : 2, 3 or 4 (for jakarta vs javax, Jackson version)
  • Check if
    org.springdoc:springdoc-openapi
    is in
    presentDeps
    -->
    hasSpringDoc
  • Check if
    org.hibernate.validator:hibernate-validator
    or
    org.springframework.boot:spring-boot-starter-validation
    is in
    presentDeps
    -->
    hasValidation
  • Jackson version detection: Check
    presentDeps
    for
    tools.jackson:jackson-databind
    or
    tools.jackson:jackson-core
    -->
    jacksonMajor = 3
    . Otherwise if
    com.fasterxml.jackson:jackson-databind
    -->
    jacksonMajor = 2
    . Spring Boot 4.x uses Jackson 3.x (
    tools.jackson
    package), Spring Boot 2.x/3.x use Jackson 2.x (
    com.fasterxml.jackson
    package).
    • If
      jacksonMajor = 3
      :
      JsonNodeFqn
      =
      tools.jackson.databind.JsonNode
      ,
      ObjectMapperFqn
      =
      tools.jackson.databind.ObjectMapper
    • If
      jacksonMajor = 2
      :
      JsonNodeFqn
      =
      com.fasterxml.jackson.databind.JsonNode
      ,
      ObjectMapperFqn
      =
      com.fasterxml.jackson.databind.ObjectMapper
  • PagedModel detection:
    PagedModel
    (
    org.springframework.data.web.PagedModel
    ) is available in Spring Data 3.2+. If
    bootMajor >= 3
    (Spring Boot 3.2+) or
    bootMajor = 4
    , use
    PagedModel
    wrapper for GET_LIST with Page pagination. Otherwise return
    Page<Entity>
    directly.
If multi-module project (multiple modules in
get_project_summary
): Ask which module to use. Then re-call module-specific MCP tools with that module.

仅调用结果会在后续步骤中实际使用的MCP工具。不要提前获取"以防需要"——此处的每个变量必须有明确的下游用途。
工具变量用途
get_project_summary
language
,
bootMajor
,
moduleName
,
buildFile
,
mainPackage
language → 参考文件选择(java vs kotlin);bootMajor → jakarta vs javax、Jackson版本;moduleName → 多模块区分;buildFile → 步骤6依赖注入;mainPackage → 控制器包回退
list_module_dependencies(moduleName)
presentDeps
派生以下标志——SpringDoc/Validation/Jackson功能开关,步骤6依赖检查
list_project_endpoints
endpoints
步骤4路径冲突检测、现有basePath/命名约定检测
这就是步骤1的全部内容。不要获取:
  • list_all_domain_entities
    ——仅当用户在提示中未指定实体时才需要。推迟到步骤2作为惰性回退。
  • list_entity_repositories
    ——依赖于实体的确定,这发生在步骤2。推迟到步骤3作为惰性回退。
  • get_entity_details
    ——依赖于实体的确定。推迟到步骤2。
  • list_entity_dtos
    /
    list_entity_mappers
    ——依赖于实体的确定和DTO决策。推迟到步骤4。
调用
get_project_summary
后,确定:
  • language
    : Java或Kotlin
  • bootMajor
    : 2、3或4(用于区分jakarta vs javax、Jackson版本)
  • 检查
    presentDeps
    中是否有
    org.springdoc:springdoc-openapi
    hasSpringDoc
  • 检查
    presentDeps
    中是否有
    org.hibernate.validator:hibernate-validator
    org.springframework.boot:spring-boot-starter-validation
    hasValidation
  • Jackson版本检测: 检查
    presentDeps
    中是否有
    tools.jackson:jackson-databind
    tools.jackson:jackson-core
    jacksonMajor = 3
    。否则如果有
    com.fasterxml.jackson:jackson-databind
    jacksonMajor = 2
    。Spring Boot 4.x使用Jackson 3.x(
    tools.jackson
    包),Spring Boot 2.x/3.x使用Jackson 2.x(
    com.fasterxml.jackson
    包)。
    • 如果
      jacksonMajor = 3
      :
      JsonNodeFqn
      =
      tools.jackson.databind.JsonNode
      ,
      ObjectMapperFqn
      =
      tools.jackson.databind.ObjectMapper
    • 如果
      jacksonMajor = 2
      :
      JsonNodeFqn
      =
      com.fasterxml.jackson.databind.JsonNode
      ,
      ObjectMapperFqn
      =
      com.fasterxml.jackson.databind.ObjectMapper
  • PagedModel检测:
    PagedModel
    org.springframework.data.web.PagedModel
    )在Spring Data 3.2+中可用。如果
    bootMajor >= 3
    (Spring Boot 3.2+)或
    bootMajor = 4
    ,对使用Page分页的GET_LIST使用
    PagedModel
    包装器。否则直接返回
    Page<Entity>
如果是多模块项目(
get_project_summary
中有多个模块):询问使用哪个模块。然后使用该模块重新调用特定模块的MCP工具。

Step 2 -- Select entity

步骤2 -- 选择实体

By Step 0 you should already know the entity if the user mentioned it. Most common case: the user wrote "create CRUD controller for Product" → entity is
Product
, skip the question, go straight to the fetch below.
Lazy fallback — only when entity is unknown: call
list_all_domain_entities(moduleName)
entities
, then ask via
AskUserQuestion
(options = entity names from the list, max 4; if more than 4 entities, use the 4 most likely candidates based on context and add a note that the user can type a different name via "Other").
This is the only place
list_all_domain_entities
should be called. If the user named the entity in their prompt, do NOT call it.
After the entity FQN is known, call
get_entity_details(entityFqn)
to get:
  • IdType
    -- entity ID field type (e.g.
    java.lang.Long
    ,
    java.util.UUID
    )
  • entityVar
    -- decapitalized entity name (e.g.
    product
    )
  • entityVarPlural
    -- pluralized decapitalized name (e.g.
    products
    )
  • EntityName
    -- simple class name (e.g.
    Product
    )
  • EntityNamePlural
    -- pluralized simple name (e.g.
    Products
    )
  • Whether entity has validation annotations -->
    entityHasValidation

通过步骤0,如果用户提到了实体,你应该已经知道它。最常见的情况:用户写了"为Product创建CRUD控制器" → 实体是
Product
,跳过问题,直接进行下方的获取操作。
惰性回退 — 仅当实体未知时: 调用
list_all_domain_entities(moduleName)
entities
,然后通过
AskUserQuestion
询问(选项 = 列表中的实体名称,最多4个;如果实体超过4个,根据上下文选择4个最可能的候选者,并添加注释说明用户可以通过"其他"输入不同名称)。
这是唯一应该调用
list_all_domain_entities
的地方。如果用户在提示中指定了实体,不要调用它。
确定实体FQN后,调用
get_entity_details(entityFqn)
获取:
  • IdType
    -- 实体ID字段类型(例如
    java.lang.Long
    java.util.UUID
  • entityVar
    -- 小写开头的实体名称(例如
    product
  • entityVarPlural
    -- 小写开头的复数名称(例如
    products
  • EntityName
    -- 简单类名(例如
    Product
  • EntityNamePlural
    -- 复数化的简单名称(例如
    Products
  • 实体是否有验证注解 →
    entityHasValidation

Step 3 -- Select repository

步骤3 -- 选择仓库

By Step 0 you may already know the repository if the user mentioned it.
Call
list_entity_repositories(entityFqn)
repos
. Then apply the Decision-making principle:
  • If exactly one repository exists → select it silently (principle 1).
  • If the user named a specific repository → use it directly, skip the question.
  • If multiple repositories exist → ask via
    AskUserQuestion
    with the options from
    repos
    .
  • If no repository exists → inform the user and suggest creating one manually or using a separate skill.
After selection:
  • repoFieldName
    -- decapitalized repository class name (e.g.
    productRepository
    )
  • RepoFqn
    -- FQN of repository class

通过步骤0,如果用户提到了仓库,你可能已经知道它。
调用
list_entity_repositories(entityFqn)
repos
。然后应用决策原则:
  • 如果只有一个仓库存在 → 静默选择它(原则1)。
  • 如果用户指定了特定仓库 → 直接使用它,跳过问题。
  • 如果有多个仓库存在 → 通过
    AskUserQuestion
    询问,选项来自
    repos
  • 如果没有仓库存在 → 告知用户,并建议手动创建或使用单独的技能。
选择后:
  • repoFieldName
    -- 小写开头的仓库类名(例如
    productRepository
  • RepoFqn
    -- 仓库类的FQN

Step 4 -- DTO and customization questions

步骤4 -- DTO和自定义问题

By Step 0 you may already know the DTO mode if the user mentioned it (e.g. "with DTO", "without DTO", "use entity directly", "map to ProductDto"). If so, skip the question and proceed.
If unknown, ask via
AskUserQuestion
:
QuestionHeaderOptions (first = recommended)
Use DTO for mapping?DTO modeYes, use DTO (Recommended): select existing or create new via
dto-creator
/ No, use entity directly
通过步骤0,如果用户提到了DTO模式(例如"使用DTO"、"不使用DTO"、"直接使用实体"、"映射到ProductDto"),你可能已经知道它。如果是这样,跳过问题继续。
如果未知,通过
AskUserQuestion
询问:
问题标题选项(首位为推荐)
是否使用DTO进行映射?DTO模式是,使用DTO(推荐):选择现有DTO或通过
dto-creator
创建新DTO / 否,直接使用实体

If DTO selected:

如果选择DTO:

Call
list_entity_dtos(entityFqn)
and
list_entity_mappers(entityFqn)
.
If existing DTO + mapper found: ask user to select them. Extract:
  • DtoFqn
    -- DTO class FQN
  • dtoVar
    -- decapitalized DTO name
  • mapperFieldName
    -- decapitalized mapper class name
  • toDtoMethodName
    -- mapper method entity-->DTO (e.g.
    toDto
    )
  • toEntityMethodName
    -- mapper method DTO-->entity (e.g.
    toEntity
    )
  • updateMethodName
    -- mapper method for update (e.g.
    updateWithNullValues
    )
Warn: CREATE and PATCH operations require the mapper to have
toEntity
and
updateWithNull
methods.
If no DTO exists for the entity: delegate to
dto-creator
to create one. The
dto-creator
skill will handle DTO generation and will automatically delegate to
mapper-creator
for the mapper (since the DTO is for a REST controller — conversion is inevitable). After both are created, return here and continue with Step 4 path settings.
If DTO exists but no mapper: delegate to
mapper-creator
to create one. After the mapper is created, return here and continue.
调用
list_entity_dtos(entityFqn)
list_entity_mappers(entityFqn)
如果找到现有DTO + 映射器: 请用户选择它们。提取:
  • DtoFqn
    -- DTO类的FQN
  • dtoVar
    -- 小写开头的DTO名称
  • mapperFieldName
    -- 小写开头的映射器类名
  • toDtoMethodName
    -- 映射器的实体转DTO方法(例如
    toDto
  • toEntityMethodName
    -- 映射器的DTO转实体方法(例如
    toEntity
  • updateMethodName
    -- 映射器的更新方法(例如
    updateWithNullValues
警告:CREATE和PATCH操作要求映射器具有
toEntity
updateWithNull
方法。
如果实体没有现有DTO: 委托给
dto-creator
技能创建一个。
dto-creator
技能将处理DTO生成,并自动委托给
mapper-creator
技能创建映射器(因为DTO用于REST控制器——转换是不可避免的)。两者创建完成后,返回此处继续步骤4的路径设置。
如果DTO存在但没有映射器: 委托给
mapper-creator
技能创建一个。映射器创建完成后,返回此处继续。

Path, pagination & filter settings

路径、分页与过滤设置

Apply the Decision-making principle. These settings almost always have good defaults derivable from context — use principle 2 (one-line confirmation) unless the user explicitly asked for customization:
Will create `{EntityName}Controller` in `{controllerPackage}` at `{basePath}/{entityVarPlural}`, Page pagination, no filter. OK?
The user can answer "ok" / "yes" / silence → accept all defaults; or override specific values → apply only those overrides.
Only fall back to individual questions when the user explicitly asked for fine-grained control ("custom paths", "configure pagination") or when context yields no clear defaults.
If the user selects a filter: ask to select existing filter class. Extract
FilterFqn
and
toSpecificationMethodName
. If the repository does not extend
JpaSpecificationExecutor
, add it (WA-repo-enhance).
应用决策原则。这些设置几乎总是可以从上下文推导到合适的默认值——除非用户明确要求自定义,否则使用原则2(单行确认):
将在`{controllerPackage}`中创建`{EntityName}Controller`,路径为`{basePath}/{entityVarPlural}`,使用Page分页,无过滤器。是否确认?
用户可以回答"ok" / "yes" / 保持沉默 → 接受所有默认值;或覆盖特定值 → 仅应用这些覆盖。
只有当用户明确要求细粒度控制("自定义路径"、"配置分页")或上下文没有明确默认值时,才回退到单独的问题。
如果用户选择过滤器:请选择现有过滤器类。提取
FilterFqn
toSpecificationMethodName
。如果仓库未扩展
JpaSpecificationExecutor
,添加该接口(WA-repo-enhance)。

Method selection

方法选择

By Step 0 you may already know which methods the user wants (e.g. "read-only", "only GET and CREATE", "full CRUD"). If so, skip the question.
If unknown, ask via
AskUserQuestion
:
QuestionHeaderOptions (first = recommended)
Which CRUD methods to generate?MethodsFull CRUD (Recommended): GET_LIST, GET_ONE, GET_MANY, CREATE, PATCH, PATCH_MANY, DELETE, DELETE_MANY / Standard CRUD: GET_LIST, GET_ONE, CREATE, PATCH, DELETE / Read-only: GET_LIST, GET_ONE / Custom: select individual methods
Store the selected method set as
selectedMethods
. Step 5.3 generates only these methods, skipping the rest.

通过步骤0,如果用户提到了想要的方法(例如"只读"、"仅GET和CREATE"、"完整CRUD"),你可能已经知道。如果是这样,跳过问题。
如果未知,通过
AskUserQuestion
询问:
问题标题选项(首位为推荐)
要生成哪些CRUD方法?方法完整CRUD(推荐):GET_LIST、GET_ONE、GET_MANY、CREATE、PATCH、PATCH_MANY、DELETE、DELETE_MANY / 标准CRUD:GET_LIST、GET_ONE、CREATE、PATCH、DELETE / 只读:GET_LIST、GET_ONE / 自定义:选择单个方法
将所选方法集存储为
selectedMethods
。步骤5.3仅生成这些方法,跳过其余方法。

Step 5 -- Generate code

步骤5 -- 生成代码

5.1 Create controller class (WA1)

5.1 创建控制器类(WA1)

Read
examples/_skeletons/java.md
or
examples/_skeletons/kotlin.md
based on
language
.
Apply variable substitutions:
  • {packageName}
    --> controllerPackage
  • {className}
    --> controllerName
  • {requestPath}
    --> basePath + resourcePath
Use Write tool to create
src/main/{java,kotlin}/{package-path}/{controllerName}.{java,kt}
.
根据
language
读取
examples/_skeletons/java.md
examples/_skeletons/kotlin.md
应用变量替换:
  • {packageName}
    → controllerPackage
  • {className}
    → controllerName
  • {requestPath}
    → basePath + resourcePath
使用Write工具创建
src/main/{java,kotlin}/{package-path}/{controllerName}.{java,kt}

5.2 Add bean injection (WA2)

5.2 添加Bean注入(WA2)

Read
examples/_beans/injection/java.md
or
kotlin.md
.
Add constructor parameter for repository. If DTO with mapper: also inject mapper bean. Inject
${ObjectMapperFqn}
field (resolved in Step 1:
tools.jackson.databind.ObjectMapper
for Jackson 3.x,
com.fasterxml.jackson.databind.ObjectMapper
for Jackson 2.x).
Use Edit tool to modify the controller class.
读取
examples/_beans/injection/java.md
kotlin.md
添加仓库的构造函数参数。如果使用带映射器的DTO:同时注入映射器Bean。注入
${ObjectMapperFqn}
字段(在步骤1中解析:Jackson 3.x使用
tools.jackson.databind.ObjectMapper
,Jackson 2.x使用
com.fasterxml.jackson.databind.ObjectMapper
)。
使用Edit工具修改控制器类。

5.3 Add CRUD methods (WA3-WA11)

5.3 添加CRUD方法(WA3-WA11)

For each method in
selectedMethods
(from Step 4 method selection):
  1. Determine the example file path:
    examples/_methods/{method-name}/{language}.md
  2. Read the example file
  3. Select the correct code variant based on:
    • DTO mode (no DTO vs with DTO)
    • For GET_LIST: pagination (PAGE / WINDOW / none) and filter (with/without)
    • For PATCH/PATCH_MANY: ObjectMapper vs ObjectPatcher, and DTO vs no-DTO (4 combinations)
    • For CREATE: with/without @Valid
  4. Apply variable substitutions (ONLY variables declared in the Variables section)
  5. FQN handling (CRITICAL): examples contain FQNs (e.g.
    org.springframework.web.bind.annotation.GetMapping
    ,
    org.springframework.data.domain.Pageable
    , entity/DTO/repository FQNs). When writing the final file, you MUST:
    1. Replace every FQN in the body with its short name
    2. Collect every FQN you shortened and emit a corresponding
      import
      line right after the
      package
      statement, sorted, no duplicates
    3. Classes from the same package as the controller must NOT be imported
    4. Types from
      java.lang
      must NOT be imported
    5. Kotlin: same rules — shorten in the body and add
      import
      lines at the top
  6. Use Edit tool to insert the method into the controller class body
对于
selectedMethods
中的每个方法(来自步骤4的方法选择):
  1. 确定示例文件路径:
    examples/_methods/{method-name}/{language}.md
  2. 读取示例文件
  3. 根据以下条件选择正确的代码变体:
    • DTO模式(无DTO vs 使用DTO)
    • 对于GET_LIST:分页(PAGE / WINDOW / 无)和过滤器(有/无)
    • 对于PATCH/PATCH_MANY:ObjectMapper vs ObjectPatcher,以及DTO vs 无DTO(4种组合)
    • 对于CREATE:带/不带@Valid
  4. 应用变量替换(仅替换变量部分声明的变量)
  5. FQN处理(重要): 示例中包含FQN(例如
    org.springframework.web.bind.annotation.GetMapping
    org.springframework.data.domain.Pageable
    、实体/DTO/仓库FQN)。在编写最终文件时,你必须:
    1. 将正文中的每个FQN替换为其短名称
    2. 收集所有缩短的FQN,并在
      package
      语句后添加相应的
      import
      行,排序,无重复
    3. 与控制器同包的类不要导入
    4. java.lang
      中的类型不要导入
    5. Kotlin:规则相同——在正文中缩短并在顶部添加
      import
  6. 使用Edit工具将方法插入控制器类体中

5.4 Add JpaSpecificationExecutor if needed (WA-repo-enhance)

5.4 按需添加JpaSpecificationExecutor(WA-repo-enhance)

If filter is selected and repository does not already extend
JpaSpecificationExecutor
:
Read
examples/_beans/repo-enhance/java.md
or
kotlin.md
. Use Edit tool to add
org.springframework.data.jpa.repository.JpaSpecificationExecutor<{EntityFqn}>
to the repository's extends list.

如果选择了过滤器且仓库尚未扩展
JpaSpecificationExecutor
读取
examples/_beans/repo-enhance/java.md
kotlin.md
。使用Edit工具将
org.springframework.data.jpa.repository.JpaSpecificationExecutor<{EntityFqn}>
添加到仓库的extends列表中。

Step 6 -- Dependencies & properties (automatic)

步骤6 -- 依赖与属性(自动)

  1. Read
    examples/_dependencies/dependencies.md
  2. For each artifact NOT in
    presentDeps
    :
    • Use
      buildFile
      from Step 1
    • Edit the build file to add the dependency
  3. Call
    refresh_build_system_model
  4. No properties are written for this skill (controller has no application.properties entries)
  5. Report: "Created controller {controllerName} with CRUD endpoints for {EntityName}. Added dependencies: [list]."

  1. 读取
    examples/_dependencies/dependencies.md
  2. 对于每个不在
    presentDeps
    中的工件:
    • 使用步骤1中的
      buildFile
    • 编辑构建文件以添加依赖
  3. 调用
    refresh_build_system_model
  4. 此技能无需写入属性(控制器没有application.properties条目)
  5. 报告:"已为{EntityName}创建带有CRUD接口的控制器{controllerName}。已添加依赖:[列表]。"

Anti-hallucination checklist

防幻觉检查清单

Before writing ANY code, verify:
  • The code comes from an examples/ file (cite which one)
  • Only declared variables were substituted
  • No framework API calls were added "from knowledge"
  • Import list covers all FQNs shortened in the body (no missing imports, no extras)
  • Method signatures match the example exactly
  • No comments or convenience methods were added
  • FQNs from examples are shortened in the body AND corresponding
    import
    lines were added after
    package
    (IDE will NOT do this for you)
  • @ParameterObject
    annotation is only added when
    hasSpringDoc = true
  • @Valid
    annotation is only added when
    hasValidation = true
    AND entity has validation annotations
  • PATCH and PATCH_MANY methods use ObjectMapper (fallback) or ObjectPatcher depending on project dependencies
  • getId() in PATCH_MANY matches entity's actual ID accessor
  • Jackson FQNs use
    tools.jackson.databind.*
    for Jackson 3.x (Spring Boot 4.x) and
    com.fasterxml.jackson.databind.*
    for Jackson 2.x (Spring Boot 2.x/3.x). NEVER hardcode one or the other — always resolve
    ${JsonNodeFqn}
    and
    ${ObjectMapperFqn}
    from Step 1.
  • GET_LIST with Page pagination uses
    PagedModel<Entity>
    wrapper (Spring Data 3.2+ / Boot 3.2+/4.x) or returns
    Page<Entity>
    directly (older versions). Select the correct example variant.
在编写任何代码之前,验证:
  • 代码来自examples/文件(注明来自哪个文件)
  • 仅替换了声明的变量
  • 没有添加"凭知识"的框架API调用
  • 导入列表涵盖了正文中所有缩短的FQN(无缺失导入,无多余导入)
  • 方法签名与示例完全匹配
  • 没有添加注释或便利方法
  • 示例中的FQN在正文中被缩短,并且在
    package
    语句后添加了相应的
    import
    行(IDE不会自动完成此操作)
  • @ParameterObject
    注解仅在
    hasSpringDoc = true
    时添加
  • @Valid
    注解仅在
    hasValidation = true
    且实体有验证注解时添加
  • PATCH和PATCH_MANY方法根据项目依赖使用ObjectMapper(回退)或ObjectPatcher
  • PATCH_MANY中的getId()与实体实际的ID访问器匹配
  • Jackson FQN对Jackson 3.x(Spring Boot 4.x)使用
    tools.jackson.databind.*
    ,对Jackson 2.x(Spring Boot 2.x/3.x)使用
    com.fasterxml.jackson.databind.*
    。永远不要硬编码其中一种——始终从步骤1解析
    ${JsonNodeFqn}
    ${ObjectMapperFqn}
  • 使用Page分页的GET_LIST使用
    PagedModel<Entity>
    包装器(Spring Data 3.2+ / Boot 3.2+/4.x)或直接返回
    Page<Entity>
    (旧版本)。选择正确的示例变体。