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<user> result = Result.success(user);</user>→ data 是 User 类型 -
Result<list>> result = Result.success(orders);</list>→ data 是 List -
Result<void> result = Result.success();</void>→ 明确表示无返回数据
扩展支持分页场景(嵌套泛型)
列表接口常需分页信息(总条数、当前页、每页大小等),可单独定义 PageResult<t></t>,它继承或组合 Result<page>></page>,但更推荐聚合方式,保持单一职责:
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<t></t> 是你自己的分页实体(含 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<user></user> -
public void deleteOrder(Long id) { ... }→ 自动转成Result<void></void>
异常情况再配合 @ExceptionHandler 返回 Result.fail(...) 即可。
注意 JSON 序列化兼容性(Jackson)
泛型在运行时被擦除,但 Jackson 能通过泛型签名正确反序列化 Result<user></user>。前提是:
- 前端传入的 JSON 字段名与 Java 字段严格匹配(或用
@JsonProperty标注) - 若用
ObjectMapper.readValue(json, new TypeReference<result>>(){})</result>,TypeReference 必须显式指定泛型,否则 data 会变成 LinkedHashMap - 避免在泛型字段上滥用
@JsonAnyGetter或@JsonUnwrapped,易破坏结构
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











