spring boot拦截器获取requestBody的巨坑
·
SpringBoot拦截器获取RequestBody的巨坑
在SpringBoot开发中,拦截器(Interceptor)是常用的功能组件,但很多开发者在使用拦截器获取RequestBody时会遇到各种"坑"。本文将揭示这些常见问题及解决方案。
问题根源
拦截器获取RequestBody的主要问题在于:HttpServletRequest的输入流只能读取一次。当请求体被Controller或其他组件读取后,输入流就会关闭,导致拦截器中再次读取时抛出异常。
常见场景
1.直接读取导致后续处理失败:在拦截器中调用`request.getInputStream()`后,Controller中`@RequestBody`注解会失效
2.包装类使用不当:虽然可以通过`ContentCachingRequestWrapper`缓存请求体,但需要在Filter层就进行包装
3.性能问题:缓存大请求体会显著增加内存消耗
解决方案
1.使用Filter提前包装请求:
```java
publicclassRequestWrapperFilterextendsOncePerRequestFilter{
@Override
protectedvoiddoFilterInternal(HttpServletRequestrequest,
HttpServletResponseresponse,
FilterChainfilterChain){
ContentCachingRequestWrapperwrappedRequest=newContentCachingRequestWrapper(request);
filterChain.doFilter(wrappedRequest,response);
}
}
```
2.在拦截器中安全读取:
```java
@Override
publicbooleanpreHandle(HttpServletRequestrequest,
HttpServletResponseresponse,
Objecthandler){
if(requestinstanceofContentCachingRequestWrapper){
ContentCachingRequestWrapperwrapper=(ContentCachingRequestWrapper)request;
byte[]body=wrapper.getContentAsByteArray();
//处理body内容
}
returntrue;
}
```
最佳实践
1.仅在实际需要时读取请求体
2.对大请求体考虑流式处理
3.在拦截器中避免修改请求体内容
4.注意字符编码问题
理解这些"坑"并采用正确方法,可以避免在SpringBoot拦截器中处理RequestBody时的各种问题。
在SpringBoot开发中,拦截器(Interceptor)是常用的功能组件,但很多开发者在使用拦截器获取RequestBody时会遇到各种"坑"。本文将揭示这些常见问题及解决方案。
问题根源
拦截器获取RequestBody的主要问题在于:HttpServletRequest的输入流只能读取一次。当请求体被Controller或其他组件读取后,输入流就会关闭,导致拦截器中再次读取时抛出异常。
常见场景
1.直接读取导致后续处理失败:在拦截器中调用`request.getInputStream()`后,Controller中`@RequestBody`注解会失效
2.包装类使用不当:虽然可以通过`ContentCachingRequestWrapper`缓存请求体,但需要在Filter层就进行包装
3.性能问题:缓存大请求体会显著增加内存消耗
解决方案
1.使用Filter提前包装请求:
```java
publicclassRequestWrapperFilterextendsOncePerRequestFilter{
@Override
protectedvoiddoFilterInternal(HttpServletRequestrequest,
HttpServletResponseresponse,
FilterChainfilterChain){
ContentCachingRequestWrapperwrappedRequest=newContentCachingRequestWrapper(request);
filterChain.doFilter(wrappedRequest,response);
}
}
```
2.在拦截器中安全读取:
```java
@Override
publicbooleanpreHandle(HttpServletRequestrequest,
HttpServletResponseresponse,
Objecthandler){
if(requestinstanceofContentCachingRequestWrapper){
ContentCachingRequestWrapperwrapper=(ContentCachingRequestWrapper)request;
byte[]body=wrapper.getContentAsByteArray();
//处理body内容
}
returntrue;
}
```
最佳实践
1.仅在实际需要时读取请求体
2.对大请求体考虑流式处理
3.在拦截器中避免修改请求体内容
4.注意字符编码问题
理解这些"坑"并采用正确方法,可以避免在SpringBoot拦截器中处理RequestBody时的各种问题。
更多推荐
所有评论(0)