# Scorpio-Framework开发文档
## 路径信息
```yaml
basePackage: com.congyuntech.scorpio.framework
modules:
- core.congestive # 聚合根相关模块
exports:
- com.congyuntech.scorpio.framework.core.congestive.Congestive
- com.congyuntech.scorpio.framework.core.congestive.CongestiveException
- com.congyuntech.scorpio.framework.core.congestive.CongestiveNotFoundException
- com.congyuntech.scorpio.framework.core.congestive.CongestiveRepository
- com.congyuntech.scorpio.framework.core.congestive.CongestiveEntityListener
- com.congyuntech.scorpio.framework.core.congestive.id.CongestiveId
- com.congyuntech.scorpio.framework.core.congestive.id.CongestiveIdGenerator
- com.congyuntech.scorpio.framework.core.congestive.id.SnowflakeGenerator
- com.congyuntech.scorpio.framework.core.congestive.manager.CongestiveManager
- com.congyuntech.scorpio.framework.core.congestive.provider.CongestiveProvider
- com.congyuntech.scorpio.framework.core.congestive.validation.CongestiveValidator
- com.congyuntech.scorpio.framework.core.congestive.validation.CongestiveNotValidException
- core.data # 数据相关模块
exports:
- com.congyuntech.scorpio.framework.core.data.jpa.entity.BaseEntity
- core.enumeration # 枚举相关模块
exports:
- com.congyuntech.scorpio.framework.core.enumeration.AnnotationEnum
- com.congyuntech.scorpio.framework.core.enumeration.BeautifulEnum
- com.congyuntech.scorpio.framework.core.enumeration.EnumAttribute
- com.congyuntech.scorpio.framework.core.enumeration.EnumAttributes
- com.congyuntech.scorpio.framework.core.enumeration.parser.AttributeValueParser
- com.congyuntech.scorpio.framework.core.enumeration.parser.StringParser
- core.security # 安全相关模块
exports:
- com.congyuntech.scorpio.framework.core.security.SecurityFilter
- com.congyuntech.scorpio.framework.core.security.SecurityWebTokenFilter
- com.congyuntech.scorpio.framework.core.security.AbstractSecurityFilter
- com.congyuntech.scorpio.framework.core.security.authentication.Authentication
- core.trouble # 异常处理模块
exports:
- com.congyuntech.scorpio.framework.core.trouble.Trouble
- com.congyuntech.scorpio.framework.core.trouble.TroublePrefix
- com.congyuntech.scorpio.framework.core.trouble.TroubleEnum
- com.congyuntech.scorpio.framework.core.trouble.TroubleException
- core.service.query # 查询服务模块
exports:
- com.congyuntech.scorpio.framework.core.service.query.CriteriaParser
- com.congyuntech.scorpio.framework.core.service.query.ExpressionParser
- com.congyuntech.scorpio.framework.core.service.query.QueryExecutor
- com.congyuntech.scorpio.framework.core.service.query.QueryExpression
- com.congyuntech.scorpio.framework.core.service.query.QueryExpressionService
- com.congyuntech.scorpio.framework.core.service.query.QueryServiceFactory
- com.congyuntech.scorpio.framework.core.service.query.expression.Embed
- com.congyuntech.scorpio.framework.core.service.query.expression.Expression
- com.congyuntech.scorpio.framework.core.service.query.expression.Expressions
- com.congyuntech.scorpio.framework.core.service.query.expression.Join
- com.congyuntech.scorpio.framework.core.service.query.expression.JsonPath
- com.congyuntech.scorpio.framework.core.service.query.expression.Operator
- com.congyuntech.scorpio.framework.core.service.query.expression.Path
- com.congyuntech.scorpio.framework.core.service.query.jpa.JpaExpressionParser
- com.congyuntech.scorpio.framework.core.service.query.jpa.JpaQueryExecutor
- com.congyuntech.scorpio.framework.core.service.query.jpa.JpaQueryExpression
```
## Congestive 聚合根模块
### 概述
Congestive 是 Scorpio Framework 的核心模块之一,它提供了一套完整的聚合根(Aggregate Root)实现方案。该模块基于领域驱动设计(DDD)思想,通过简单的接口实现和注解配置,帮助开发者快速构建具有充血模型特征的领域实体。
主要特性:
1. 统一的聚合根生命周期管理
2. 灵活的业务标识生成策略
3. 强大的数据验证机制
4. 简洁的仓储查询能力
5. 完善的异常处理机制
通过 Congestive 模块,开发者可以:
- 将实体类转变为具有完整业务行为的充血模型
- 实现统一的业务标识生成和管理
- 集中管理实体的业务规则验证
- 使用简洁的方式进行数据访问
这个模块特别适合:
- 需要实现 DDD 架构的项目
- 需要统一管理实体标识的场景
- 需要规范化实体验证逻辑的场景
- 期望简化数据访问层代码的项目
### 使用 Congestive 接口定义聚合根
#### 基本定义
要创建一个聚合根,需要实现 Congestive 接口。这个接口有两个泛型参数:
- T: 聚合根实体类型
- R: 对应的 Repository 类型
基本示例:
```java
@Entity
@Table(name = "user")
public class User implements Congestive
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@CongestiveId(generator = SnowflakeGenerator.class)
private String userId;
private String name;
private String phoneNo;
// 业务字段...
}
```
#### 关键注解说明
1. @CongestiveId
- 用于标注业务标识字段
- 必须应用在 String 类型的字段上
- 通过 generator 属性指定 ID 生成器
```java
// 使用默认的雪花算法生成器
@CongestiveId(generator = SnowflakeGenerator.class)
private String userId;
// 或者使用自定义的 ID 生成器
@CongestiveId(generator = CustomUserIdGenerator.class)
private String userId;
```
2. 自定义 ID 生成器
```java
public class CustomUserIdGenerator implements CongestiveIdGenerator {
@Override
public String nextUid() {
// 实现自定义的 ID 生成逻辑
return "USER_" + System.currentTimeMillis();
}
}
```
3. @Entity 和 @Table
- 标准的 JPA 注解
- @Table 用于指定表名,使用聚合根名称作为表名
#### 继承 BaseEntity
推荐聚合根实体继承 BaseEntity 以获得基础字段支持:
```java
@Entity
@Table(name = "user")
public class User extends BaseEntity implements Congestive {
@CongestiveId(generator = SnowflakeGenerator.class)
private String userId;
private String name;
private String phoneNo;
// BaseEntity 已经包含:
// - id (主键)
// - version (版本号)
// - createdTime (创建时间)
// - updatedTime (更新时间)
}
```
#### 核心功能
1. 聚合根实体操作方法
```java
@Service
public class UserService {
// 保存实体
public User createUser(String name, String email) {
User user = new User();
user.setName(name);
user.setEmail(email);
return user.save(); // 直接调用实体的 save() 方法
}
// 删除实体
public void removeUser(String userId) {
User user = Congestive.get(userId, User.class);
user.delete(); // 直接调用实体的 delete() 方法
}
}
```
2. 静态查询方法
Congestive 接口提供了一系列静态查询方法:
```java
@Service
public class UserService {
// 根据聚合根ID获取实体
public User getUser(String userId) {
return Congestive.get(userId, User.class);
}
// 根据属性查询单个实体(返回 Optional)
public Optional findByEmail(String email) {
return Congestive.findByAttribute("email", email, User.class);
}
// 根据属性查询单个实体(不存在则抛出异常)
public User getByPhone(String phone) {
return Congestive.getByAttribute("phoneNo", phone, User.class);
}
// 检查属性值是否存在
public boolean isEmailExists(String email) {
return Congestive.existsByAttribute("email", email, User.class);
}
// 根据属性查询多个实体
public List findByStatus(UserStatus status) {
return Congestive.findAllByAttribute("status", status, User.class);
}
}
3. 使用 JPA 元模型查询
为了提供类型安全的查询,可以使用 JPA 元模型:
```java
@Service
public class UserService {
// 使用元模型进行查询
public Optional findByEmail(String email) {
return Congestive.findByAttribute(User_.email, email);
}
public User getByPhone(String phone) {
return Congestive.getByAttribute(User_.phoneNo, phone);
}
public boolean isEmailExists(String email) {
return Congestive.existsByAttribute(User_.email, email);
}
public List findByStatus(UserStatus status) {
return Congestive.findAllByAttribute(User_.status, status);
}
}
```
4. 获取 Repository
如果需要使用更复杂的查询,可以获取实体的 Repository:
```java
@Service
public class UserService {
// 通过实体实例获取 Repository
public List findActiveUsers(String userId) {
User user = Congestive.get(userId, User.class);
return user.repository().findByStatus(UserStatus.ACTIVE);
}
// 直接获取 Repository
public List searchUsers(String keyword) {
UserRepository repository = Congestive.getRepository(User.class);
return repository.searchByNameOrEmail(keyword);
}
}
```
### 定义 CongestiveRepository
#### 基本定义
CongestiveRepository 接口继承自 JpaRepository,为聚合根提供基础的数据访问能力。定义 Repository 只需要继承 CongestiveRepository 接口:
```java
@Repository
public interface UserRepository extends CongestiveRepository {
// 可以添加自定义查询方法
}
```
#### 核心功能
CongestiveRepository 提供了以下核心方法:
1. 属性查询
```java
// 根据属性查找单个实体
Optional findByAttribute(String attributeName, Object value);
Optional findByAttribute(SingularAttribute attribute, Object value);
// 检查特定属性值的实体是否存在
boolean existsByAttribute(String attributeName, Object value);
boolean existsByAttribute(SingularAttribute attribute, Object value);
// 根据属性查找所有匹配的实体
List findAllByAttribute(String attributeName, Object value);
List findAllByAttribute(SingularAttribute attribute, Object value);
```
#### 使用示例
1. 基本查询
```java
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public Optional findByPhone(String phoneNo) {
// 使用字符串指定属性名
return userRepository.findByAttribute("phoneNo", phoneNo);
// 或使用 JPA 元模型(推荐)
return userRepository.findByAttribute(User_.phoneNo, phoneNo);
}
}
```
2. 结合 JPA 元模型
```java
// 使用 JPA 元模型可以提供类型安全的查询
public boolean isPhoneExists(String phoneNo) {
return userRepository.existsByAttribute(User_.phoneNo, phoneNo);
}
public List findUsersByStatus(UserStatus status) {
return userRepository.findAllByAttribute(User_.status, status);
}
```
#### 自定义查询方法
除了使用 CongestiveRepository 提供的通用方法外,还可以在 Repository 接口中定义自定义的查询方法:
```java
@Repository
public interface UserRepository extends CongestiveRepository {
// 使用方法名定义查询
List findByAgeGreaterThan(int age);
// 使用 @Query 注解定义查询
@Query("SELECT u FROM User u WHERE u.status = :status AND u.age > :age")
List findActiveUsersOlderThan(
@Param("status") UserStatus status,
@Param("age") int age
);
// 使用 QueryDSL 支持
@Override
default List findActiveUsers() {
QUser user = QUser.user;
return from(user)
.where(user.status.eq(UserStatus.ACTIVE))
.fetch();
}
}
```
#### 最佳实践
1. 查询方法选择
- 优先使用 CongestiveRepository 提供的通用方法
- 对于复杂查询,使用自定义方法
- 推荐使用 JPA 元模型而不是字符串属性名
2. 性能考虑
- 需要分页的场景使用 findAll 的分页重载
- 大数据量查询时考虑使用流式查询
- 合理使用索引优化查询性能
3. 命名规范
- 查询方法名应该清晰表达其功能
- 遵循 JPA 命名规范
- 使用领域术语而不是技术术语
4. 注意事项
- 避免在 Repository 中包含业务逻辑
- 查询方法应该是幂等的
- 合理使用事务注解
### 定义 CongestiveValidator
#### 基本定义
CongestiveValidator 是聚合根的验证器,提供两种验证机制:
1. Bean Validation (JSR-380) 标准验证
2. 自定义业务规则验证
基本示例:
```java
@Component
public class UserValidator implements CongestiveValidator {
@Override
public void validateSave(User user) throws CongestiveNotValidException {
// 验证手机号唯一性
user.repository().findByAttribute(User_.PHONE_NO, user.getPhoneNo())
.filter(t -> !t.getUserId().equals(user.getUserId()))
.ifPresent(t -> {
throw new CongestiveNotValidException("手机号已被注册");
});
}
@Override
public void validateDelete(User user) throws CongestiveNotValidException {
// 删除前的业务规则验证
if (user.getStatus() == UserStatus.ACTIVE) {
throw new CongestiveNotValidException("活跃用户不能删除");
}
}
}
```
#### Bean Validation 支持
CongestiveValidator 内置支持 Jakarta Bean Validation,可以直接使用标准注解:
```java
@Entity
public class User implements Congestive {
@CongestiveId(generator = SnowflakeGenerator.class)
private String userId;
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 20, message = "用户名长度必须在2-20之间")
private String username;
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phoneNo;
@Email(message = "邮箱格式不正确")
private String email;
}
```
Bean Validation 会在 save 操作前自动执行。
#### 核心方法
1. validateSave
- 在保存聚合根前执行
- 验证失败时抛出 CongestiveNotValidException
- 用于实现复杂的业务规则验证
2. validateDelete
- 在删除聚合根前执行
- 验证失败时抛出 CongestiveNotValidException
- 用于确保删除操作不会破坏业务规则
#### 使用示例
1. 复杂业务规则验证
```java
@Component
public class OrderValidator implements CongestiveValidator {
@Override
public void validateSave(Order order) {
// 验证订单金额
if (order.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
throw new CongestiveNotValidException("订单金额必须大于0");
}
// 验证订单项
if (order.getItems().isEmpty()) {
throw new CongestiveNotValidException("订单必须包含至少一个商品");
}
// 验证收货地址
if (order.getDeliveryAddress() == null) {
throw new CongestiveNotValidException("收货地址不能为空");
}
}
}
```
2. 组合验证规则
```java
@Component
public class ProjectValidator implements CongestiveValidator {
@Override
public void validateSave(Project project) {
validateProjectDates(project);
validateProjectMembers(project);
validateProjectBudget(project);
}
private void validateProjectDates(Project project) {
if (project.getEndDate().isBefore(project.getStartDate())) {
throw new CongestiveNotValidException("项目结束日期不能早于开始日期");
}
}
private void validateProjectMembers(Project project) {
if (project.getMembers().isEmpty()) {
throw new CongestiveNotValidException("项目必须至少有一个成员");
}
}
private void validateProjectBudget(Project project) {
if (project.getBudget().compareTo(BigDecimal.ZERO) <= 0) {
throw new CongestiveNotValidException("项目预算必须大于0");
}
}
}
```
#### 最佳实践
1. 验证规则设计
- 优先使用 Bean Validation 注解进行基础字段验证
- 在 validateSave 中实现复杂的业务规则验证
- 保持验证逻辑的清晰和可维护性
2. 异常处理
- 使用明确的错误消息
- 统一使用 CongestiveNotValidException 抛出验证失败
- 在全局异常处理器中统一处理验证异常
3. 性能考虑
- 避免在验证器中执行重量级操作
- 合理使用缓存减少数据库查询
- 验证逻辑应该是幂等的
4. 代码组织
- 将复杂的验证逻辑拆分为多个私有方法
- 保持验证方法的单一职责
- 适当添加注释说明验证规则
## Trouble 异常处理模块
### 概述
Trouble 模块提供了一套统一的异常定义和处理机制,通过枚举和注解的方式,实现了业务异常的标准化定义。
主要特性:
1. 基于枚举的异常定义
2. 支持异常码前缀
3. 链式的异常构建方式
4. 与 HTTP 状态码的自然映射
### 核心组件
#### 1. Trouble 注解
用于在枚举字段上定义异常信息:
```java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Trouble {
HttpStatus status() default HttpStatus.BAD_REQUEST; // HTTP状态码
String code(); // 异常码
String message(); // 异常消息
}
```
#### 2. TroublePrefix 注解
用于在枚举类上定义异常码前缀:
```java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TroublePrefix {
String value(); // 异常码前缀
}
```
#### 3. TroubleEnum 接口
异常枚举需要实现的接口:
```java
public interface TroubleEnum extends AnnotationEnum {
default TroubleException asException() {
var troublePrefix = getClassAnnotation(TroublePrefix.class);
String prefix = troublePrefix == null ? "" : troublePrefix.value();
var trouble = getFieldAnnotation(Trouble.class);
return new TroubleException(trouble.status(), prefix + trouble.code(), trouble.message());
}
}
```
### 使用示例
1. 定义异常枚举:
```java
@TroublePrefix("USER")
public enum UserTrouble implements TroubleEnum {
@Trouble(
code = "001",
message = "用户不存在"
)
USER_NOT_FOUND,
@Trouble(
code = "002",
message = "用户名已被使用",
status = HttpStatus.CONFLICT
)
USERNAME_ALREADY_EXISTS
}
```
2. 使用异常:
```java
@Service
public class UserService {
public User getUser(String userId) {
return userRepository.findById(userId)
.orElseThrow(() -> UserTrouble.USER_NOT_FOUND
.asException()
.detail("用户ID: " + userId)
.thrown()
);
}
public void createUser(String username) {
if (userRepository.existsByUsername(username)) {
UserTrouble.USERNAME_ALREADY_EXISTS
.asException()
.detail("用户名: " + username)
.thrown();
}
try {
// 业务逻辑
} catch (Exception e) {
UserTrouble.USERNAME_ALREADY_EXISTS
.asException()
.detail("创建用户失败")
.cause(e)
.thrown();
}
}
}
```
### 异常处理
TroubleException 提供了链式的异常构建方法:
```java
SomeTrouble.SOME_ERROR
.asException() // 创建异常实例, 返回一个 TroubleException 实例
.detail("详细信息") // 通过TroubleException 的 detail 方法设置详细信息
.cause(otherException) // 通过TroubleException 的 cause 方法设置原因异常
.thrown(); // 通过TroubleException 的 thrown 方法抛出异常
```
异常信息结构:
```java
public class TroubleException extends RuntimeException {
private final HttpStatus status; // HTTP状态码
private final String code; // 异常码
private final String message; // 异常消息
private String detailMessage; // 详细信息
}
```
### 最佳实践
1. 异常定义
- 使用有意义的前缀区分不同领域的异常
- 异常码应该具有规律性和可读性
- 异常消息应该简洁明确
- 合理使用 HTTP 状态码映射业务语义
2. 异常使用
- 使用 asException() 创建异常实例
- 使用 detail() 提供更多上下文信息
- 使用 cause() 保留原始异常信息
- 使用 thrown() 显式抛出异常
3. 异常处理
- 在全局异常处理器中统一处理
- 合理记录异常日志
- 确保异常信息的安全性
- 提供有意义的错误响应
4. 注意事项
- 异常码应全局唯一
- 避免在异常消息中包含敏感信息
- 详细信息应该有助于问题诊断
- 保持异常处理的一致性
## Enumeration 枚举增强模块
### 概述
Enumeration 模块提供了一套增强的枚举处理机制,通过注解和接口的方式,使枚举类型能够携带更多的元数据信息,并支持灵活的数据解析。
主要特性:
1. 支持为枚举添加任意键值对属性
2. 支持属性值的自定义解析
3. 提供统一的注解访问机制
4. 支持枚举数据的序列化
### 核心组件
#### 1. AnnotationEnum 接口
提供基础的枚举注解访问能力:
```java
public interface AnnotationEnum {
// 获取当前枚举实例
default Enum> thisEnum();
// 获取枚举字段上的注解
default T getFieldAnnotation(Class annotationClass);
// 获取枚举类上的注解
default T getClassAnnotation(Class annotationClass);
}
```
#### 2. BeautifulEnum 接口
继承自 AnnotationEnum,提供枚举数据序列化能力:
```java
public interface BeautifulEnum extends AnnotationEnum {
// 获取枚举的所有属性数据
default Map getEnumData();
}
```
#### 3. EnumAttribute 注解
用于定义枚举字段的属性:
```java
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(EnumAttributes.class)
public @interface EnumAttribute {
String key(); // 属性键
String value(); // 属性值
Class extends AttributeValueParser> parser() default StringParser.class; // 值解析器
}
```
#### 4. AttributeValueParser 接口
用于自定义属性值的解析逻辑:
```java
public interface AttributeValueParser {
T parse(String value);
}
```
### 使用示例
1. 基本使用:
```java
public enum UserStatus implements BeautifulEnum {
@EnumAttribute(key = "text", value = "活跃")
@EnumAttribute(key = "color", value = "green")
ACTIVE,
@EnumAttribute(key = "text", value = "已禁用")
@EnumAttribute(key = "color", value = "red")
DISABLED
}
```
2. 使用自定义解析器:
```java
// 定义解析器
public class JsonParser implements AttributeValueParser