SuperAPI AI Directory

spring-boot-4

Coding & development

View repository

Updated 10-16 00:03

About this skill

Spring Boot 4 Development Specification

This project uses the Spring Boot 4.0.1 + JPA + MySQL 8 technology stack.

Technology Stack

Technology Version Purpose
Spring Boot 4.0.1 Web Framework
Spring Data JPA 3.4.x Data Access
Hibernate 7.x ORM
MySQL 8.0 Database
JSpecify 1.0.0 Null Safety
SpringDoc 2.8.x API Documentation
Lombok - Code Simplification

Directory Structure

backend/src/main/java/com/taichu/yingjiguanli/
├── YingjiGuanliApplication.java    # 启动类
├── common/                          # 通用类
│   ├── ApiResponse.java            # 统一响应
│   ├── BusinessException.java      # 业务异常
│   └── PageResult.java             # 分页结果
├── config/                          # 配置类
│   ├── CorsConfig.java
│   ├── GlobalExceptionHandler.java
│   └── JpaConfig.java
├── modules/                         # 业务模块
│   └── {module}/                   # 模块名
│       ├── entity/                 # 实体类
│       ├── repository/             # 数据访问
│       ├── service/                # 服务层
│       │   └── impl/
│       ├── controller/             # 控制器
│       ├── dto/                    # 数据传输对象
│       └── vo/                     # 视图对象
└── resources/
    ├── application.yml
    └── db/migration/               # Flyway 迁移

Code Templates

Entity Entity Class

package com.taichu.yingjiguanli.modules.{module}.entity;

import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.Comment;
import org.jspecify.annotations.Nullable;

import java.time.LocalDateTime;

/**
 * {实体描述}
 *
 * @author CX
 * @since {date}
 */
@Data
@Entity
@Table(name = "{table_name}")
@Comment("{表描述}")
public class {EntityName} {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Comment("主键ID")
    private Long id;

    /**
     * {字段描述}
     */
    @Column(nullable = false, length = 100)
    @Comment("{字段描述}")
    private String name;

    /**
     * 创建时间
     */
    @Column(nullable = false, updatable = false)
    @Comment("创建时间")
    private LocalDateTime createdAt;

    /**
     * 更新时间
     */
    @Column(nullable = false)
    @Comment("更新时间")
    private LocalDateTime updatedAt;

    @PrePersist
    protected void onCreate() {
        createdAt = LocalDateTime.now();
        updatedAt = LocalDateTime.now();
    }

    @PreUpdate
    protected void onUpdate() {
        updatedAt = LocalDateTime.now();
    }
}

Repository Data Access

package com.taichu.yingjiguanli.modules.{module}.repository;

import com.taichu.yingjiguanli.modules.{module}.entity.{EntityName};
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

import java.util.Optional;

/**
 * {实体}数据访问接口
 *
 * @author CX
 * @since {date}
 */
@Repository
public interface {EntityName}Repository extends JpaRepository<{EntityName}, Long>, JpaSpecificationExecutor<{EntityName}> {

    /**
     * 根据名称查询
     */
    Optional<{EntityName}> findByName(String name);
}

Service Service Layer

package com.taichu.yingjiguanli.modules.{module}.service;

import com.taichu.yingjiguanli.modules.{module}.dto.{EntityName}DTO;
import com.taichu.yingjiguanli.modules.{module}.entity.{EntityName};
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.Optional;

/**
 * {实体}服务接口
 *
 * @author CX
 * @since {date}
 */
public interface {EntityName}Service {

    /**
     * 创建
     */
    {EntityName} create({EntityName}DTO dto);

    /**
     * 更新
     */
    {EntityName} update(Long id, {EntityName}DTO dto);

    /**
     * 删除
     */
    void delete(Long id);

    /**
     * 根据ID查询
     */
    Optional<{EntityName}> findById(Long id);

    /**
     * 分页查询
     */
    Page<{EntityName}> findAll(Pageable pageable);
}

ServiceImpl Service Implementation

package com.taichu.yingjiguanli.modules.{module}.service.impl;

import com.taichu.yingjiguanli.common.BusinessException;
import com.taichu.yingjiguanli.modules.{module}.dto.{EntityName}DTO;
import com.taichu.yingjiguanli.modules.{module}.entity.{EntityName};
import com.taichu.yingjiguanli.modules.{module}.repository.{EntityName}Repository;
import com.taichu.yingjiguanli.modules.{module}.service.{EntityName}Service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

/**
 * {实体}服务实现
 *
 * @author CX
 * @since {date}
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class {EntityName}ServiceImpl implements {EntityName}Service {

    private final {EntityName}Repository repository;

    @Override
    @Transactional
    public {EntityName} create({EntityName}DTO dto) {
        log.info("创建{实体}: {}", dto);
        {EntityName} entity = new {EntityName}();
        // 设置属性...
        return repository.save(entity);
    }

    @Override
    @Transactional
    public {EntityName} update(Long id, {EntityName}DTO dto) {
        log.info("更新{实体} ID={}: {}", id, dto);
        {EntityName} entity = repository.findById(id)
                .orElseThrow(() -> new BusinessException(404, "{实体}不存在"));
        // 更新属性...
        return repository.save(entity);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        log.info("删除{实体} ID={}", id);
        if (!repository.existsById(id)) {
            throw new BusinessException(404, "{实体}不存在");
        }
        repository.deleteById(id);
    }

    @Override
    public Optional<{EntityName}> findById(Long id) {
        return repository.findById(id);
    }

    @Override
    public Page<{EntityName}> findAll(Pageable pageable) {
        return repository.findAll(pageable);
    }
}

Controller Controller

package com.taichu.yingjiguanli.modules.{module}.controller;

import com.taichu.yingjiguanli.common.ApiResponse;
import com.taichu.yingjiguanli.common.BusinessException;
import com.taichu.yingjiguanli.modules.{module}.dto.{EntityName}DTO;
import com.taichu.yingjiguanli.modules.{module}.entity.{EntityName};
import com.taichu.yingjiguanli.modules.{module}.service.{EntityName}Service;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

/**
 * {实体}控制器
 *
 * @author CX
 * @since {date}
 */
@RestController
@RequestMapping("/api/{module}")
@RequiredArgsConstructor
@Tag(name = "{模块名称}", description = "{模块描述}")
public class {EntityName}Controller {

    private final {EntityName}Service service;

    /**
     * 创建
     */
    @PostMapping
    @Operation(summary = "创建{实体}")
    public ApiResponse<{EntityName}> create(@Valid @RequestBody {EntityName}DTO dto) {
        return ApiResponse.success(service.create(dto));
    }

    /**
     * 更新
     */
    @PutMapping("/{id}")
    @Operation(summary = "更新{实体}")
    public ApiResponse<{EntityName}> update(@PathVariable Long id, @Valid @RequestBody {EntityName}DTO dto) {
        return ApiResponse.success(service.update(id, dto));
    }

    /**
     * 删除
     */
    @DeleteMapping("/{id}")
    @Operation(summary = "删除{实体}")
    public ApiResponse<Void> delete(@PathVariable Long id) {
        service.delete(id);
        return ApiResponse.success();
    }

    /**
     * 查询详情
     */
    @GetMapping("/{id}")
    @Operation(summary = "查询{实体}详情")
    public ApiResponse<{EntityName}> getById(@PathVariable Long id) {
        return ApiResponse.success(service.findById(id)
                .orElseThrow(() -> new BusinessException(404, "{实体}不存在")));
    }

    /**
     * 分页查询
     */
    @GetMapping
    @Operation(summary = "分页查询{实体}")
    public ApiResponse<Page<{EntityName}>> list(Pageable pageable) {
        return ApiResponse.success(service.findAll(pageable));
    }
}

DTO Data Transfer Object

package com.taichu.yingjiguanli.modules.{module}.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;

/**
 * {实体}数据传输对象
 *
 * @author CX
 * @since {date}
 */
@Data
public class {EntityName}DTO {

    /**
     * 名称
     */
    @NotBlank(message = "名称不能为空")
    @Size(max = 100, message = "名称长度不能超过100")
    private String name;

    // 其他字段...
}

Flyway Migration Script

-- V{n}__{description}.sql
-- 作者: CX
-- 日期: {date}
-- 描述: {description}

CREATE TABLE {table_name} (
    id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
    name VARCHAR(100) NOT NULL COMMENT '名称',
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='{表描述}';

Naming Conventions

Location Convention Example
Package Name lowercase com.taichu.yingjiguanli.modules.user
Class Name PascalCase UserController, UserService
Method Name camelCase findById, createUser
Variable Name camelCase userName, createdAt
Constant Name UPPER_SNAKE MAX_PAGE_SIZE
Table Name snake_case sys_user, t_order
Field Name snake_case user_name, created_at

Best Practices

  1. Unified Response: All interfaces return ApiResponse<T>
  2. Business Exception: Use BusinessException to throw business errors
  3. Parameter Validation: Use @Valid + jakarta.validation
  4. Logging: Use @Slf4j for key operations to record logs
  5. Transaction Management: Use @Transactional
  6. Chinese Comments: All classes, methods, and fields must have Chinese comments

Project: Emergency Management System (yingjiguanli) Technology Stack: Spring Boot 4.0.1 + JPA + MySQL 8