我们如何在 Spring Boot Filter 中获取和设置响应体
Posted
技术标签:
【中文标题】我们如何在 Spring Boot Filter 中获取和设置响应体【英文标题】:How can we get and set response body in Spring Boot Filter 【发布时间】:2020-11-09 04:07:29 【问题描述】:我有一个 Spring MVC 应用程序,它返回 ResponseEntity 和 clientResponse 对象作为响应体
@RestController
public class XxxController
public void ResponseEntity(ClientRequest clientRequest)
...
return ResponseEntity.ok(clientResponse);
但是我们如何在 Spring Boot Filter 中获取 clientResponse 对象或者设置一个新的 Response body 呢?
@Component
public class MyClassFilter implements Filter
@Override
public void doFilter( HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException
@Override
public void destroy()
@Override
public void init(FilterConfig arg0) throws ServletException
【问题讨论】:
【参考方案1】:我不确定,但我认为你可以试试这个:
HttpServletResponse res = (HttpServletResponse) response;
ContentCachingResponseWrapper ccrw= new ContentCachingResponseWrapper(res);
//old body:
String content=new String(ccrw.getContentAsByteArray(), "utf-8");
//try this
HttpServletResponseWrapper hsrw=new HttpServletResponseWrapper(res);
hsrw.getOutputStream().write(/*new body*/);
//OR this
ServletResponseWrapper responseWrapper = (ServletResponseWrapper)response;
responseWrapper.getResponse().resetBuffer();
responseWrapper.getResponse().getOutputStream().write(/*new body*/);
【讨论】:
使用上面的ccrw
可以做到ccrw.resetBuffer();
ccrw.getOutputStream().write(<bytes>);
crw.copyBodyToResponse();
【参考方案2】:
不确定在过滤器中获取响应是什么意思。在过滤器中,请求尚未传递给控制器,因此还没有响应。你可以得到请求。但是请注意不要读取请求,因为在这种情况下,请求流将在过滤器中被读取,并且当它到达控制器时,整个请求流将已经被读取。要设置响应,您可以执行以下操作:
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException
response.resetBuffer();
response.setStatus(HttpStatus.OK);
response.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
response.getOutputStream().print(new ObjectMapper().writeValueAsString(myData));
response.flushBuffer(); // marks response as committed -- if we don't do this the request will go through normally!
你可以在这里看到为什么你必须刷新响应。你也可以sendError
HttpServletResponse#sendError How to change ContentType
如果您不刷新响应,您的请求将沿过滤器链继续(当然,您必须添加 chain.doFilter(request, response);
!)。
【讨论】:
There is a response on the way out... "过滤器是一个对象,它对资源请求(servlet 或静态内容)或来自资源,或两者兼而有之。” - docs.oracle.com/javaee/6/api/javax/servlet/Filter.html以上是关于我们如何在 Spring Boot Filter 中获取和设置响应体的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 2 实战:如何自定义 Servlet Filter
Spring Boot使用嵌入式容器,自定义Filter如何配置?
Spring Boot参考教程Spring Boot配置Servlet,Filter,Listener,Interceptor