1
0
Files
spring-boot-service-template/README.md

182 lines
7.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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<E> extends
FenixJpaRepository<E, Long>,
FenixJpaSpecificationExecutor<E>,
ListQueryByExampleExecutor<E>,
ListQuerydslPredicateExecutor<E> {}
```
业务 Repository 直接继承: `interface EmployeeRepository extends SimpleRepository<Employee> {}`
无 XML Mapper无自定义 SQL查询通过 JPA Criteria / Fenix / QueryDSL 动态构建。
### 接口组合模式
```java
SimpleService<ENTITY> extends SaveService<ENTITY>, QueryService<ENTITY>, RemoveService<ENTITY>
SimpleController<S, L, D> extends SaveController<S>, QueryController<L, D>, RemoveController
```
抽象基类: `SimpleServiceSupport`(Service) / `SimpleControllerSupport`(Controller),用 `*Support` 后缀(非 `*Impl`)。
Controller 子类必须提供三个 mapper 函数: `saveItemMapper()`, `listItemMapper()`, `detailItemMapper()`
### CRUD 五步
1. 创建实体 — 继承 `SimpleEntity`
2. 创建 Repository — 继承 `SimpleRepository<Entity>`
3. 创建 Service — 继承 `SimpleServiceSupport<Entity>`
4. 创建 DTO — 在 Controller 内定义 `SaveItem`/`ListItem`/`DetailItem` record
5. 创建 Controller — 继承 `SimpleControllerSupport<Entity, SaveItem, ListItem, DetailItem>`,实现 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<T>(status:Integer, message:String, data:T)`,成功 status=0失败 status=500。
- 列表: `data = ListItem<T>(items:Iterable<T>, total:Long)`
- 详情: `data = DetailItem<T>(item:T)`
### 查询条件
查询对象: `Query(Queryable query, List<Sortable> 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`,可用 `<p>`/`<h3>`/`<ul>`/`<pre>`
- 不写 `//` 行内注释,除非必要
### 注解
用:
- 实体: `@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 `<properties>` + `<dependencyManagement>`,子模块不声明版本。
全局继承: `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
```