Core 核心模块
Core 模块是 sh-framework 框架的核心基础组件,提供了应用程序开发所需的基础技术能力和通用架构组件。它封装了开发中常用的非业务性技术组件、基础实体、异常处理、响应封装等核心功能。
模块概述
核心价值
- 标准化:统一技术实现标准,提升代码一致性
- 高效性:减少重复代码编写,提高开发效率
- 可维护性:集中管理基础组件,便于维护和升级
- 扩展性:提供灵活的扩展机制,支持定制化需求
解决的问题
- 基础实体重复定义问题
- 响应格式不统一问题
- 异常处理混乱问题
- 用户上下文管理复杂问题
- 代码描述信息缺失问题
核心功能特性
1. 基础实体类
- DbColumnEntity:数据库基础字段实体(ID、创建时间、更新时间等)
- BaseEntity:扩展基础实体(分页、查询、用户信息等辅助功能)
- UserInfo:用户基础信息实体(用户编码、用户名、租户编码等)
2. 统一响应封装
- R<T>:统一API响应格式(响应码、消息、数据、耗时等)
- PageData<T>:统一分页响应格式(分页信息和数据列表)
3. 异常处理体系
- CommonException:基础业务异常类
- 专用异常类:ValidationException、UnauthorizedException、NotFoundException等
- 异常工厂方法:支持字符串模板的静态工厂方法
4. 结果码枚举 (ResultCode)
完整的结果码体系,涵盖:
- 基础状态码(200、400、401、404、500)
- Token相关(10000系列)
- 应用/租户相关(10100系列)
- 用户认证相关(30000系列)
- 数据操作相关(40000系列)
- 订单相关(60000系列)
5. 注解系统
- @FieldDesc:字段描述注解(描述信息 + 是否非空)
- @ApiDesc:API描述注解
- @Router:路由注解
- @Desc:通用描述注解(已废弃)
6. 用户上下文管理
- UserContext:基于ThreadLocal的用户上下文工具类
- UserNameProvider:用户名提供者SPI接口
7. 其他功能
- EnvType:系统环境类型枚举(DEV、SIT、UAT、PROD)
- MaskingPatternLayout:日志脱敏处理布局
快速开始
1. 添加依赖
xml
<dependency>
<groupId>com.wkclz.framework</groupId>
<artifactId>sh-core</artifactId>
</dependency>2. 使用基础实体
java
@Data
public class UserEntity extends BaseEntity {
@FieldDesc("用户名")
private String username;
@FieldDesc("邮箱")
private String email;
}3. 使用统一响应
java
@RestController
@RequestMapping("/api/user")
public class UserController {
@GetMapping("/{id}")
@ApiDesc("根据ID查询用户")
public R<UserEntity> getUser(@PathVariable Long id) {
UserEntity user = userService.getById(id);
if (user == null) {
return R.error(ResultCode.NOT_FOUND);
}
return R.ok(user);
}
@PostMapping
@ApiDesc("创建用户")
public R<UserEntity> createUser(@RequestBody @Valid UserEntity user) {
UserEntity created = userService.create(user);
return R.ok(created);
}
}4. 使用分页查询
java
@Service
public class UserService {
public R<PageData<UserEntity>> getUsers(BaseEntity query) {
// 初始化分页参数
query.init();
// 查询数据
List<UserEntity> userList = userMapper.selectUsers(query);
Long total = userMapper.countUsers(query);
// 返回分页结果
PageData<UserEntity> pageData = PageData.of(userList, total, query.getCurrent(), query.getSize());
return R.ok(pageData);
}
}5. 使用异常处理
java
@Service
public class OrderService {
public OrderEntity getOrder(Long orderId) {
OrderEntity order = orderMapper.selectById(orderId);
if (order == null) {
// 使用预定义的结果码
throw new NotFoundException(ResultCode.RECORD_NOT_EXIST);
}
if (order.getStatus() == OrderStatus.PAID) {
// 使用自定义消息
throw new CommonException("订单已支付,不能重复支付");
}
// 使用字符串模板
if (order.isExpired()) {
throw CommonException.of("订单 {} 已超时,请重新下单", orderId);
}
return order;
}
}6. 使用用户上下文
java
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 从请求中解析用户信息
UserInfo userInfo = extractUserInfo(request);
// 设置到用户上下文
UserContext.setUserInfo(userInfo);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// 请求完成后清除用户上下文
UserContext.clear();
}
}java
@Service
public class AuditService {
public void saveAuditLog(String action, String resource) {
AuditLog log = new AuditLog();
log.setAction(action);
log.setResource(resource);
// 从用户上下文获取用户信息
UserInfo userInfo = UserContext.getUserInfo();
if (userInfo != null) {
log.setUserCode(userInfo.getUserCode());
log.setTenantCode(userInfo.getTenantCode());
log.setUsername(userInfo.getUsername());
}
auditMapper.insert(log);
}
}7. 实现SPI扩展
java
@Component
public class CustomUserNameProvider implements UserNameProvider {
@Autowired
private UserService userService;
@Override
public Map<String, String> getNamesByUserCodes(Set<String> userCodes) {
if (userCodes == null || userCodes.isEmpty()) {
return Collections.emptyMap();
}
// 查询用户信息
List<UserEntity> users = userService.getByUserCodes(userCodes);
// 构建映射关系
return users.stream()
.collect(Collectors.toMap(
UserEntity::getUserCode,
UserEntity::getUsername
));
}
}8. 使用日志脱敏
xml
<!-- logback.xml配置 -->
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<layout class="com.wkclz.core.log.MaskingPatternLayout">
<!-- 添加脱敏规则 -->
<maskPattern>(\d{3})\d{4}(\d{4})</maskPattern> <!-- 手机号 -->
<maskPattern>(\w{3})\w+@(\w+\.\w+)</maskPattern> <!-- 邮箱 -->
<maskPattern>"password":"([^"]+)"</maskPattern> <!-- 密码 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</layout>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>最佳实践指南
1. 实体设计规范
- 统一继承BaseEntity:所有数据库实体都应继承BaseEntity
- 合理使用注解:为重要字段添加FieldDesc注解
- 版本控制:使用version字段实现乐观锁
- 分页参数初始化:调用query.init()初始化分页参数
2. 响应设计规范
- 统一响应格式:所有API返回R<T>类型响应
- 合理使用状态码:根据业务场景选择ResultCode
- 分页标准化:分页查询使用PageData<T>封装
- 错误信息友好:提供清晰的错误提示信息
3. 异常处理规范
- 异常分类明确:根据异常类型选择合适异常类
- 异常信息友好:提供清晰的异常描述
- 异常链完整:保留原始异常信息
- 统一异常处理:使用@ControllerAdvice统一处理
4. 用户上下文规范
- 及时设置清除:在拦截器中设置,请求完成后清除
- 避免内存泄漏:确保ThreadLocal被正确清理
- 上下文验证:使用前验证用户上下文是否存在
- SPI扩展实现:根据需求实现UserNameProvider
5. 日志安全规范
- 敏感信息脱敏:配置脱敏规则保护用户隐私
- 日志级别合理:根据重要性设置合适的日志级别
- 日志格式统一:使用统一的日志格式
- 异常日志完整:记录完整的异常堆栈信息
常见问题解答
Q1: 为什么需要继承BaseEntity?
A: BaseEntity提供了数据库通用字段和分页查询辅助功能,避免在每个实体中重复定义这些字段,提高代码复用性和一致性。
Q2: 如何自定义异常消息格式?
A: 可以使用字符串模板功能:CommonException.of("用户 {} 不存在", userId),支持参数化消息。
Q3: 用户上下文在多线程环境下是否安全?
A: UserContext基于ThreadLocal实现,每个线程有独立的副本,在多线程环境下是安全的。但需要注意在异步任务中手动传递用户上下文。
Q4: 如何扩展结果码体系?
A: 可以在ResultCode枚举中添加新的结果码,建议按照功能模块分类(如10000系列为Token相关,30000系列为用户认证相关)。
Q5: 日志脱敏支持哪些模式?
A: 支持正则表达式模式,可以配置手机号、邮箱、密码、身份证号等常见敏感信息的脱敏规则。
Q6: SPI扩展如何生效?
A: 实现UserNameProvider接口并添加@Component注解,框架会自动发现并加载该实现。
贡献指南
1. 代码规范
- 遵循Java编码规范
- 使用Lombok减少样板代码
- 添加必要的单元测试
- 保持向后兼容性
2. 文档要求
- 为新增功能添加使用示例
- 更新API文档
- 添加必要的注释
- 提供迁移指南(如有破坏性变更)
3. 测试要求
- 单元测试覆盖率不低于80%
- 集成测试覆盖主要功能
- 性能测试验证关键路径
- 兼容性测试确保向后兼容
4. 发布流程
- 功能开发完成
- 编写测试用例
- 更新文档
- 代码审查
- 合并到主分支
- 版本发布
版本兼容性
当前版本:1.0.0
- 基础实体类稳定
- 异常体系完善
- 响应格式标准化
- 用户上下文管理
未来规划
- 增强国际化支持
- 优化性能表现
- 扩展SPI机制
- 增强监控能力
总结
Core模块作为sh-framework的技术基础,提供了完整的基础技术能力支持。通过合理使用Core模块的各项功能,开发者可以:
- 大幅减少重复代码编写
- 统一技术实现标准
- 提高代码质量和可维护性
- 快速构建稳定可靠的应用程序
建议新项目从一开始就集成Core模块,充分利用其提供的标准化组件,确保项目技术架构的一致性和可维护性。