如何解决请求参数为JSON时,采用IO流读取,只能请求一次的问题?

这篇具有很好参考价值的文章主要介绍了如何解决请求参数为JSON时,采用IO流读取,只能请求一次的问题?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、错误演示

  • 当客户端发送一个参数为JSON的请求时,我现在想使用拦截器先将它拦截并缓存起来,但是发现拦截器拦截之后,请求就无法再一次获取到数据,如下:

1. 创建项目,添加所需依赖

	<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

2. 配置redis环境

server.port=8888
spring.redis.port=6379
spring.redis.host=localhost

3. 写一个简单的测试请求

@RestController
public class HelloController {

    @PostMapping("/hello")
    public String hello(@RequestBody String json) {
        return json;
    }
}

4. 写一个拦截器,拦截请求

@Component
public class RepeatSubmitInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String s = request.getReader().readLine();
        System.out.println("request.getReader().readLine()= " + s);
        return true;
    }

}

5. WebConfig 注册拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    RepeatSubmitInterceptor repeatSubmitInterceptor;

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

6. 测试请求

如何解决请求参数为JSON时,采用IO流读取,只能请求一次的问题?
如何解决请求参数为JSON时,采用IO流读取,只能请求一次的问题?

二、问题解决

采用一个装饰者模式,将请求重新包装一下

1. 创建 RepeatableReadRequestWrapper 类,包装请求

public class RepeatableReadRequestWrapper extends HttpServletRequestWrapper {

    private final byte[] bytes;

    public RepeatableReadRequestWrapper(HttpServletRequest request, HttpServletResponse response) throws IOException {
        super(request);
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        bytes = request.getReader().readLine().getBytes();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
        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 bi.read();
            }

            @Override
            public int available() throws IOException {
                return bytes.length;
            }
        };
    }

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

2. 创建 RepeatableRequestFilter 过滤器,过滤器在拦截器之前执行,如果请求参数为JSON,则包装请求

public class RepeatableRequestFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if (StringUtils.startsWithIgnoreCase(request.getContentType(),"application/json")){
            RepeatableReadRequestWrapper requestWrapper = new RepeatableReadRequestWrapper(request, response);
            filterChain.doFilter(requestWrapper,response);
            return;
        }
        filterChain.doFilter(request,response);
    }
}

3. WebConfig 注册过滤器

@Bean
    FilterRegistrationBean<RepeatableRequestFilter> repeatableRequestFilterFilterRegistrationBean(){
        FilterRegistrationBean<RepeatableRequestFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(new RepeatableRequestFilter());
        bean.addUrlPatterns("/*");
        return bean;
    }

4. 再次测试

如何解决请求参数为JSON时,采用IO流读取,只能请求一次的问题?
如何解决请求参数为JSON时,采用IO流读取,只能请求一次的问题?
这样,就解决了请求参数为JSON时,采用IO流读取,只能请求一次的问题。
点击跳转源码仓库地址文章来源地址https://www.toymoban.com/news/detail-442644.html

到了这里,关于如何解决请求参数为JSON时,采用IO流读取,只能请求一次的问题?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Flutter 笔记 | Flutter 文件IO、网络请求、JSON、日期与国际化

    Dart的 IO 库包含了文件读写的相关类,它属于 Dart 语法标准的一部分,所以通过 Dart IO 库,无论是 Dart VM 下的脚本还是 Flutter,都是通过 Dart IO 库来操作文件的,不过和 Dart VM 相比,Flutter 有一个重要差异是文件系统路径不同,这是因为 Dart VM 是运行在 PC 或服务器操作系统下,

    2024年02月07日
    浏览(100)
  • 请求响应-json参数的接收

    JSON参数:JSON数据 键名 与形参对象 属性名 (即实体类中的成员变量)相同,定义POJO实体类即可接收参数,需要使用 @RequestBody 标识,将请求体的数据封装到对应的参数中。 前端发送JSON格式的数据,要使用 POST 方法发送请求,因为JSON格式的数据要放在请求体中, 而GET请求方

    2024年02月15日
    浏览(43)
  • Flutter携带JSON参数post请求

    在Flutter中发送带有JSON参数的网络请求,你可以使用HTTP库(如 http 或 dio )来实现。以下是使用 http 库发送网络请求并携带JSON参数的示例: 在上述示例中,首先创建一个参数Map,并将其转换为JSON字符串。然后设置请求头,使其指明请求类型为JSON。最后使用 http.post() 方法发送

    2024年02月14日
    浏览(50)
  • 新增:前端提示“请求JSON参数格式不正确,请检查参数格式

    解决方法: 1.检查后端控制台报错: 参数格式传递异常,请求号为:3b44424d-73bd-4db7-970b-38638451c439,具体信息为:JSON parse error: Cannot deserialize value of type ` java.lang.Long` from String \\\" 新增的字段 \\\": not a valid Long value; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot

    2024年02月17日
    浏览(37)
  • Spring-Cloud-Gateway修改请求(json,form带文件请求)参数,返回值参数

    新项目需要在getway统一做入参、出参加解密,记录日志。记录一下form,x-www-form-urlencoded , json 这几种修改数据的方式。 gateway做拦截器是实现GlobalFilter接口,修改json方式网上有很多文章,后来又想研究研究能不能实现修改form-data参数,以及文件请求,后者文章不多大部分是怎

    2024年02月16日
    浏览(46)
  • Postman - post请求application/json参数

    请求参数是json格式,这种是最常见的,以登录接口为例 接口名称:用户账户登录 接口地址: /api/v1/login 请求方式: POST 请求参数: 请求示例 1、新增登陆1的请求 2.请求方式选POST,输入url地址http://localhost:8201/api/v1/login 3、请求 body 选 raw,并选择 application/json类型 4、输入json格式

    2024年02月11日
    浏览(66)
  • SpringMVC项目请求(JSON数据传输参数)

    现在比较流行的开发方式为异步调用。前后台以异步方式进行交换,传输的数据使用的是 JSON ,所以前端如果发送的是JSON数据,后端该如何接收? 对于JSON数据类型,我们常见的有三种: json普通数组([“value1”,“value2”,“value3”,…]) json对象({key1:value1,key2:value2,…}) json对象

    2023年04月18日
    浏览(41)
  • 〔001〕虚幻 UE5 发送 get、post 请求、读取 json 文件

    打开 虚幻商城 ,搜索 varest 进行检索, varest 是一个 api 调用插件,支持 http/https 请求,也支持 json 文件的读取,最关键是该插件完全免费 点击第一个插件,将其安装到引擎中 安装好扩展后,需要在项目中开启扩展才可以使用 点击界面右上角的 设置 选择其中的 插件

    2024年02月06日
    浏览(39)
  • [SpringMVC]请求与响应③(JSON数据传输参数、日期类型参数传递、内部实现原理)

    前面我们说过,现在比较流行的开发方式为异步调用。前后台以异步方式进行交换,传输的数据使用的是 JSON ,所以前端如果发送的是JSON数据,后端该如何接收? 对于JSON数据类型,我们常见的有三种: json普通数组([\\\"value1\\\",\\\"value2\\\",\\\"value3\\\",...]) json对象({key1:value1,key2:value2,...})

    2024年02月08日
    浏览(52)
  • java业务代码发送http请求(Post方式:请求参数为JSON格式;Get方式)

    实际开发中,可能需要发送http请求到第三方服务获取数据,于是就有以下应用: 依赖: 假设我需要在我的业务代码中调用该地址: url:http://xx.xx:xxxx/user/count 请求方法:post 内容类型:application/json 请求参数:id, username 返回参数:code 响应结果 int类型                  

    2024年02月12日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包