Spring Boot Filter中截取响应输出内容
在本文中,我们将探讨如何从Spring Boot 过滤器中的ServletResponse检索响应正文。
本质上,我们将定义问题,然后使用缓存响应正文的解决方案,使其在 Spring Boot 过滤器中可用。让我们开始。
首先,让我们了解我们要解决的问题。
使用 Spring Boot 过滤器时,从 ServletResponse 访问响应主体很 棘手。这是因为响应主体不容易获得,因为它是在过滤器链完成执行后写入输出流的。
但是,某些操作(例如生成哈希签名)需要响应正文的内容,然后才能将其发送到客户端。因此,我们需要找到一种方法来读取body的内容。
在过滤器中使用ContentCachingResponseWrapper
为了克服前面定义的问题,我们将创建一个自定义过滤器并使用Spring Framework 提供的ContentCachingResponseWrapper类:
@Override |
简而言之,包装类允许我们包装HttpServletResponse来缓存响应正文内容,并调用doFilter()将请求传递到下一个过滤器。
请记住,我们一定不要忘记这里的doFilter()调用。否则,传入的请求将不会进入 Spring 过滤器链中的下一个过滤器,应用程序也不会按照我们的预期处理该请求。事实上,不调用doFilter()是违反servlet规范的。
此外,我们一定不要忘记使用responseCacheWrapperObject调用doFilter ()。否则,响应正文将不会被缓存。简而言之,ContentCachingResponseWrapper将过滤器放置在响应输出流和发出 HTTP 请求的客户端之间。因此,在创建响应主体输出流后(在本例中是在doFilter()调用之后),内容可在过滤器内进行处理。
使用包装器后,可以使用getContentAsByteArray()方法在过滤器中获取响应正文。我们使用这个方法来计算MD5哈希值。
首先,我们使用MessageDigest类创建响应正文的 MD5 哈希值。其次,我们将字节数组转换为十六进制字符串。第三,我们使用setHeader()方法将生成的哈希字符串设置为响应对象的标头。
如果需要,我们可以将字节数组转换为字符串,并使正文的内容更加明确。
最后,在退出doFilter()方法之前调用copyBodyToResponse()至关重要,以将更新后的响应正文复制回原始响应:
responseCacheWrapperObject.copyBodyToResponse();
在退出doFilter()方法之前调用copyBodyToResponse()至关重要。否则,客户端将不会收到完整的响应。
配置过滤器
现在,我们需要在 Spring Boot 中添加过滤器:
@Bean |
在这里,我们使用 我们之前创建的过滤器的实现来配置创建一个FilterRegistrationBean 。
测试MD5
最后,我们可以使用Spring 中的集成测试来测试一切是否按预期工作:
@Test |
在这里,我们调用/api/example控制器,它返回“Hello, World!”正文中的文字。我们定义了getMD5Hash()方法,它将响应转换为 MD5,类似于我们在过滤器中使用的:
private String getMD5Hash(String input) throws NoSuchAlgorithmException { |
结论
在本文中,我们学习了如何使用ContentCachingResponseWrapper类从Spring Boot 过滤器中的ServletResponse检索响应正文。我们使用此机制来展示如何在 HTTP 响应标头中实现正文的 MD5 编码。