# Spring Boot Service Template 微服务快速开发能力模板,v1.1.0-SNAPSHOT。Java 17, Spring Boot 4.0.0, Spring Cloud 2025.1.0。 GroupId: `com.lanyuanxiaoyao`,根包: `com.lanyuanxiaoyao.service.template`。 ## 模块 ``` spring-boot-service-template/ (根 POM, packaging=pom) ├── spring-boot-service-template-common/ (jar — 通用工具) └── spring-boot-service-template-database/ (jar — JPA 数据库能力) ``` 模块命名规则: `spring-boot-service-template-{capability}[-{impl}]` ## 包结构 ``` com.lanyuanxiaoyao.service.template.{module}/ configuration/ # @Configuration(用 configuration 不用 config) controller/ # REST 控制器 + 接口 entity/ # JPA 实体、Query、GlobalResponse 等数据对象 exception/ # 自定义异常(用 exception 不用 exceptions) helper/ # 工具类(用 helper 不用 util/utils) repository/ # Spring Data 仓库 service/ # 业务服务 ``` 无独立 DTO/VO 包,DTO 作为 Controller 内部 record。 ## database 模块 单表 CRUD → REST 接口的快速实现框架。基于 JPA + Fenix + QueryDSL + MapStruct。 ### 实体继承 ``` IdOnlyEntity (id: Long, @SnowflakeId) ← @MappedSuperclass ↑ SimpleEntity (+ createdTime: LocalDateTime, ← @MappedSuperclass modifiedTime: LocalDateTime) ↑ 业务实体 (具体 @Entity) ``` - ID: Long,雪花算法,字段标 `@SnowflakeId`(自定义注解) - 时间字段: `@CreatedDate`/`@LastModifiedDate`,JPA `AuditingEntityListener` 自动填充 - 列注释: `@Column(comment = "...")` - 物理命名: `PhysicalNamingStrategySnakeCaseImpl`(camelCase→snake_case) - 保存: Fenix `saveOrUpdateByNotNullProperties()`,自动 INSERT/UPDATE,仅更新非 null 字段 ### Repository ```java @NoRepositoryBean public interface SimpleRepository extends FenixJpaRepository, FenixJpaSpecificationExecutor, ListQueryByExampleExecutor, ListQuerydslPredicateExecutor {} ``` 业务 Repository 直接继承: `interface EmployeeRepository extends SimpleRepository {}` 无 XML Mapper,无自定义 SQL,查询通过 JPA Criteria / Fenix / QueryDSL 动态构建。 ### 接口组合模式 ```java SimpleService extends SaveService, QueryService, RemoveService SimpleController extends SaveController, QueryController, RemoveController ``` 抽象基类: `SimpleServiceSupport`(Service) / `SimpleControllerSupport`(Controller),用 `*Support` 后缀(非 `*Impl`)。 Controller 子类必须提供三个 mapper 函数: `saveItemMapper()`, `listItemMapper()`, `detailItemMapper()` ### CRUD 五步 1. 创建实体 — 继承 `SimpleEntity` 2. 创建 Repository — 继承 `SimpleRepository` 3. 创建 Service — 继承 `SimpleServiceSupport` 4. 创建 DTO — 在 Controller 内定义 `SaveItem`/`ListItem`/`DetailItem` record 5. 创建 Controller — 继承 `SimpleControllerSupport`,实现 3 个 mapper 也可用 `DatabaseHelper.generateBasicFiles()` 自动生成上述脚手架,`@RequestMapping` 路径由实体名 camelCase→snake_case 推导。`DatabaseHelper.generateDDL()` 可从实体类生成 DDL SQL。 ### API 端点 | 操作 | 方法 | 路径 | | --------- | ---- | ---------------- | | 新增/更新 | POST | `/save` | | 全部列表 | GET | `/list` | | 条件列表 | POST | `/list` | | 详情 | GET | `/detail/{id}` | | 删除 | GET | `/remove/{id}` | 统一响应: `GlobalResponse(status:Integer, message:String, data:T)`,成功 status=0,失败 status=500。 - 列表: `data = ListItem(items:Iterable, total:Long)` - 详情: `data = DetailItem(item:T)` ### 查询条件 查询对象: `Query(Queryable query, List sort, Pageable page)` 支持: equal/notEqual/like/notLike/contain/notContain/startWith/endWith/great/less/greatEqual/lessEqual/between/notBetween/inside/notInside/nullEqual/notNullEqual/empty/notEmpty 分页: `Pageable(index, size)`,index 从 1 开始,默认 `(1, 10)`,无排序默认 `createdTime DESC` ## 开发规范 ### 命名 | 类别 | 模式 | 示例 | | --------------- | ---------------------------------------- | ---------------------------------- | | 实体基类 | `*Entity` | `IdOnlyEntity`, `SimpleEntity` | | 业务实体 | 纯名词 | `Employee` | | 控制器接口 | `*Controller` | `SaveController` | | 控制器抽象基类 | `*ControllerSupport` | `SimpleControllerSupport` | | 服务接口 | `*Service` | `SaveService` | | 服务抽象基类 | `*ServiceSupport` | `SimpleServiceSupport` | | 仓库 | `*Repository` | `EmployeeRepository` | | 工具类 | `*Helper` | `ObjectHelper` | | 配置类 | `*Configuration` | `QueryDSLConfiguration` | | 异常 | `*Exception` | `IdNotFoundException` | | 内部 DTO record | `SaveItem`/`ListItem`/`DetailItem` | Controller 内部 | - 接口不加 `I` 前缀 - 方法: 动词开头 `save()`/`list()`/`detail()`/`remove()`;布尔用 `is`/`has` 前缀 - 常量 UPPER_SNAKE_CASE;字段常量用 `@FieldNameConstants` 生成 `{Class}.Fields.{field}` - 泛型: 简单用 `T`/`E`,领域用 `ENTITY`/`SAVE_ITEM`/`LIST_ITEM`/`DETAIL_ITEM` ### 代码风格 - 2 空格缩进,K&R 大括号,不用 Tab - Import 排序: `java.*` → `jakarta.*` → 第三方 → `com.lanyuanxiaoyao.*`,不用通配符 - 积极使用 Java 17 特性: `record`(DTO) / `var` / `instanceof` 模式匹配 / Text Blocks / `String.formatted()` - JavaDoc 用中文,含 `@param`/`@return`/`@see`,可用 `

`/`

`/`
    `/`
    `
    - 不写 `//` 行内注释,除非必要
    
    ### 注解
    
    用:
    
    - 实体: `@Getter` `@Setter` `@ToString` `@FieldNameConstants`,子类加 `@ToString(callSuper = true)`
    - 日志: `@Slf4j`
    - 注入: `@RequiredArgsConstructor(access = AccessLevel.PROTECTED)`(构造器注入)
    - 事务: 写 `@Transactional(rollbackFor = Throwable.class)`,读 `@Transactional(readOnly = true)`
    - 实体基类: `@MappedSuperclass` `@EntityListeners(AuditingEntityListener.class)`
    
    不用:
    
    - 不用 `@Valid`/`@NotNull` 等校验注解
    - 不用 Swagger/OpenAPI 注解
    - 不用 `@Autowired` 字段注入
    - 不写代码注释(`//`),除非必要
    
    ### 异常
    
    继承 `RuntimeException`,构造器用 `String.formatted()`。查无数据用 `Optional.orElseThrow(() -> new IdNotFoundException(id))`。无全局 `@ControllerAdvice`。
    
    ### 依赖管理
    
    版本集中在根 POM `` + ``,子模块不声明版本。
    全局继承: `lombok` / `jspecify:1.0.0`
    核心: `spring-boot-starter-data-jpa` / `fenix-spring-boot-starter:4.0.0` / `querydsl-jpa:7.1` / `mapstruct:1.6.3`
    database 模块注解处理器: lombok → hibernate-jpamodelgen → querydsl-apt(jpa) → jakarta.persistence-api → mapstruct-processor
    
    ### 通用原则
    
    - 文档/注释/commit 用中文,代码标识符用英文
    - 不引入新依赖前先复用已有组件,优先 JDK 和 Spring 内置能力
    - 构造器注入,不使用 `@Autowired` 字段注入
    
    ### 构建
    
    ```bash
    mvn clean package
    ```