SpringBoot 统一接口数据返回格式实战
在开发过程中,如果每个控制器的返回值格式都不一致,后续前端对接和维护都会非常麻烦。有没有办法在不修改每个方法的前提下统一格式?答案是肯定的,利用 Spring Boot 提供的 @ControllerAdvice 和 ResponseBodyAdvice 机制即可实现全局拦截。
核心实现思路
定义一个类实现 ResponseBodyAdvice 接口,并加上 @ControllerAdvice 注解。这样可以在响应体写入前统一处理数据。
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 如果已经是 Result 类型,直接返回
if (body instanceof Result) {
return body;
}
// 否则包装成统一的成功响应
return Result.success(body);
}
}
配置完成后,普通的 Integer、Boolean 等类型都能正常被包装成 Result 结构。但在实际测试中,我们发现返回类型为 String 时会出现异常。
为什么 String 类型会报错?
当返回值为 String 时,Spring MVC 的消息转换器(HttpMessageConverter)处理逻辑会有所不同。StringHttpMessageConverter 对响应头有特定要求,它期望处理的是纯文本。而我们的拦截器试图将 String 转换为 Result 对象,这导致在后续的序列化阶段,StringHttpMessageConverter 无法正确处理自定义的 Result 类型,从而抛出 ClassCastException。
简单来说,就是消息转换器的优先级和类型匹配在 String 场景下产生了冲突。
解决方案:手动序列化
要解决这个问题,我们需要在拦截器内部对 String 类型做特殊处理,先将其序列化为 JSON 字符串,再包装进 Result。这需要引入 Jackson 的 ObjectMapper。


