SuperAPI AI Directory

spring-boot

Coding & development

View repository

Updated 10-16 01:56

About this skill

Spring Boot Backend Development

Deliver Spring Boot code that conforms to the existing project architecture, interface contracts, and quality requirements. First identify the actual conventions of the current repository, then decide whether to follow them, gradually migrate, or explicitly refactor; do not treat examples or preferences as a global transformation the user did not request.

Applicable Boundaries

  • Use the project conventions of this file in youlai-boot .
  • In other Spring Boot projects, adopt only the general principles; directories, naming, response wrappers, and permission expressions are subject to the target repository.
  • User instructions take precedence. Before modifying, check AGENTS.md, build files, related modules, and uncommitted changes to avoid overwriting the user's work.
  • Ordinary feature development is not automatically expanded into a security audit, repository-wide renaming, framework upgrade, or multi-module split.

Project Baseline

Layer Selection
JDK Java 17+
Base Framework Spring Boot 4.x
ORM MyBatis-Plus
Database MySQL 8.x
Cache Redis 7.x
Authentication Spring Security + JWT / Redis Token
API Documentation Springdoc OpenAPI + Knife4j
Object Mapping MapStruct; for complex joined queries, Mapper may project directly to VO

The target repository's pom.xml and configuration classes are the final source of truth; verify official compatibility before upgrading dependencies or changing the compatibility baseline.

Architecture Boundaries

The target structure adopts a monolithic architecture of "package by business domain, layered within the domain":

com.youlai.boot
├── common/       # 纯共享类型:基础对象、结果、常量、通用异常
├── framework/    # Web、Security、MyBatis、缓存、切面等基础设施
├── config/       # 应用装配;不承载业务规则
├── support/      # file、mail、sms、sse 等外部能力
├── auth/         # 认证业务
├── system/       # 用户、角色、菜单、部门、字典等
├── form/         # 动态表单
├── workflow/     # 工作流
└── codegen/      # 代码生成

During migration, module/form、module/workflowmay be temporarily retained, but new code should not continue to create two top-level directory languages.

Observe the following boundaries:

  • common does not depend on framework、config or any business domain.
  • framework does not depend on specific business domains; obtain business capabilities through Ports or callback interfaces.
  • config may serve as a composition root to assemble Beans such as framework, auth, and system.
  • Cross-business-domain calls use explicitly intentional Facades, Ports, or Commands, and do not pass another domain's Entity.
  • Business Service interfaces do not extend MyBatis-Plus IService<Entity>; implementation classes may internally reuse ServiceImpl。
  • Avoid bidirectional package dependencies. When necessary, prefer introducing project-owned command objects or domain events rather than moving Entity to common。
  • For a monolithic project, first use package boundaries and ArchUnit to enforce dependency direction; do not proactively split into microservices without an independent deployment requirement.

Determining the ownership of configuration classes and property classes:

  • @Configuration For assembly classes, look at the Bean consumer: Beans consumed only by a single business domain or support component are placed with the domain (e.g., auth/config/CaptchaConfig、support/mail/MailConfig); only cross-domain or framework-level Beans remain in the global config/. Test method: if after deleting a business domain the Bean has no references, the assembly class should move with that domain.
  • @ConfigurationProperties For property classes, look at the package root shape: packages that already have sibling classes at the root (support/mail、support/sms、framework/web/ratelimit) are placed flat at the root; collection roots that contain only subdirectories under the root (auth、codegen、framework/security、support/file) get a property/ subpackage.
  • Property classes are annotated only with @ConfigurationProperties, not stacked with @Configuration; registration is uniformly delegated to @ConfigurationPropertiesScan, avoiding dual registration by component scanning and property scanning.

Model Responsibilities and Improvement Directions

Type Suggested Definition Current Project Improvement Focus
Entity Used only by the persistence layer Basically reasonable, but SysUser/SysLog and Role/Dept/Menu 's Sys prefixes are inconsistent
Form Write request input Create/update may share; within Body, id duplicates the Path ID, and validation at some entry points is incomplete
Query query conditions; paginated classes use XxxPageQuery UserQuery is actually a paginated query,DeptQuery is again a non-paginated query, so the semantics are inconsistent
VO external responses or read-only projections overall fairly standardized; having the Mapper directly project a VO for complex joins can be retained
DTO intra-module or inter-module transfer already converged: push payloads are sent by DictChangeDTO into dto/, and event semantics are carried by topic constants

New code converges according to the following rules; for historical code, unless the user requests it, do not perform unprofitable batch renaming:

  • Entity uses the domain name, e.g., User、Role; the table prefix is expressed by @TableName("sys_user") . Keep the existing SysUser、SysLog as a migration compatibility item.
  • Write models use XxxForm. When create and update fields or validations differ, split into XxxCreateForm、XxxUpdateForm。
  • When the resource ID is already present in the Path, the Path is the single source of truth, and the Form does not carry the ID redundantly.
  • Paginated queries use XxxPageQuery, and non-paginated filtering uses XxxQuery. For time ranges, prefer createdFrom、createdTo and other explicit time types.
  • Do not stuff execution contexts such as permission scopes, the current user, or tenants into external Query objects; pass them through independent context parameters or security components.
  • VO is only used for output and is not reused as a write model. The Mapper may directly return a VO for complex joins, but does not accept Controller Forms.
  • DTOs must have clear internal transfer semantics. SSE/message push payloads are cross-layer transfer carriers; name them according to XxxDTO and place them into dto/, with event semantics carried by topic constants (e.g., SseTopics); put session or process state in context. Only create the event/ package for genuine Spring domain events, and do not open a new category package for a single payload.
  • The auth module and other business domains uniformly use Form/Query/VO, and no longer have both req/resp suffix sets coexist.

Input validation

  • @RequestBody inputs use @Valid; when a Controller class needs to validate Path/Query scalars, use @Validated。
  • pagination parameter constraints pageNum >= 1, and set a reasonable upper limit for pageSize .
  • Sort fields must map to a server-side whitelist; sort directions use enums or explicit allowed values, and directly concatenating arbitrary SQL fields is prohibited.
  • For finite sets such as status and type, prefer enums; when compatible with database integers, complete conversion and validation at the boundary.
  • Dynamic forms' Map<String, Object> cannot be covered by Bean Validation alone and must enforce field whitelisting, type, length, and business rule validation.
  • Do not validate only in create APIs; write entry points such as updates, status changes, and password resets must also validate.

API and responses

  • Resource paths use plural nouns, e.g., /api/v1/users; action endpoints are used only when they cannot be naturally expressed as a resource state.
  • Controller returns Result<T> or PageResult<T>; when there is no response data, use Result<Void>, avoiding Result<?>。
  • Controller is responsible for protocol adaptation; Service does not return Result, and Mapper does not return Result or PageResult。
  • Existing modules may temporarily have Service return IPage<VO>, with Controller calling PageResult.success(page); do not mix within the same module Page、IPage、PageResult three types of service contracts.
  • For create success, return the resource ID first; for update and delete success, return Result<Void>。
  • Keep the existing business code A****、B****、C**** system, and use appropriate HTTP statuses to express protocol errors, such as 400, 401, 403, 404, 409, 429, 500.
  • Use for create/update APIs according to actual idempotency risk @RepeatSubmit; add for create, delete, update, and key actions according to audit needs @Log, and do not mechanically annotate all queries.

Persistence and Object Mapping

  • Entities are not returned directly from Controllers, nor are they used as cross-module contracts.
  • Prefer MapStruct for simple single-table mapping; for complex joined queries, Mappers may directly project VOs.
  • Do not use BeanUtils.copyProperties or JSON serialization for routine object mapping; handwritten mapping for a small number of explicit fields is acceptable.
  • Entity primary key strategy and logical deletion method shall follow the project-wide MyBatis-Plus configuration. Do not simultaneously invent a conflicting set of @TableLogic or ID strategies.

Implementation Process

  1. Read the target module, adjacent modules, database mappings, configurations, and tests to confirm the real contract.
  2. Determine whether the change belongs to an input Form, query Query, output VO, or internal DTO/Event/Context.
  3. Define validation, authorization, transaction boundaries, and failure semantics first, then implement the Mapper, Service, and Controller.
  4. Check cross-domain dependencies; if data or actions from another domain are needed, call a narrow interface instead of depending on its Entity or general-purpose IService。
  5. Compile and run tests related to the change; when an external database, Redis, or third-party service is unavailable, clearly state the unverified parts.
  6. Only modify files within the task scope, and report compatibility impacts and remaining migration items.

Comment Principles

  • Comments explain constraints, reasons, side effects, threading/transaction requirements, and easily missed behaviors; they do not repeat class names, annotations, or the surface meaning of code.
  • Public extension points, cross-module interfaces, and methods with non-obvious constraints should have Javadoc; simple internal POJOs and obvious getters/setters do not require item-by-item comments.
  • When a stable Javadoc summary needs to be generated, prefer {@summary ...}。
  • @author Use the project's existing author convention, and do not invent values;@since write the project's current version number, consistent with pom.xml of the version ; update it synchronously when upgrading the version, and do not write dates.
  • API fields should preferably be described by @Schema for protocol meaning; Javadoc supplements domain constraints, avoiding copying the same sentence in two places.
  • Update comments synchronously when code changes; historical explanations that may no longer hold should be deleted or verified and rewritten.

For detailed rules, see references/comments.md。

Read references as needed