当前位置: 首页 > news >正文

Spring框架接口之RequestBodyAdvice和ResponseBodyAdvice

Spring框架接口之RequestBodyAdvice和ResponseBodyAdvice

  • Spring框架接口之 RequestBodyAdvice 和 ResponseBodyAdvice
    • RequestBodyAdvice
      • 1、核心方法
      • 2、典型应用场景
      • 3、工作流程
    • ResponseBodyAdvice
      • 1、核心方法
      • 2、典型应用场景
      • 3、工作流程
    • 代码实践
      • 1、使用 RequestBodyAdvice 进行请求解密
      • 2、使用 ResponseBodyAdvice 实现统一响应包装
    • 补充

Spring框架接口之 RequestBodyAdvice 和 ResponseBodyAdvice

RequestBodyAdviceResponseBodyAdvice 是Spring MVC 中两个非常重要的高级特性,于Spring 4.2 版本引入,它们提供了在消息转换器(HttpMessageConverter) 执行前后进行拦截的切面能力,便于对请求体和响应体进行全局性的、非侵入式的处理。下面将详细介绍一下这两个接口。


RequestBodyAdvice

RequestBodyAdvice 用于在读取请求体之前(或读取得到的对象作为参数传入 @RequestBody 或 HttpEntity Controller 方法之前)进行自定义处理。

1、核心方法

方法说明
boolean supports(…)判断该 Advice 是否支持当前的请求(根据方法参数、注解类型等)。
HttpInputMessage beforeBodyRead(…)在 body 被读取之前调用。可以用于包装或替换原始的 HttpInputMessage(例如,对加密的请求体进行解密)。
Object afterBodyRead(…)在 body 被读取并转换之后调用。可以对转换得到的 Java 对象进行后处理(例如,数据校验、属性填充)。
Object handleEmptyBody(…)当请求体为空时调用。可以返回一个默认值。

2、典型应用场景

  1. 全局请求数据解密:客户端发送的数据是加密的,在 Controller 接收到明文对象之前,先在这里进行解密。

  2. 请求日志记录:记录下请求体的原始内容,用于调试或审计。

  3. 预处理或数据包装:将原始的请求数据包装成一个特定的上下文对象,再传递给 Controller。

  4. 默认值处理:当请求体为空时,提供一个默认的请求对象。


3、工作流程

HttpRequest -> beforeBodyRead (可操作原始流) -> HttpMessageConverter (转换流为对象) -> afterBodyRead (可操作转换后的对象) -> @RequestBody 参数


ResponseBodyAdvice

ResponseBodyAdvice 用于在执行完 @ResponseBodyResponseEntity 控制器方法后,响应体被处理之前对 Controller 方法值进行自定义处理。

1、核心方法

方法说明
boolean supports(…)判断该 Advice 是否支持当前的响应(根据返回值类型、方法注解等。
T beforeBodyWrite(…)在 body 被写入响应之前调用。这是对返回体进行处理的主要方法,可以修改或替换返回的对象。

2、典型应用场景

  1. 统一响应体封装:这是最经典的用法。将 Controller 返回的各种类型(String, Object, List 等)统一包装成 Result/ApiResponse 格式(如 {code: 200, data: …, message: “success”})。

  2. 全局响应数据加密:在响应写出到客户端之前,对数据进行加密。

  3. 响应日志记录:记录即将返回给客户端的响应体。

  4. 敏感信息过滤:在响应写出前,脱敏或过滤掉敏感数据(如密码、手机号)。


3、工作流程

Controller 返回值 -> beforeBodyWrite (可操作返回对象) -> HttpMessageConverter (将对象转换为流) -> HttpResponse


代码实践

1、使用 RequestBodyAdvice 进行请求解密

@ControllerAdvice
public class DecryptRequestBodyAdvice implements RequestBodyAdvice {@Autowiredprivate DecryptService decryptService; // 假设的解密服务@Overridepublic boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {// 只处理带有 @Decrypt 注解的参数return methodParameter.hasParameterAnnotation(Decrypt.class);}@Overridepublic HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,Class<? extends HttpMessageConverter<?>> converterType) throws IOException {// 1. 读取加密的请求体String encryptedBody = StreamUtils.copyToString(inputMessage.getBody(), StandardCharsets.UTF_8);// 2. 进行解密String decryptedBody = decryptService.decrypt(encryptedBody);// 3. 将解密后的字符串重新封装成新的 InputMessage 并返回return new ByteArrayHttpInputMessage(decryptedBody.getBytes(), inputMessage.getHeaders());}// 其他方法可以默认实现...@Overridepublic Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,Class<? extends HttpMessageConverter<?>> converterType) {return body;}@Overridepublic Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType,Class<? extends HttpMessageConverter<?>> converterType) {return body;}// 内部类,用于创建新的 HttpInputMessagestatic class ByteArrayHttpInputMessage implements HttpInputMessage {private final byte[] body;private final HttpHeaders headers;public ByteArrayHttpInputMessage(byte[] body, HttpHeaders headers) {this.body = body;this.headers = headers;}@Overridepublic InputStream getBody() {return new ByteArrayInputStream(body);}@Overridepublic HttpHeaders getHeaders() {return headers;}}
}

2、使用 ResponseBodyAdvice 实现统一响应包装

定义一个统一响应类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {private Integer code;private String message;private T data;public static <T> Result<T> success(T data) {return new Result<>(200, "成功", data);}
}
// 使用 @ControllerAdvice 注解,使其成为一个全局组件
@RestControllerAdvice(basePackages = "com.example.controller")
public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {/*** 判断是否支持增强处理。* 这里我们排除掉本身就是 Result 类型的返回和一些特殊类型(如 String,需要单独处理)。*/@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {// 检查方法上是否有不需要包装的注解(自定义)// 如果方法或类上有 @IgnoreResponseAdvice 注解,则不做处理if (returnType.getMethod().isAnnotationPresent(IgnoreResponseAdvice.class)|| returnType.getContainingClass().isAnnotationPresent(IgnoreResponseAdvice.class)) {return false;}return true;}/*** 在写入响应体之前进行处理*/@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {// 如果返回体已经是 Result 类型,则直接返回(避免重复包装)if (body instanceof Result) {return body;}// 如果返回的是 String 类型,需要特殊处理// 因为 StringHttpMessageConverter 会直接写入字符串,不会转成JSONif (body instanceof String) {// 通常需要手动将 Result 对象序列化成 JSON 字符串// 这里需要确保 Jackson 等库在类路径上try {return new ObjectMapper().writeValueAsString(Result.success(body));} catch (JsonProcessingException e) {throw new RuntimeException(e);}}// 最普遍的情况:将原始数据包装成 Result 对象return Result.success(body);}
}

补充

RequestBodyAdvice 接口有实现类 RequestBodyAdviceAdapter (抽象类),在使用时,如 Interceptor (拦截器)处理请求时可以既继承 RequestBodyAdviceAdapter类,又实现 ResponseBodyAdvice 接口,实现对请求前后同时处理。

http://www.dtcms.com/a/398192.html

相关文章:

  • Unity 性能优化 之 打包优化( 耗电量 | 发热量 | 启动时间 | AB包)
  • 北京南站在几环山西路桥建设集团网站
  • 北京专业网站建设公司哪家好网站及备案
  • RabbitMQ-保证消息不丢失的机制、避免消息的重复消费
  • 分布式之RabbitMQ的使用(1)
  • 基于Java后端与Vue前端的MES生产管理系统,涵盖生产调度、资源管控及数据分析,提供全流程可视化支持,包含完整可运行源码,助力企业提升生产效率与管理水平
  • 阿里云ACP云计算和大模型考哪个?
  • RabbitMQ C API 实现 RPC 通信实例
  • Ingress原理:七层流量的路由管家
  • 代理网站推荐做网站公司是干什么的
  • 个人建设门户网站 如何备案网址域名注册信息查询
  • React 19 vs React 18全面对比,掌握最新前端技术趋势
  • 链改2.0倡导者朱幼平:内地RWA代币化是违规的,但RWA数资化是可信可行的!
  • iOS 混淆后崩溃分析与符号化实战,映射表管理、自动化符号化与应急排查流程
  • 【JavaSE】【网络原理】网络层、数据链路层简单介绍
  • PyTorch 神经网络工具箱核心内容
  • Git高效开发:企业级实战指南
  • 外贸营销型网站策划中seo层面包括影楼网站推广
  • ZooKeeper详解
  • RabbitMQ如何构建集群?
  • 【星海随笔】RabbitMQ开发篇
  • 深入理解 RabbitMQ:消息处理全流程与核心能力解析
  • docker安装canal-server(v.1.1.8)【mysql->rabbitMQ】
  • 学习嵌入式的第四十天——ARM
  • 佛山营销网站建设公司益阳市城乡和住房建设部网站
  • Linux磁盘数据挂载以及迁移
  • 【图像算法 - 28】基于YOLO与PyQt5的多路智能目标检测系统设计与实现
  • Android音视频编解码全流程之Muxer
  • 一家做土产网站呼和浩特网站建设信息
  • Android Studio - Android Studio 检查特定资源被引用的情况