SpringBoot 接口返回响应体修改
在开发中,有时候会遇到一些统一修改http接口响应体内容的场景,比如返回体Wrapper统一增加一些数据包装处理。
解决思路 :通过自定义注解 + 切面 或者 自定义注解 + ResponseBodyAdvice 处理接口返回体
1、创建自定义注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface WrapperNested { }
2、创建切面处理标注了自定义注解的类或者接口
注意: 切点pointcut @within 作用在类上 @annotation作用在方法上
@Component @Aspect @Slf4j public class WrapperNestedAspect { // @within 作用在类上 @annotation作用在方法上 @Pointcut("@within(com.**.WrapperNested)") public void pointCut() { } @AfterReturning(returning = "ret", pointcut = "pointCut()") public void doAfterReturning(Object ret) { log.debug("ret:{}", JSON.toJSONString(ret)); Wrapper wrapper = (Wrapper) ret; WrapperRes outerWrapper = JSON.parseObject(JSON.toJSONString(ret), WrapperRes.class); if (ObjectUtils.isNotEmpty(wrapper) && ObjectUtils.isNotEmpty(outerWrapper)) { WrapperRes innerWrapper = new WrapperRes(); BeanUtils.copyProperties(outerWrapper, innerWrapper); outerWrapper.setResult(innerWrapper); BeanUtils.copyProperties(outerWrapper, wrapper); } log.debug("ret1:{}", JSON.toJSONString(ret)); } }
3、或者通过ResponseBodyAdvice 来实现,ResponseBodyAdvice 中定义了两个接口方法:
supports方法用于判断beforeBodyWrite方法的执行与否,返回值为布尔类型,返回true即执行beforeBodyWrite方法;可以在实现类中编写实现逻辑,来根据MethodParameter以及HttpMessageConverter类型判断是否需要改写http响应体。
beforeBodyWrite方法提供了用于修改http响应体的能力,该方法中提供了Controller方法的返回body,MethodParameter,MediaType, Class ,ServerHttpRequest 、ServerHttpResponse 对象,我们拿到这些对象,根据需要来编写修改逻辑。
@Slf4j @ControllerAdvice public class WrapperNestedResponseBodyAdvice implements ResponseBodyAdvice { @Override public boolean supports(MethodParameter returnType, Class converterType) { Class targetClass = returnType.getMethod().getDeclaringClass(); return ObjectUtils.isNotEmpty(targetClass.getAnnotation(WrapperNested.class)) || returnType.hasMethodAnnotation(WrapperNested.class); } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { log.debug("beforeBodyWrite data={}", JSON.toJSONString(body)); if (ObjectUtils.isNotEmpty(body) && body instanceof Wrapper) { Wrapper wrapper = (Wrapper) body;return WrapMapper.wrap(wrapper.getCode(), wrapper.getMessage(), WrapMapper.wrap(wrapper.getCode(), wrapper.getMessage(), wrapper.getResult())); } return body; } }