Spring的HandlerInterceptor拦截器中重复获取Post方法的请求体数据方法

1.需求

现在有一个实现了HandlerInterceptor的拦截器,现在要实现以下功能,拦截器只拦截指定两个接口进行处理,然后每个接口都有一个请求体参数,使用@RequestBody传入,现在需要获取两个请求的请求体数据,请求体采用json传入,格式如下{"queryCode":"AAA","queryParams":{}},需要通过请求体参数的queryCode数据来执行处理逻辑。

2.遇到的问题

在Spring框架中,HandlerInterceptor是一个用于拦截和处理HTTP请求的接口。当你在HandlerInterceptor中读取了请求体(比如从HttpServletRequest对象中获取输入流或读取请求体的内容),通常会影响后续其他过滤器或处理器读取请求体。
在 Servlet 请求中,HttpServletRequest 的 getReader() 方法或 getInputStream() 方法只能调用一次。这是因为HTTP请求请求体的输入流只能被读取一次,当一个过滤器或拦截器读取了输入流后,它的内容就被消耗掉了,再次读取时就会得到空数据。因此,如果在拦截器中读取了请求体,后续的处理流程(如控制器、其他过滤器或拦截器)将无法再次读取请求体,这可能导致请求体数据不可用的问题。

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing

3.解决

如果你需要在拦截器中读取请求体,但又希望后续处理能够再次访问请求体数据,可以采用以下方法:

  1. 缓存请求体数据:在拦截器中将请求体数据读取并缓存,然后再使用HttpServletRequestWrapper来包裹原始的HttpServletRequest,并提供重新读取缓存数据的能力。

4.演示

4.1 代码实现

自定义拦截器

import com.fasterxml.jackson.databind.ObjectMapper;      
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

@Component
public class CustomInterceptor implements HandlerInterceptor {
   

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
   
        // 包装请求以缓存请求体
        CachedBodyHttpServletRequest cachedRequest = new CachedBodyHttpServletRequest(request);

        // 获取请求体并解析为JSON对象
        String requestBody = cachedRequest.getBody();
        MyRequestBody myRequestBody = objectMapper.readValue(requestBody, MyRequestBody.class);

        // 缓存请求体数据到请求属性,供postHandle使用
        request.setAttribute("cachedBody", requestBody);

        // 判断queryCode
        if ("A".equals(myRequestBody.getQueryCode())) {
   
            // 在这里执行你需要的逻辑
        }

        return true; // 继续处理请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Obj
  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 可以参考以下代码实现一个handlerinterceptor拦截器: ``` public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在请求处理之前进行拦截处理 return true; // 返回true表示继续执行请求处理,返回false表示请求处理 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 在请求处理之后进行拦截处理 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在请求完成之后进行拦截处理 } } ``` 然后在Spring MVC配置文件添加以下配置: ``` <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <!-- 拦截所有请求 --> <bean class="com.example.MyInterceptor"/> <!-- 拦截器类 --> </mvc:interceptor> </mvc:interceptors> ``` 这样就可以实现一个简单的handlerinterceptor拦截器了。 ### 回答2: HandlerInterceptorSpring MVC框架拦截器,用于对请求进行拦截和处理。下面是一个简单的HandlerInterceptor示例: ```java import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class MyHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在请求处理之前进行拦截操作 System.out.println("Pre-handle"); return true; // 返回true表示继续执行后续的拦截器或处理器方法,返回false表示请求 } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 请求处理之后进行拦截操作 System.out.println("Post-handle"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 请求处理完成后进行拦截操作,包括异常处理 System.out.println("After completion"); } } ``` 在上面的代码,我们实现了HandlerInterceptor接口,并重写了preHandle、postHandle和afterCompletion方法。其: - preHandle方法请求处理之前被调用,可以进行一些权限验证、日志记录等操作。返回true表示继续执行后续的拦截器或处理器方法,返回false表示请求。 - postHandle方法请求处理之后,渲染视图之前被调用,可以对ModelAndView进行修改或添加额外的模型数据。 - afterCompletion方法请求处理完成后被调用,无论请求成功或失败都会执行,可以进行一些清理操作,如资源释放。 要使用这个拦截器,我们需要在Spring MVC的配置文件配置拦截器,如下所示: ```xml <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <!-- 拦截所有请求 --> <bean class="com.example.MyHandlerInterceptor"/> </mvc:interceptor> </mvc:interceptors> ``` 上述配置,我们指定了要拦截的路径为"/**",即拦截所有请求,并指定了要使用的拦截器为MyHandlerInterceptor。 通过上述的HandlerInterceptor拦截器的实现和配置,我们可以在请求处理之前、之后和完成后做一些定制化的操作,如权限验证、日志记录、异常处理等。 ### 回答3: HandlerInterceptorSpring MVC框架拦截器,用于拦截请求并在请求处理前后执行一些预处理或后处理操作。 首先,我们需要创建一个类,实现HandlerInterceptor接口,并重写其的三个方法:preHandle、postHandle和afterCompletion。 preHandle方法请求处理之前执行,返回布尔值。如果返回true,表示继续执行后续的请求处理器和拦截器;如果返回false,表示终止请求处理流程。在preHandle方法,可以进行一些前置的验证或处理操作,例如登录验证、权限验证等。 postHandle方法请求处理之后视图渲染之前执行,在该方法可以对模型数据或视图进行进一步的处理。通常在该方法可以对请求的返回结果进行修改或添加一些额外的处理逻辑。 afterCompletion方法在整个请求完成后执行,无论请求处理器是否抛出异常,都会执行afterCompletion方法。在该方法可以进行一些资源的释放操作,例如关闭数据库连接、释放文件资源等。 然后,我们需要在Spring配置文件注册这个拦截器。可以通过<mvc:interceptors>标签来配置拦截器,指定要拦截的URL模式和拦截器类。 最后,我们可以在拦截器添加一些具的业务逻辑,例如记录请求日志、统计请求处理时间、修改请求参数等。 总结来说,HandlerInterceptor拦截器可以在请求处理前后执行一些额外的处理操作,可以用于验证登录、权限控制、日志记录等场景,提供了一种便捷的方式来对请求进行统一处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈小哥cw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值