Java通用数据返回包装类应使用泛型Result统一响应结构,支持success/fail工厂方法、分页扩展PageResult,结合@ControllerAdvice自动包装,确保类型安全与JSON兼容。

Java 中设计通用的数据返回包装类,核心是用泛型替代具体类型,让同一个类能适配不同业务数据,同时保持类型安全和可读性。关键不是“写个泛型类”就行,而是要兼顾实际使用场景:比如统一响应结构、支持成功/失败状态、兼容分页、便于 JSON 序列化等。
定义基础泛型响应类(含状态与数据)
一个典型的返回包装类至少包含状态码、提示信息、时间戳和泛型数据体。用泛型参数 T 表示业务数据类型,避免强制转型或 Object 带来的隐患:
public class Result<t> {
private int code; // 状态码,如 200、500
private String message; // 提示信息
private long timestamp; // 响应时间戳
private T data; // 业务数据,类型由调用方决定
// 私有构造,强制通过静态工厂方法创建
private Result(int code, String message, T data) {
this.code = code;
this.message = message;
this.timestamp = System.currentTimeMillis();
this.data = data;
}
// 成功响应(带数据)
public static <t> Result<t> success(T data) {
return new Result(200, "OK", data);
}
// 成功响应(无数据)
public static Result<void> success() {
return new Result(200, "OK", null);
}
// 失败响应
public static <t> Result<t> fail(int code, String message) {
return new Result(code, message, null);
}
// getter 方法(略,按需生成)
}</t></t></void></t></t></t>
这样调用时类型一目了然:
-
Result→ data 是 User 类型result = Result.success(user); -
Result→ data 是 List- > result = Result.success(orders);
-
Result→ 明确表示无返回数据result = Result.success();
扩展支持分页场景(嵌套泛型)
列表接口常需分页信息(总条数、当前页、每页大小等),可单独定义 PageResult,它继承或组合 Result,但更推荐聚合方式,保持单一职责:
public class PageResult<t> extends Result<page>>
public PageResult(Page<t> page) {
super(200, "OK", page);
}
public static <t> PageResult<t> of(Page<t> page) {
return new PageResult(page);
}
}</t></t></t></t></page></t>
其中 Page 是你自己的分页实体(含 total、list、pageNum 等字段),这样 JSON 输出结构清晰,前端也容易解析。
配合 Spring Boot 统一返回(避免重复写 Result)
在 Controller 层,不建议每个方法都手动 new Result。可用 @ControllerAdvice + @ResponseBodyAdvice 实现自动包装:
@ControllerAdvice
public class ResultResponseAdvice implements ResponseBodyAdvice<object> {
@Override
public boolean supports(MethodParameter returnType, Class extends HttpMessageConverter>> converterType) {
// 只对未返回 Result 的接口生效(避免嵌套包装)
return !Result.class.isAssignableFrom(returnType.getParameterType());
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType, Class extends HttpMessageConverter>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof Result) {
return body; // 已经是 Result,不处理
}
return Result.success(body); // 自动包装为成功响应
}
}</object>
之后 Controller 可直接写:
-
public User getUserById(Long id) { ... }→ 自动转成Result -
public void deleteOrder(Long id) { ... }→ 自动转成Result
异常情况再配合 @ExceptionHandler 返回 Result.fail(...) 即可。
注意 JSON 序列化兼容性(Jackson)
泛型在运行时被擦除,但 Jackson 能通过泛型签名正确反序列化 Result。前提是:
- 前端传入的 JSON 字段名与 Java 字段严格匹配(或用
@JsonProperty标注) - 若用
ObjectMapper.readValue(json, new TypeReference,TypeReference 必须显式指定泛型,否则 data 会变成 LinkedHashMap>(){}) - 避免在泛型字段上滥用
@JsonAnyGetter或@JsonUnwrapped,易破坏结构
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











