首页 > 其他分享 >如何利用拦截器获取HTTP请求参数

如何利用拦截器获取HTTP请求参数

时间:2023-11-23 16:00:01浏览次数:30  
标签:拦截器 HTTP 请求 request 参数 return public

在开发Web应用时,我们经常需要获取HTTP请求的参数。Spring框架提供了多种方式来获取这些参数,其中一种就是使用拦截器(Interceptor)。本文将详细介绍如何利用拦截器获取HTTP请求参数。

1. 拦截器简介

在Spring框架中,拦截器是实现了HandlerInterceptor接口的类。拦截器可以在请求被处理之前、之后或者在视图被渲染之前进行拦截,以执行一些自定义的操作。

在我们的项目中,我们定义了一个名为RequestInterceptor的拦截器,它实现了HandlerInterceptor接口。在这个拦截器中,我们重写了preHandle方法,用来在请求被处理之前获取请求参数。

@Slf4j
public class RequestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {

        // 如果请求是MultipartHttpServletRequest,那么跳过处理
        if (request instanceof MultipartHttpServletRequest) {
            return true;
        }

        //获取请求参数
        String queryString = request.getQueryString();
        log.info("请求参数:{}", queryString);

        //获取请求body
        byte[] bodyBytes = StreamUtils.copyToByteArray(request.getInputStream());
        String body = new String(bodyBytes, request.getCharacterEncoding());

        log.info("请求体:{}", body);

        // 将请求参数和请求体放入当前线程中
        HashMap<String, Object> paramMap = MapUtil.newHashMap(2);
        paramMap.put("param", queryString);
        paramMap.put("body", body);
        RequestParamThreadLocal.set(paramMap);

        return true;
    }

    @Override
    public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        // 移除当前线程中的数据
        RequestParamThreadLocal.remove();
    }
}

我们在WebMvcConfig类中注册了这个拦截器,使其能够拦截所有的请求。

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/**");
    }

    @Bean
    @Qualifier(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServlet dispatcherServlet() {
        return new XinDispatcherServlet();
    }
}

2. 获取请求参数

在拦截器中,我们可以通过HttpServletRequest对象来获取请求参数。HttpServletRequest提供了多种方法来获取请求参数,例如getQueryString()getParameterMap()getInputStream()

但是,HttpServletRequest的输入流只能被读取一次。一旦读取完毕,就不能再次读取。为了解决这个问题,我们定义了一个名为CustomerHttpServletRequestWrapper的类,它继承自HttpServletRequestWrapper,并重写了getInputStream()getReader()方法,使得输入流可以被多次读取。

public class CustomerHttpServletRequestWrapper extends HttpServletRequestWrapper {

    /**
     * 缓存下来的HTTP body
     */
    private final byte[] body;

    public CustomerHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = StreamUtils.copyToByteArray(request.getInputStream());
    }

    /**
     * 重新包装输入流
     *
     * @return {@link ServletInputStream}
     * @throws IOException ioexception
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        InputStream bodyStream = new ByteArrayInputStream(body);
        return new ServletInputStream() {

            @Override
            public int read() throws IOException {
                return bodyStream.read();
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return true;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
}

CustomerDispatcherServlet类中,我们重写了doDispatch方法,将原始的HttpServletRequest包装成CustomerHttpServletRequestWrapper,然后再传递给super.doDispatch()方法。

public class CustomerDispatcherServlet extends DispatcherServlet {

    @Override
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        super.doDispatch(new CustomerHttpServletRequestWrapper(request), response);
    }
}

3. 存储请求参数

为了在后续的处理中方便地获取请求参数,我们将请求参数和请求体存储在了ThreadLocal中。我们定义了一个名为RequestParamThreadLocal的类,它提供了setget方法来存储和获取数据。

public class RequestParamThreadLocal {

    private static final ThreadLocal<Map<String, Object>> REQUEST_PARAM_CONTEXT = new ThreadLocal<>();

    public static void set(Map<String, Object> map) {
        REQUEST_PARAM_CONTEXT.set(map);
    }

    public static Map<String, Object> get() {
        return REQUEST_PARAM_CONTEXT.get();
    }

    public static void remove() {
        REQUEST_PARAM_CONTEXT.remove();
    }
}

RequestInterceptorpreHandle方法中,我们将请求参数和请求体存储在了RequestParamThreadLocal中。

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 获取请求参数和请求体
    // ...

    // 将请求参数和请求体存储在ThreadLocal中
    RequestParamThreadLocal.set(paramMap);

    return true;
}

4. 总结

通过使用Spring框架的拦截器,我们可以方便地获取HTTP请求的参数。我们还可以通过自定义HttpServletRequestWrapper来解决输入流只能被读取一次的问题。最后,我们可以将请求参数和请求体存储在ThreadLocal中,以便在后续的处理中使用。

标签:拦截器,HTTP,请求,request,参数,return,public
From: https://www.cnblogs.com/zzusjw/p/17851718.html

相关文章

  • 深入理解Python爬虫中的HTTP请求与响应过程
    在Python爬虫开发中,了解HTTP请求与响应的过程是非常重要的。HTTP(HypertextTransferProtocol)是一种用于传输超文本的应用层协议,通过HTTP协议,我们可以在网络上获取各种资源。本文将深入探讨Python爬虫中的HTTP请求与响应过程,帮助您更好地理解和应用Python爬虫技术。1.了解HTTP协议H......
  • 通过Spring MVC 实现 Restful 风格请求⽀持
     通过SpringMVC可以很方便地实现Restful风格的请求支持。Restful风格的请求是一种基于HTTP协议的轻量级的Web服务架构风格,它通过HTTP的GET、POST、PUT、DELETE等方法来实现对资源的增删改查操作。在SpringMVC中,我们可以使用注解来定义Restful风格的请求处理方法,并且可以方便......
  • Golang Gin 请求参数的获取值 & 路由分组 & 控制器继承
    一. 请求参数的获取值  动态路由1typeUserstruct{2Usernamestring`form:"username"json:"username"`3Passwordstring`form:"password"json:"password"`4Ageint`form:"age"json:"......
  • uni-app token过期刷新与重新请求
    importstorefrom'@/store/index.js'functionloginOut(){ uni.showToast({ title:'登录失效,请重新登录', icon:'none' }) setTimeout(()=>{ uni.clearStorage() uni.reLaunch({ url:'/pages/index/index' }) ......
  • IIS增加SSL证书(https)
    参考视频:https://www.bilibili.com/video/BV1fW4y1q75V一、证书文件将pfx文件放置于要搭建IIS的Windows服务器中。二、在系统中添加证书运行mms添加证书三、在IIS站点中选择证书 ......
  • 20231121 rock5b 接入mpu6050模块 驱动成功!感谢https://github.com/LitchiCheng/mpu60
    我的rock5b安装的其radxa官方OS,里面有一个rsetup程序的overlay功能可以管理设备树,我想根据https://github.com/LitchiCheng/mpu6050-linux来尝试连接一个6050;先rsetup里面的overlay管理开启i2c8-m4设备节点,之后在/boot/dtco i2c8-m4设备节点已经启用现在......
  • 队列存放用户请求,执行耗时操作的解决方案
    队列存放用户请求的实现方案直接上图待补充……......
  • 并发请求函数的实现
    实施步骤:初始化结果和执行数组:创建数组来存储每个请求的结果并跟踪当前正在执行的请求。为单个请求编写异步函数:该函数发送请求,存储结果,并从执行数组中删除已完成的请求。对并发请求使用循环和Promises:利用循环初始化一定数量的并发请求并将它们添加到执行数组中。递归调用函......
  • DELPHI WIn7下使用 NetHttpClient 请求HTPPS 网站
    转载自:WIn7下使用NetHttpClient请求HTPPS网站-EEEEEEEEEEEEEEEEEEE-博客园(cnblogs.com)WIn7下使用NetHttpClient请求HTPPS网站在WIN7下使用HttpClient会报以下两种错;1ServerCertificateInvalidornotpresent2Errorsendingdata:(12175)发生了安......
  • C# HttpClient 基本使用方式(一)
    .NetCore主要提供了HttpWebRequest,WebClient,HttpClient这三种访问web的方式,其中HttpWebRequest,WebClient都在官方被标注为已过时,如果没有特殊需求,一般情况下还是使用官方推荐的HttpClient方式。HttpClient的基本使用方法使用HttpClient发送请求一般是如下几步:1.创建HttpClien......