在Spring Boot中,我们经常需要对HTTP响应进行包装,以统一响应格式、添加额外的信息(如执行状态、消息提示等)或处理错误。自动包装响应可以通过多种方式实现,比如使用Spring的@ControllerAdvice
和ResponseBodyAdvice
或自定义过滤器等。以下是一个使用ResponseBodyAdvice
接口自动包装响应的简单例子。
定义统一响应格式
首先,我们定义一个通用的响应格式类。这个类将包含所有API响应的基本结构
package com.shore.my_spring_demo.web.domain.common;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class ApiResponse<T> {
private int code;
private String msg;
private T data;
// 成功响应
public static <T> ApiResponse<T> success(T data) {
return new ApiResponse<>(200, "请求成功", data);
}
// 错误响应
public static <T> ApiResponse<T> error(int code, String message) {
return new ApiResponse<>(code, message, null);
}
}
使用ResponseBodyAdvice包装响应
ResponseBodyAdvice
接口允许在Spring MVC框架写入HTTP响应体之前自定义或修改响应内容。我们可以通过实现这个接口来自动将控制器返回的数据包装进ApiResponse
对象中。
package com.shore.my_spring_demo.web.advice;
import com.shore.my_spring_demo.web.domain.common.ApiResponse;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@ControllerAdvice
public class ApiResponseAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
// 只包装那些需要进行包装的返回类型,可以通过返回类型、注解等方式进行判断
// 这里简单返回true,表示对所有返回类型进行包装
return true;
}
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
// 这里可以根据实际情况包装响应体
if (o instanceof ApiResponse) {
// 如果已经是ApiResponse类型,则直接返回
return o;
}
return ApiResponse.success(o);
}
}