在构建 RESTful API 时,保持一致的返回数据格式至关重要。统一的返回格式不仅可以提高 API 的可读性,还能方便客户端解析和处理响应数据。Spring Boot 提供了多种方式来实现统一的返回数据格式,本文将深入探讨如何在 Spring Boot 项目中实现这一目标,并提供代码示例和最佳实践。
在 Spring Boot 中,实现统一的返回数据格式,通常采用以下步骤:
1.定义统一的响应体结构: 创建一个 Java 类,用于表示统一的响应体结构,该结构通常包含:
code
: 表示响应状态码,例如成功、失败、参数错误等。
message
: 表示响应消息,用于描述请求结果。
data
: 表示响应数据,用于返回实际的数据内容。
timestamp
: (可选) 返回时间戳。
2.创建统一的响应类:创建一个工具类,用于创建具有统一格式的响应对象。
使用 @RestControllerAdvice
或 @ResponseBodyAdvice
进行全局处理:
使用 @RestControllerAdvice
注解可以拦截所有 @RestController
中的响应,并修改响应数据。
使用 @ResponseBodyAdvice
注解也可以拦截响应,但是需要配合 @Controller
使用。
@ApiModel("响应结果")
@Data
public class Result<T> extends BaseObject{
/**
* code
*/
@ApiModelProperty(value = "响应代码")
private Integer code;
/**
* message
*/
@ApiModelProperty(value = "响应消息")
private String msg;
/**
* data
*/
@ApiModelProperty(value = "数据结果")
private T data;
public Result() {
}
public Result(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
private Result(T data) {
this.code = Status.SUCCESS.getCode();
this.data = data;
}
private Result(Status status) {
if (status != null) {
this.code = status.getCode();
this.msg = status.getMsg();
}
}
public Result(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
/**
* Call this function if there is success
* @param data data
* @param type
* @return resule
*/
public static <T> Result<T> success(T data) {
return new Result<>(data);
}
/**
* 返回错误消息
* @return
*/
public static Result error()
{
return Result.error("操作失败");
}
/**
* 返回错误消息
* @param msg 返回内容
* @return 警告消息
*/
public static Result error(String msg)
{
return Result.error(msg, null);
}
}
public enum Status {
//成功
SUCCESS(0, "success", "成功"),
//系统异常
SYSTEM_EXCEPTION(10000, "system exception", "系统异常"),
//业务异常
SERVICE_EXCEPTION(10001, "service exception", "业务异常")
;
private final int code;
private final String enMsg;
private final String zhMsg;
private Status(int code, String enMsg, String zhMsg) {
this.code = code;
this.enMsg = enMsg;
this.zhMsg = zhMsg;
}
public int getCode() {
return this.code;
}
public String getMsg() {
if (Locale.SIMPLIFIED_CHINESE.getLanguage().equals(LocaleContextHolder.getLocale().getLanguage())) {
return this.zhMsg;
} else {
return this.enMsg;
}
}
}
@ControllerAdvice
public class CustomerResponseAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
return o;
}
}
@RestControllerAdvice
注解声明该类为全局响应处理类。ResponseBodyAdvice
接口,可以拦截所有的响应。beforeBodyWrite
方法中,将返回数据包装成 Result 对象。supports
方法判断是否需要拦截,这里通过判断包名进行拦截。@RestController
@RequestMapping("/yes")
public class ExtendController extends BaseController {
@Autowired
private UserInfoService userInfoService;
@PostMapping("/list")
public Result<PageDataInfo<UserInfo>> queryUserInfoList(@RequestBody UserInfoReq req) {
startPage(req);
return Result.success(buildPageDataInfo(userInfoService.list()));
}
}
{
"code": 0,
"msg": null,
"data": {
"total": 5,
"list": [
{
"id": 1,
"name": "test02",
"password": "test02",
"age": 1,
"status": 1,
"lastLoginTime": null,
"token": null,
"createTime": "2022-06-21 17:57:14",
"updateTime": "2022-06-21 17:57:16"
}
],
"statObj": null
}
}