Request Body数据读取

2023-05-16

拦截器要读取request body数据的话需要注意一个问题,一旦拦截器把数据流从request读取出来后,后区的接口层就拿不到数据了,因为流是一次性的,那么要解决这个问题,我们就需要在拦截器取出流拿到数据后重新将数据放回流,这样后面的接口层就能正常获取到数据了

下面放出代码实现:

@Component
@Order(10000)
@WebFilter(filterName = "HttpServletRequestFilter", urlPatterns = "/")
public class HttpServletRequestFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig){
 
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
        String path = "";
        if (servletRequest instanceof HttpServletRequest && servletRequest.getInputStream() != null) {
            path = ((HttpServletRequest) servletRequest).getRequestURI();
            if(path.equals( "/health" )){
                filterChain.doFilter(servletRequest, servletResponse);
                return;
            }
            //获取请求中的流如何,将取出来的字符串,再次转换成流,然后把它放入到新request对象中
            requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
        }
        //在chain.doFiler方法中传递新的request对象
        if (null == requestWrapper) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            filterChain.doFilter(requestWrapper, servletResponse);
        }
        if(servletResponse.getOutputStream() != null){
            RequestWrapper.transmittableThreadLocal.remove();
        }
    }
 
    @Override
    public void destroy() {
 
    }
}

/**
* <p>Title:HttpServletRequest 包装器</p>
* <p>Description:
 * 解决: request.getInputStream()只能读取一次的问题
 * 目标: 流可重复读
 * </p>
* @author QIQI
* @params
* @return
* @throws
* @date 2020/11/16 14:24
*/
public class RequestWrapper extends HttpServletRequestWrapper {
    public static final ThreadLocal<String> transmittableThreadLocal = new TransmittableThreadLocal<>();
    /**
     * 请求体
     */
    private String mBody;
 
    public RequestWrapper(HttpServletRequest request) {
        super(request);
        // 将body数据存储起来
        mBody = getBody(request);
        transmittableThreadLocal.set(mBody);
    }
 
    /**
     * 获取请求体
     *
     * @param request 请求
     * @return 请求体
     */
    private String getBody(HttpServletRequest request) {
        return getBodyString(request);
    }
 
    /**
     * 获取请求体
     *
     * @return 请求体
     */
    public String getBody() {
        return mBody;
    }
 
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
 
    @Override
    public ServletInputStream getInputStream() throws IOException {
        // 创建字节数组输入流
        final ByteArrayInputStream bais = new ByteArrayInputStream(mBody.getBytes( StandardCharsets.UTF_8));
 
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }
 
            @Override
            public boolean isReady() {
                return false;
            }
 
            @Override
            public void setReadListener(ReadListener readListener) {
 
            }
 
            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }
 
    /**
     * 获取请求Body
     *
     * @param request
     * @return
     */
    private String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Request Body数据读取 的相关文章

  • 如何解析来自 ruby​​ 客户端的 SOAP 响应?

    我正在学习 Ruby 并且编写了以下代码来了解如何使用 SOAP 服务 require soap wsdlDriver wsdl http www abundanttech com webservices deadoralive deado
  • 谷歌recaptcha Remoteip解释

    In the 验证码文档 https developers google com recaptcha docs verify它说remoteip参数是可选的 但我不明白它的目的 因为即使我发送与 REMOTE ADDR 不同的 IP 来自
  • 使用内容配置作为文件名下载 Node.js 文件

    我正在使用 Request 模块下载文件 但是当文件名必须来自 Content Disposition 标头时 我不太确定如何将响应传输到输出流 所以基本上 我需要读取响应直到找到标头 然后将其余部分通过管道传输到该文件名 这些示例显示如下
  • 发送 XML 字符串作为响应

    我正在从第三方应用程序 不同域 向我的 ASP 应用程序获取请求 我正在处理请求并在我的应用程序中执行业务部分 作为确认 我需要将 XML 字符串作为响应发送到将请求发布到我的应用程序的同一页面 我使用以下代码成功检索了 Request 中
  • “Request::is()”在 laravel 5.5 上不起作用,在 Blade 中

    我正在尝试在活动菜单上设置活动类 过去我用的是请求 is 函数为此 但在新版本的 laravel 中它说 未找到 请求 类 当你正在使用blade您可以使用request https laravel com docs 5 5 helpers
  • 使用缓存文件还是一个以上的 HTTP 请求?

    在所有 加速你的网站 网站和书籍上 他们总是告诉我们不惜一切代价尽量减少 HTTP 请求 这很好 但如果这意味着在每个页面上你都必须一次又一次地重新加载 120kb 因为用户缓存是空的怎么办 如果我在网站的每个页面上使用 5 个 js 文件
  • 请求超时并显示代码

    Error Domain NSURLErrorDomain Code 1001 The request timed out UserInfo NSUnderlyingError 0x608000244a70 Error Domain kCF
  • Volley.NoConnectionError:java.io.EOFException 0

    我不明白这个错误 虽然我在网上搜索了很多次 但没有采取任何措施 有时会出现该错误 我做了一个使用 VOlley 库的应用程序 一切正常 我的请求 95 有效 但有时我遇到错误 11 12 12 18 54 991 I Error 1870
  • Java上将数据库中的数据以表单的形式输出给用户

    我最近开始学习Java 我需要用 Java 编写一个 Web 应用程序 用户可以从下拉列表中的主页 html 页面上的表单中选择他所需的产品 产品列表存储在数据库的表中 使用 MySQL 然后将所选产品写入 订单历史记录 表中 如何将数据库
  • 对于许多请求,nodeJS 会挂起并且 Promise 无法解析 - 特别是在低带宽情况下

    具体代码 循环中的多个请求挂出节点 尤其是在低带宽连接上 const baseRequest request defaults const specialRequest baseRequest defaults agent false MU
  • JSP/Servlet如何识别HTTP请求是否来自ajax请求

    我正在为我的 Web 应用程序使用 JQuery Ajax 和 History js 我是否可以识别请求是来自 AJAX 请求还是来自普通请求 我的目标是这样的
  • 如何使用 axios 发送基本身份验证

    我正在尝试实现以下代码 但有些东西不起作用 这是代码 var session url http api address api session endpoint var username user var password password
  • 如何使 NodeJS 中的 request 调用同步?

    我的 Nodejs 应用程序中有一个名为 get source at 的函数 它接受 uri 作为参数 其目的是从该 uri 返回源代码 我的问题是我不知道如何使函数同步调用请求 而不是给它那个回调函数 我want控制流停止加载 uri 所
  • 每次我发出 http 请求时应用程序都会崩溃

    这是我的代码 每次我触摸 imageview 我的应用程序都会等待大约 5 秒然后崩溃 我有互联网权限 在服务器端 我有一个 php 页面 它读取 GET 并将其插入数据库中 public class Home extends Activi
  • 动态创建 Laravel Request 对象

    我正在一个控制器中处理数据 并希望将其进一步传递到另一个控制器中以避免重复代码 有没有办法设置另一个控制器中需要的 Request 对象store 方法 我追踪了 Request 继承并找到了 Symfony 的 Request 对象 它有
  • Play Framework 2.1:Scala:如何获取整个基本url(包括协议)?

    目前我可以从request http www playframework com documentation api 2 1 0 scala index html play api mvc Request 其中包括域和可选端口 不幸的是 它
  • 检测 PHP 中的请求类型(GET、POST、PUT 或 DELETE)

    如何检测 PHP 中使用了哪种请求类型 GET POST PUT 或 DELETE Answer recommended by PHP collectives php Collective By using SERVER REQUEST M
  • Solidity有HTTP请求功能吗?

    我正在使用以太坊制作一个项目 在这个项目中 我正在签订一份名为 A 的合同 当我向 A 发送消息时 我希望 A 发出网络请求 Solidity 是否可以使用 http 请求 方法 GET POST 以太坊区块链无法与外界交互 否则它将不再是
  • 将 cookie 作为 node.js 请求的一部分传递

    我正在使用request包来创建我的服务器端请求 我编写了身份验证中间件 用于检查所有请求的 cookie 会话 ID 因此 有没有办法将用户的 cookie 作为请求的一部分包含在内 这是我当前的代码 var cookie parseCo
  • 如果没有收到请求的响应,会发生什么情况?我看到重试

    我认为我遇到的问题可能更多是与浏览器相关的问题 但它是一个非常基本的问题 当我冒险构建一个 Web 应用程序时 我也想找到答案 在我的客户端代码中我正在做一个 ajax称呼 这篇文章可能需要一段时间才能回复 我看到的是在一段时间后再次发送请

随机推荐

  • axios自定义请求头跨域,thinkphp设置

    axios添加自定义请求头 在axios拦截器中 headers XXX 61 XX 配置后 thinkphp 返回跨域 需要对thinkphp中间件进行重新设置 主要配置在tp 复制 vendor topthink framework s
  • git webhook linux 切换www用户

    vim etc passwd 把 www x 1000 1000 home www sbin nologin 改成 www x 1000 1000 home www bin bash ESC键结束 wq 保存文件并退出编辑 切换www用户
  • mint下nginx和uwsgi部署django

    参考 xff1a http www cnblogs com fnng p 5268633 html 安装Nginx apt get install nginx 启动Nginx xff1a etc init d nginx start 启动
  • (原创)Android安装APK报错Installation failed due to: ‘INSTALL_FAILED_TEST_ONLY‘

    这个问题遇到是在vivo手机与oppo手机 xff0c 换成在华为 小米等手机中未发现该问题 其实是因为Android Studio 自3 0 开始自带一个隐藏的功能 xff0c 那就是编译打包 debug 包时 xff0c 会自动在 ap
  • strapi-api使用说明

    strapi controllers 返回项目中可用的控制器的对象 位于该 api controllers文件夹中的每个JavaScript文件都将被解析为该strapi controllers对象 由于这个对象 xff0c 您可以访问项目
  • sublime tex4配置vue开发环境

    前提 已安装package control 参考网站 https lsp sublimetext io https www prettier cn 安装包快捷键 ctrl 43 alt 43 p 输入install package 安装以下
  • win下mkcert+phpenv本地ssl环境配置

    环境win mkcert 安装过程略 使用Chocolatey安装比较方便 1 choco install mkcert 2 mkcert install 弹出窗口点安装 3 mkcert shop test 注意点 shop test 本
  • Android http post/get

    虽然在Android开发中有很多网络框架 xff0c 可是都比较臃肿 xff0c 要考虑很多请求姿势 xff0c 所以自己写了一个 感谢大家发表评论 xff01 1 网络请求一般分为post和get两种方式 xff0c 在工作中我比较常用的
  • Android相机,图库获取图片

    大家的APP中经常会有从手机相机 图库获取图片 xff0c 这里封装了方法可以方便大家 xff0c 解决了Android7 0资源uri的获取方式 xff0c 兼容SDK19以上的机子 xff0c 有权限请求整合 xff0c 欢迎大家下架使
  • 《Streaming System》流式系统-序章

    本文翻译摘抄自 Streaming System xff0c 在阅读的时候进行翻译 xff0c 同时方便广大同学 xff0c 如有错误或侵权 xff0c 烦请指出 偶尔有机会搜到了这本书籍 xff0c 还看到知乎有有问小伙伴对此书佩服的五体
  • 《Streaming System》 第二章:数据处理的四要素 What Where When and How

    本文由 Streaming System 一书第二章的提炼翻译而来 xff0c 译者才疏学浅 xff0c 如有错误 xff0c 欢迎指正 转载请注明出处 xff0c 侵权必究 本章主要介绍鲁棒的处理乱序数据的核心概念 xff0c 这些概念的
  • 《Streaming System》 第三章:Watermarks

    简介 本章主要介绍鲁棒的处理乱序数据的核心概念 xff0c 这些概念的运用使流处理系统超越批处理系统的关键所在 本章我们从流计算系统的底层机制深入来探讨一下watermark 学习这些机制有助于我们更好理解和使用watermark 我们将讨
  • Centos 7 开放查看端口 防火墙关闭打开

    Centos 7 firewall 命令 xff1a 查看已经开放的端口 xff1a firewall span class hljs attribute cmd span span class hljs subst span span c
  • linux CentOS 安装rz和sz命令 lrzsz

    lrzsz在linux里可代替ftp上传和下载 lrzsz 官网入口 xff1a http freecode com projects lrzsz lrzsz是一个unix通信套件提供的X xff0c Y xff0c 和ZModem文件传输
  • (原创)Flutter开发问题:项目启动一直卡在Running Gradle task ‘assembleDebug‘

    问题描述 按照flutter官网步骤安装Flutter SDK Android studio等 xff0c 在创建第一个flutter项目后run的过程一直是Running Gradle task assembleDebug 针对这个问题
  • Redis 分页排序查询

    Redis是一个高效的内存数据库 xff0c 它支持包括String List Set SortedSet和Hash等数据类型的存储 xff0c 在Redis中通常根据数据的key查询其value值 xff0c Redis没有条件查询 xf
  • 使用Spring实现读写分离( MySQL实现主从复制)

    1 背景 我们一般应用对数据库而言都是 读多写少 xff0c 也就说对数据库读取数据的压力比较大 xff0c 有一个思路就是说采用数据库集群的方案 xff0c 其中一个是主库 xff0c 负责写入数据 xff0c 我们称之为 xff1a 写
  • 解决 Unable to load native-hadoop library for your platform

    安装hadoop启动之后总有警告 xff1a Unable to load native hadoop library for your platform using builtin java classes where applicabl
  • [音乐] 随遇而安

    黄霑真的很适合唱这种充满了江湖气息的歌 xff0c 这首歌的经典程度不亚于 沧海一声笑 有兴趣的自己搜来听听吧 人外有人山外有山 不怕拼命怕平凡 有得有失有欠有还 老天不许人太贪 挺起胸膛咬紧牙关 生死容易低头难 就算当不成英雄 也要是一条
  • Request Body数据读取

    拦截器要读取request body数据的话需要注意一个问题 xff0c 一旦拦截器把数据流从request读取出来后 xff0c 后区的接口层就拿不到数据了 xff0c 因为流是一次性的 xff0c 那么要解决这个问题 xff0c 我们就