外观
核心工具(nebula-framework-core)
2026-04-01
nebula-framework-core是整个 Nebula 框架的基石,提供统一的 HTTP 响应包装、分页模型、异常体系和 JSON 工具。
所有业务服务、框架模块都可以直接依赖它,它不引入任何 Spring 运行时依赖,可在任意 Java 环境使用。
目录
一、统一响应 R<T>
1.1 字段结构
所有 HTTP 接口必须返回 R<T> 类型:
public class R<T> {
private int code; // 状态码:0 表示成功
private String message; // 提示信息
private String traceId; // 链路追踪 ID(由框架自动注入,无需手动填写)
private T data; // 业务数据
}响应示例:
{
"code": 0,
"message": "操作成功",
"traceId": "2036344300517855232",
"data": { "id": 1001, "name": "示例数据" }
}1.2 创建响应对象
// 成功,无数据
R.ok()
// 成功,带数据
R.ok(demoRespVO)
// 成功,带自定义消息和数据
R.ok("查询成功", demoRespVO)
// 失败,使用全局错误码
R.fail(GlobalErrorCode.PARAM_INVALID)
// 失败,使用错误码 + 自定义消息
R.fail(GlobalErrorCode.DATA_NOT_FOUND, "用户 ID 不存在")
// 失败,使用自定义 code + message
R.fail(40001, "编码已存在")
// 失败,仅消息(code 默认 BUSINESS_ERROR)
R.fail("操作失败,请重试")1.3 Controller 规范
// ✅ 有数据的查询接口
@GetMapping("/{id}")
public R<DemoDetailVO> getDemoById(@PathVariable Long id) {
return R.ok(demoService.getDemoById(id));
}
// ✅ 写操作,无返回值
@PutMapping
public R<Void> updateDemo(@RequestBody DemoSaveParamVO saveParam) {
demoService.updateDemo(saveParam);
return R.ok();
}
// ✅ 新增,返回新记录的 id
@PostMapping
public R<Long> createDemo(@Valid @RequestBody DemoSaveParamVO saveParam) {
return R.ok(demoService.createDemo(saveParam));
}
// ❌ 禁止直接返回裸对象
@GetMapping("/{id}")
public DemoDetailVO getDemoById(@PathVariable Long id) { ... }traceId 说明:
R.ok()/R.fail()内部通过MDC.get("traceId")自动注入,业务代码无需手动填写。前提是引入了nebula-boot-starter-trace。
二、分页模型
2.1 分页入参 PageParam
所有分页查询的入参 VO 必须继承 PageParam:
public class PageParam {
private int pageNo = 1; // 页码,从 1 开始
private int pageSize = 10; // 每页条数,最大 500
private List<SortItem> sorts; // 排序规则列表
}// SortItem 字段
public class SortItem {
private String column; // 排序字段(驼峰命名)
private boolean ascending; // true=升序,false=降序
}使用方式:
// 入参 VO 继承 PageParam
@Data
@EqualsAndHashCode(callSuper = true)
public class DemoPageParamVO extends PageParam {
private String demoName;
private Integer status;
}
// Controller 接收
@PostMapping("/page")
public R<PageResult<DemoRespVO>> pageDemo(@RequestBody DemoPageParamVO query) {
return R.ok(demoService.pageDemo(query));
}2.2 分页结果 PageResult<T>
public class PageResult<T> {
private List<T> records; // 当前页数据列表
private long total; // 总记录数
private int pageNo; // 当前页码
private int pageSize; // 每页条数
private int pages; // 总页数
}创建 PageResult:
// 从 MyBatis-Plus Page 对象构建
PageResult.of(result.getRecords(), count, query);
// 空结果(总数为 0)
PageResult.empty(query);
// 批量类型转换(DO → VO)
PageResult<DemoRespVO> voPage = doPage.convert(DemoConvert.INSTANCE::doToRespVO);常用方法:
pageResult.hasRecords() // 是否有数据
pageResult.isFirstPage() // 是否第一页
pageResult.isLastPage() // 是否最后一页三、异常体系
3.1 异常类型
Nebula 定义了两种业务运行时异常,严格区分业务失败与系统错误:
| 异常类 | 使用场景 | HTTP 状态码 |
|---|---|---|
BusinessException | 业务校验失败(参数非法、数据不存在、状态不符) | 200(code 为错误码) |
SystemException | 系统级失败(IO 异常、外部调用失败、序列化异常) | 500 |
3.2 BusinessException 使用
// 使用全局错误码
throw new BusinessException(GlobalErrorCode.PARAM_INVALID);
// 使用错误码 + 自定义消息
throw new BusinessException(GlobalErrorCode.PARAM_INVALID.getCode(),
"编码 [" + demoCode + "] 已存在,请更换");
// 使用 IErrorCode 工厂方法(推荐)
throw BusinessException.of(GlobalErrorCode.DATA_NOT_FOUND);
throw BusinessException.of(GlobalErrorCode.PARAM_INVALID, "名称不能超过 100 个字符");3.3 SystemException 使用
// IO 异常:包装为 SystemException
try {
StreamUtils.copy(in, out);
} catch (IOException e) {
throw new SystemException(GlobalErrorCode.INTERNAL_SERVER_ERROR, "文件下载失败", e);
}
// 外部调用超时
throw SystemException.wrap("调用第三方接口超时", e);3.4 GlobalErrorCode 枚举
| 错误码 | 常量名 | 说明 |
|---|---|---|
| 0 | SUCCESS | 成功 |
| 400 | BAD_REQUEST | 请求错误 |
| 400001 | PARAM_MISSING | 必填参数缺失 |
| 400002 | PARAM_INVALID | 参数校验失败 |
| 400003 | REQUEST_BODY_INVALID | 请求体解析失败 |
| 401 | UNAUTHORIZED | 未登录/Token 缺失 |
| 401001 | TOKEN_EXPIRED | Token 已过期 |
| 401002 | TOKEN_INVALID | Token 无效 |
| 403 | FORBIDDEN | 无权限 |
| 404 | NOT_FOUND | 资源不存在 |
| 429 | TOO_MANY_REQUESTS | 请求过于频繁(限流) |
| 200001 | BUSINESS_ERROR | 通用业务错误 |
| 200002 | DATA_EXISTS | 数据已存在(唯一性冲突) |
| 200003 | DATA_NOT_FOUND | 数据不存在 |
| 200004 | DATA_STATE_ERROR | 数据状态不允许该操作 |
| 200005 | REPEATED_REQUEST | 重复提交 |
| 500 | INTERNAL_SERVER_ERROR | 系统内部错误 |
| 503 | SERVICE_UNAVAILABLE | 服务不可用 |
| 500001 | DB_ERROR | 数据库错误 |
| 500002 | SYSTEM_ERROR | 系统错误 |
| 500003 | THIRD_PARTY_ERROR | 第三方服务错误 |
| 500004 | REMOTE_TIMEOUT | 远程调用超时 |
常用场景对应: 参数非法用
PARAM_INVALID;数据不存在用DATA_NOT_FOUND;唯一性冲突用DATA_EXISTS;IO/外部调用用INTERNAL_SERVER_ERROR。
四、JSON 工具 JsonUtils
Nebula 对 Jackson 做了统一封装,禁止业务代码 new ObjectMapper(),统一通过 JsonUtils 操作 JSON。
模块: nebula-framework-core
类名: com.huida.nebula.core.json.JsonUtils
4.1 序列化(对象 → JSON)
// 对象转 JSON 字符串
String json = JsonUtils.toJsonString(obj);
// 格式化(带缩进)输出
String pretty = JsonUtils.toPrettyJsonString(obj);
// 静默模式:序列化失败返回空字符串而不是抛异常(适合日志打印)
String safeJson = JsonUtils.toJsonStringOrEmpty(obj);
// 静默模式:返回 Optional
Optional<String> opt = JsonUtils.toJsonStringOptional(obj);4.2 反序列化(JSON → 对象)
// JSON → 单个对象
MyDTO dto = JsonUtils.parseObject(json, MyDTO.class);
// JSON → 带泛型的对象(如 List、Map)
List<MyDTO> list = JsonUtils.parseArray(json, MyDTO.class);
// JSON → Map<String, Object>
Map<String, Object> map = JsonUtils.parseMap(json);
// JSON → Map<String, String>
Map<String, String> strMap = JsonUtils.parseMap(json, String.class, String.class);
// 复杂泛型(如 Map<String, List<MyDTO>>)
Map<String, List<MyDTO>> complexMap = JsonUtils.parseObject(json,
new TypeReference<Map<String, List<MyDTO>>>(){});4.3 类型转换
// 对象 → 对象(常用于 DTO 互转,内部通过 JSON 中转)
TargetDTO target = JsonUtils.convert(sourceDTO, TargetDTO.class);
// 对象 → 带泛型的对象
PageResult<TargetDTO> page = JsonUtils.convert(source, new TypeReference<PageResult<TargetDTO>>(){});4.4 其他工具
// 校验字符串是否为合法 JSON
boolean valid = JsonUtils.isValidJson(str);
// 获取全局单例 ObjectMapper(需要个性化配置时使用)
ObjectMapper mapper = JsonUtils.getObjectMapper();4.5 典型使用场景
| 场景 | 推荐用法 |
|---|---|
| 任务参数反序列化 | JsonUtils.parseObject(ctx.getRawParams(), XxxParam.class) |
| Redis 存储/读取复杂对象 | JsonUtils.toJsonString(obj) / JsonUtils.parseObject(str, Clazz.class) |
| 外部 API 响应解析 | JsonUtils.parseObject(responseBody, ResultDTO.class) |
| 日志打印对象 | JsonUtils.toJsonStringOrEmpty(obj) |
五、其他常用工具类
| 工具类 | 说明 |
|---|---|
DateUtils | 日期格式化/解析,含 DatePattern 常量(如 NORM_DATETIME_PATTERN) |
StringUtils | 扩展 String 工具,含 hasText(等同 Spring 的同名方法) |
IdUtils | ID 生成(雪花算法封装) |
CollectionUtils | 集合工具(分批、转换等) |
AesUtils / RsaUtils | AES/RSA 加解密 |
DigestUtils | MD5 / SHA 摘要 |
SpelExpressionUtils | Spring EL 表达式解析(用于防重 key 计算等) |
MDCUtils | MDC 常量(MDC_TRACE_ID 等 key 名称) |
AssertUtils | 断言工具,失败时抛 BusinessException |
