Spring Boot HandlerInterceptor中HttpServletRequest.getParameter返回null问题咨询
getParameter返回null的原因
HttpServletRequest#getParameter 方法是Servlet规范定义的接口,默认仅支持从三类场景获取参数:
- URL路径后的查询参数(即
?key=value格式的参数) Content-Type为application/x-www-form-urlencoded的POST请求体参数multipart/form-data类型请求中的普通表单字段参数
你当前的请求是Content-Type: application/json格式,参数放在JSON结构的请求体中,不属于getParameter的支持范围,因此返回值为null,属于正常现象。
Spring官方无侵入解决方案
Spring框架自带ContentCachingRequestWrapper工具类,专门用于缓存请求体,解决请求输入流只能读取一次的问题,无需你自行编写请求体读取、缓存的自定义逻辑,实现步骤如下:
- 注册全局过滤器,将原生请求包装为可缓存请求体的实例
import org.springframework.web.util.ContentCachingRequestWrapper; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @WebFilter(urlPatterns = "/*") public class CachingRequestFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { ContentCachingRequestWrapper cachingRequest = new ContentCachingRequestWrapper((HttpServletRequest) request); chain.doFilter(cachingRequest, response); } }
在Spring Boot启动类上添加@ServletComponentScan注解,扫描并生效该过滤器。
- 改造自定义拦截器,读取缓存的请求体获取参数
@Component @Slf4j public class CustomInterceptor implements HandlerInterceptor { // 直接注入Spring容器自带的Jackson序列化工具 @Autowired private ObjectMapper objectMapper; @Override public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception { // 判断当前请求为JSON格式请求 if (request.getContentType() != null && request.getContentType().contains("application/json")) { ContentCachingRequestWrapper cachingRequest = (ContentCachingRequestWrapper) request; // 读取已缓存的请求体字节数组 byte[] bodyBytes = cachingRequest.getContentAsByteArray(); // 直接反序列化为目标DTO对象 Person person = objectMapper.readValue(bodyBytes, Person.class); log.info("age::{} ", person.getAge()); // 无需定义DTO也可以直接转为Map获取参数: // Map<String, Object> paramMap = objectMapper.readValue(bodyBytes, new TypeReference<Map<String,Object>>() {}); // log.info("age::{} ", paramMap.get("age")); } else { // 非JSON格式的表单/查询参数依然可以沿用getParameter方法获取 log.info("age::{} ", request.getParameter("age")); } return HandlerInterceptor.super.preHandle(request, response, handler); } }
该方案所有组件均为Spring官方提供,不会侵入业务逻辑,也不会影响后续Controller中@RequestBody注解的参数解析逻辑。
内容的提问来源于stack exchange,提问作者anonymous
相关产品推荐
相关产品推荐

