本文目录导读:

在Java开发中,统一返回结构(Response Structure) 是为了让前端、API调用者或服务间通信能有一致的契约,方便解析和错误处理,下面给你一个标准、通用的统一返回结构案例。
核心设计思路
一个通用的返回结构通常包含以下几个核心字段:
| 字段名 | 类型 | 含义 | 是否必须 |
|---|---|---|---|
code |
int | 业务状态码(非HTTP状态码) | 是 |
message |
String | 提示信息 | 是 |
data |
T (泛型) | 返回的实际数据 | 否 |
success |
boolean | 是否成功(可选) | 建议有 |
完整代码实现
1 定义响应状态码枚举
public enum ResponseCode {
SUCCESS(200, "操作成功"),
FAIL(500, "操作失败"),
// 参数校验
PARAM_ERROR(400, "参数错误"),
PARAM_MISSING(400, "缺少必要参数"),
// 权限
UNAUTHORIZED(401, "未登录或 token 过期"),
FORBIDDEN(403, "没有操作权限"),
// 业务
NOT_FOUND(404, "资源不存在"),
BIZ_ERROR(500, "业务逻辑错误"),
// 服务
SERVER_ERROR(500, "服务器内部错误");
private final int code;
private final String message;
ResponseCode(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() { return code; }
public String getMessage() { return message; }
}
2 定义统一返回类(泛型)
import java.io.Serializable;
public class ApiResult<T> implements Serializable {
private static final long serialVersionUID = 1L;
private int code;
private String message;
private T data;
private boolean success;
// 私有构造器,禁止直接new
private ApiResult() {}
// ========== 静态工厂方法 ==========
// 成功(无数据)
public static <T> ApiResult<T> success() {
return success(null);
}
// 成功(带数据)
public static <T> ApiResult<T> success(T data) {
ApiResult<T> result = new ApiResult<>();
result.code = ResponseCode.SUCCESS.getCode();
result.message = ResponseCode.SUCCESS.getMessage();
result.data = data;
result.success = true;
return result;
}
// 成功(自定义消息)
public static <T> ApiResult<T> success(String message, T data) {
ApiResult<T> result = new ApiResult<>();
result.code = ResponseCode.SUCCESS.getCode();
result.message = message;
result.data = data;
result.success = true;
return result;
}
// 失败(默认)
public static <T> ApiResult<T> error() {
return error(ResponseCode.FAIL);
}
// 失败(使用状态码枚举)
public static <T> ApiResult<T> error(ResponseCode responseCode) {
ApiResult<T> result = new ApiResult<>();
result.code = responseCode.getCode();
result.message = responseCode.getMessage();
result.data = null;
result.success = false;
return result;
}
// 失败(自定义消息)
public static <T> ApiResult<T> error(int code, String message) {
ApiResult<T> result = new ApiResult<>();
result.code = code;
result.message = message;
result.data = null;
result.success = false;
return result;
}
// 失败(自定义消息 + 数据)
public static <T> ApiResult<T> error(String message, T data) {
ApiResult<T> result = new ApiResult<>();
result.code = ResponseCode.FAIL.getCode();
result.message = message;
result.data = data;
result.success = false;
return result;
}
// ========== getter/setter ==========
public int getCode() { return code; }
public String getMessage() { return message; }
public T getData() { return data; }
public boolean isSuccess() { return success; }
@Override
public String toString() {
return "ApiResult{" +
"code=" + code +
", message='" + message + '\'' +
", data=" + data +
", success=" + success +
'}';
}
}
使用示例
1 在Controller中使用
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public ApiResult<User> getUser(@PathVariable Long id) {
// 查不到
if (id == null || id <= 0) {
return ApiResult.error(ResponseCode.PARAM_ERROR);
}
User user = userService.getUserById(id);
if (user == null) {
return ApiResult.error(ResponseCode.NOT_FOUND);
}
return ApiResult.success(user);
}
@PostMapping
public ApiResult<Long> createUser(@RequestBody @Valid UserCreateReq req) {
// 参数校验由 @Valid 处理
Long userId = userService.createUser(req);
return ApiResult.success("创建成功", userId);
}
@PutMapping("/{id}")
public ApiResult<Void> updateUser(@PathVariable Long id, @RequestBody UserUpdateReq req) {
try {
userService.updateUser(id, req);
return ApiResult.success();
} catch (BizException e) {
// 业务异常:捕获并返回通用错误
return ApiResult.error(e.getCode(), e.getMessage());
}
}
}
2 前端期望的JSON示例
成功:
{
"code": 200,
"message": "操作成功",
"data": {
"userId": 123,
"name": "张三",
"email": "zhangsan@example.com"
},
"success": true
}
失败(参数错误):
{
"code": 400,
"message": "缺少必要参数",
"data": null,
"success": false
}
失败(业务异常):
{
"code": 500,
"message": "用户余额不足",
"data": {
"currentBalance": 10.5,
"requiredBalance": 100.0
},
"success": false
}
高级进阶(可选增强)
1 结合全局异常处理器
使用 @ControllerAdvice 自动捕获异常并统一返回:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ApiResult<Void> handleValidationExceptions(MethodArgumentNotValidException ex) {
String errorMessage = ex.getBindingResult().getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining(", "));
return ApiResult.error(ResponseCode.PARAM_ERROR.getCode(), errorMessage);
}
@ExceptionHandler(BizException.class)
public ApiResult<Void> handleBizException(BizException ex) {
return ApiResult.error(ex.getCode(), ex.getMessage());
}
@ExceptionHandler(Exception.class)
public ApiResult<Void> handleAllExceptions(Exception ex) {
// 生产环境建议记日志,返回模糊信息
log.error("系统异常", ex);
return ApiResult.error(ResponseCode.SERVER_ERROR);
}
}
2 加入时间戳或请求ID(可选)
public class ApiResult<T> implements Serializable {
private int code;
private String message;
private T data;
private boolean success;
private long timestamp; // 时间戳
private String requestId; // 请求ID(可用于追踪)
// 在生产方法中自动填充
public static <T> ApiResult<T> success(T data) {
ApiResult<T> result = new ApiResult<>();
result.code = ResponseCode.SUCCESS.getCode();
result.message = ResponseCode.SUCCESS.getMessage();
result.data = data;
result.success = true;
result.timestamp = System.currentTimeMillis();
result.requestId = TraceIdUtil.getTraceId(); // 从MDC或请求头获取
return result;
}
}
最佳实践总结
| 实践点 | 说明 |
|---|---|
| 统一状态码 | 不要直接用HTTP状态码,定义自己的业务状态码枚举 |
| 泛型支持 | 使用 <T> 让 data 字段能接受任何类型 |
| 静态工厂方法 | 禁止外部直接 new,通过 success()、error() 创建 |
| 前后端协商 | 提前约定好字段名、类型、错误码范围 |
| 不透露敏感信息 | 生产环境错误消息不要暴露堆栈细节 |
| 日志记录 | 在 error() 或异常处理器中记录完整错误日志 |
| 序列化兼容 | 实现 Serializable 并定义 serialVersionUID |
扩展:如果是微服务或RPC调用
可以使用 统一响应对象 + 统一错误码枚举 + 全局异常处理 组合方案,保证所有微服务对外返回格式完全一致。
核心代码与上面完全一致,只需注意:
- RPC 调用时,
ApiResult需要实现Serializable - 不同服务的错误码范围需要规划好(50001-59999 为服务A,60000-69999 为服务B)
你可以直接复制上面的 ApiResult 类和 ResponseCode 枚举到你的项目中,并根据业务扩展 ResponseCode 的枚举值,这个方案在公司项目中经过大量验证,非常稳定和好用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播