我们再开发后端代码的时候都会遇到工程化的问题,这个时候将公共的基础设施挪出来分包就非常有必要,就是我们的公共基础模块。
一、模块概述
common是我的项目中的公共基础模块,提供所有业务共享的基础设施。该模块不依赖任何业务模块,被所有其他模块依赖
目录结构
common/
├── src/main/java/com/aryi/common/
│ ├── annotation/ # 自定义注解
│ │ └── DataScope.java
│ ├── config/ # 配置类
│ │ └── JacksonConfig.java
│ ├── entity/ # 实体类
│ │ └── BaseEntity.java
│ ├── exception/ # 异常处理
│ │ ├── BusinessException.java
│ │ └── GlobalExceptionHandler.java
│ ├── result/ # 返回结果封装
│ │ ├── Result.java
│ │ └── PageResult.java
│ └── util/ # 工具类
│ └── RsaUtils.java
└── pom.xml
二、类关系
核心类关系
Controller层的所有模块都会依赖于common层中的统一返回Result<T>、PageResult<T>、业务异常BusinessException等等这些类来帮助我们更好的去处理后端的功能和逻辑,接下来我来详细说说我的公共基础设施层都是怎么去使用的
实体继承类(BaseEntity)
BaseEntity作为所有业务实体的父类,提供通用的字段和行为。使用MyBatis Plus的注解实现自动填充和逻辑删除,通过继承此类所有实体都将获得统一的审计字段和序列化支持。
设计的目的
1.统一实体结构,减少重复代码
2.自动填充创建/更新时间爱和操作人
3.统一逻辑删除实现
id: 主键,自增策略 createTime: 创建时间,插入时自动填充 updateTime: 更新时间,插入和更新时自动填充 createBy: 创建人ID,插入时自动填充 updateBy: 更新人ID,插入和更新时自动填充 deleted: 删除标识,0-未删除,1-已删除(逻辑删除)配置与数据流向(JacksonConfig全局配置类 与 DataScope数据权限过滤注解)
JacksonConfig
统一配置Java 8日期时间类型序列化/反序列化格式,避免前端接收日期格式不一致的问题。配置后,所有通过Jackson序列化的LocalDateTime和LocalDate都会统一使用指定格式。
主要解决的问题:
1.LocalDateTime默认序列化为数组格式[2024, 1, 1, 12, 0, 0]
2.前端日期格式不统一导致解析失败
3.时区问题导致的时间差
LocalDateTime → "2024-01-01 12:00:00" LocalDate → "2024-01-01"DataScope
用于标记需要进行数据权限控制的Mapper方法,配合MyBatis Plus拦截器实现数据范围过滤。通过部门标和用户表的别名,动态拼接WHERE条件,实现不同角色看到不同数据的需求
典型应用场景:
管理员:查看所有数据
部门管理员:查看本部门数据
普通用户:仅查看自己的数据
// 统一实体结构 → 减少重复代码 // 自动填充时间/操作人 → 减轻开发负担 // 逻辑删除 → 数据安全,可恢复 {@code @DataScope(deptAlias = "d", userAlias = "u")} List<SysUser> selectUserList(SysUser user);业务异常类(BusinessExeption)
用于封装业务逻辑层抛出的异常,携带自定义错误码和错误信息。与GlobalExceptionHandler配合使用,实现异常的统一处理和友好返回。
设计特点:
1.继承RuntimeExcetion,无需强制try-catch
2.携带错误码,自定义错误状态
3.通过@Getter注解自动生成getter方法
参数校验失败(如:用户名已存在) 业务规则不满足(如:余额不足) 资源不存在(如:用户不存在)全局异常处理器(GlobalExceptionHandler )
使用@RestControllerAdvice注解,统一捕获并处理Controller层抛出的所有异常。将异常转换为统一的Result格式返回给前端,避免之间暴露堆栈信息,同时提供友好的错误提示
处理的异常类型:
1.BusinessException:业务异常,携带自定义错误码和信息
2.NotLoginException:未登录异常(Sa-Token)
3.NotPermissionERxception:无权限异常
4.NotRoleException:无角色异常
5.MethodArgumentNotValidException:参数校验异常(@Valid)
6.BindException:参数绑定异常
7.RuntimeException:运行时异常
8.IllegalArgumentExeption:非法参数异常
9.Exception:兜底异常处理
// 参数校验失败 throw new BusinessException("用户名已存在"); // 业务规则不满足 throw new BusinessException(400, "余额不足"); // 资源不存在 throw new BusinessException(404, "用户不存在");统一返回结果类(Result)
所有Controller接口的统一返回格式,封装响应码、响应信息和响应数据。提供静态工厂方法,简化返回结果的创建
字段说明:
1.code:响应码,200表示成功,其他表示失败
2.message:响应信息,描述操作结果
3.data:响应数据,泛型类型,可包含任意数据结构
返回格式示例: // 成功(无数据) { "code": 200, "message": "操作成功", "data": null } // 成功(有数据) { "code": 200, "message": "操作成功", "data": { ... } } // 失败(默认错误码) { "code": 500, "message": "操作失败", "data": null } // 失败(自定义错误码) { "code": 400, "message": "参数校验失败", "data": null } // 查询成功 return Result.ok(user); // 删除成功 return Result.ok(); // 参数校验失败 return Result.fail(400, "用户名不能为空");分页返回结果类(PageResult)
统一封装分页查询结果,提供多种静态工厂方法便捷创建实例。与MyBatis Plus的IPage接口无缝对接,简化分页结果的处理。
字段说明:
list:当前页数据列表
total:总记录数
page:当前页码
pageSize:每页条数
// 从MyBatis Plus分页 IPage<User> page = userMapper.selectPage(new Page<>(1, 10), wrapper); return Result.ok(PageResult.of(page)); // 返回空结果 return Result.ok(PageResult.empty());RSA加解密工具类(RsaUtils)
提供RSA非对称加密和解密功能,支持分段加密处理大数据。以及AES+RSA混合加密方案(推荐用于大数据加密场景)。
核心特性:
1.标准RSA加密:公钥加密、私钥解密;私钥加密、公钥解密
2.分段加密:支持超过RSA单次加密限制的数据
3.混合加密:AES加密数据 + RSA加密AES密钥,兼顾安全性和性能
4.密钥长度:2048为(标准安全级别)
技术参数:
1.RSA密钥长度:2048位
2.AES密钥长度:256位
3.加密模式:RSA/ECB/PKCS1Padding
4.AES模式:AES/GCM/NoPadding(带认证的加密)
5.编码:Base64
// 登录密码加密传输 // 敏感数据存储加密 // API接口数据加密 // 前后端密钥交换我的公共基础层的设计模式
统一返回模式
全局异常处理模式
实体类继承模式
总结
基本每次写些新项目这些公共基础都会写,写博客也是为了节省时间