通常我只定义一个拦截器,对请求参数处理的时候,尤其是对post需要用到流,那这样处理完后跑到控制器那边就会报request body missing

错误提示:
流已经关闭,因为如果通过过滤拦截器读取流的话,IO流关闭只能读取一次, 即使不关闭的话,流有个read标志位,后续控制器会从read标志位开始读,读过流之后就读取不到数据了,除非利用void reset()方法,把pos位置位开始,重新读,但是不是任何流都可以使用,所以我们写通用的方法时候,读取完流中数据之后,需要进行包装request,将流重新写入,供后续控制器读取。

网络上解释如下:
那是因为流对应的是数据,数据放在内存中,有的是部分放在内存中。read 一次标记一次当前位置(mark position),第二次read就从标记位置继续读(从内存中copy)数据。 所以这就是为什么读了一次第二次是空了。 怎么让它不为空呢?只要inputstream 中的pos 变成0就可以重写读取当前内存中的数据。javaAPI中有一个方法public void reset() 这个方法就是可以重置pos为起始位置,但是不是所有的IO读取流都可以调用该方法!ServletInputStream是不能调用reset方法,这就导致了只能调用一次getInputStream()。

解决方法

1.自定义一个request

package com.zhongyun.zycx.utils;import org.springframework.util.StreamUtils;import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;/*** @author lc* @version 1.0* @date 2021/10/27 10:27*/
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {private final byte[] body;private String bodyString;public MyHttpServletRequestWrapper(HttpServletRequest request) throws IOException {super(request);this.bodyString = StreamUtils.copyToString(request.getInputStream(), Charset.forName("UTF-8"));body = bodyString.getBytes("UTF-8");}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}@Overridepublic int read() throws IOException {return bais.read();}};}}

写一个过滤器

一定要在启动类上加@ServletComponentScan(“com.zhongyun.zycx.handler”)

package com.zhongyun.zycx.handler;import com.zhongyun.zycx.utils.MyHttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;@WebFilter(urlPatterns = "/*",filterName = "channelFilter")
public class ChannelFilter implements Filter {private Logger logger = LoggerFactory.getLogger(ChannelFilter.class);@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {logger.info("================进入过滤器======================");// 防止流读取一次后就没有了, 所以需要将流继续写出去filterChain.doFilter(new MyHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);}@Overridepublic void destroy() {}
}

拦截器

package com.zhongyun.zycx.handler;import net.sf.json.JSONObject;
import org.springframework.web.servlet.HandlerInterceptor;
import weixin.popular.util.StreamUtils;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.Charset;/*** @author lc* @version 1.0* @date 2021/10/26 14:51*/
public class TicketsInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {crossDomain(request,response); // 设置请求头,解决跨域问题String word = "测试";String method = request.getMethod();if ("GET".equals(method)) {if (request.getParameter("word") != null) {word = request.getParameter("word");}}if ("POST".equals(method)) {String paramstr = StreamUtils.copyToString(request.getInputStream(), Charset.defaultCharset());JSONObject jsonObject = JSONObject.fromObject(paramstr);if (jsonObject.containsKey("word")) {word = jsonObject.getString("word");}}if (word == null || word.length() < 2) {response.setStatus(500, "word最少为2位");return false;}System.out.println("释放拦截器");return true;}// 跨域public void crossDomain(HttpServletRequest request, HttpServletResponse response) {response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));response.setHeader("Access-Control-Allow-Credentials", "true");}
}

拦截器配置

package com.zhongyun.zycx.handler;import org.aopalliance.intercept.Interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 拦截器的配置** @author lc* @version 1.0* @date 2021/10/26 14:58*/
@Configuration//标识这是一个配置类
public class InterceptorConfiguration implements WebMvcConfigurer {// 拦截路径@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册Interceptor拦截器(Interceptor这个类是我们自己写的拦截器类)InterceptorRegistration registration = registry.addInterceptor(new TicketsInterceptor());//addPathPatterns()方法添加需要拦截的路径registration.addPathPatterns("/openapi/**");      //路径都被拦截//excludePathPatterns()方法添加不拦截的路径registration.excludePathPatterns(                         //添加不拦截路径"/demo/loginPage",            //登录页面的地址【不拦截】"/**/*.html",            //html静态资源"/**/*.js",              //js静态资源"/**/*.css"              //css静态资源);}// 跨域,上面的拦截器配置了/*@Overridepublic void addCorsMappings(CorsRegistry registry) {}*/
}

解决HttpServletRequest InputStream(错误提示Request body missin )只能使用一次的问题相关推荐

  1. 解决Ubuntu的错误提示

    如果你是一个Ubuntu用户,也许偶尔甚至经常,遇到这样一个错误提示"System Program problem detected". Ubuntu有一个内建的实用程序叫做App ...

  2. app error login.php,如何解决uniapp登录错误提示问题

    uniapp登录错误提示的解决办法:1.配置文件修改appid appsecret:2.设置微信开放平台的包名和打包时候的一样:3.使用微信提供的获取签名的工具获取签名:4. 重新安装微信再测试. 本 ...

  3. 解决HttpServletRequest InputStream只能读取一次问题

    在Filter中读取inputSeream读取一次之后就无法再次读取,解决办法如下: public class LoggerHttpServletRequestWrapper extends Http ...

  4. 微信小程序获取手机号:前后端源码示例,解决47001这个错误提示

    小程序中自动获取手机号为很常见的一个功能点,可以减少用户输入,目前小程序规则是不允许系统直接自动获取,需要用户手动触发 本文中的实现方式:前端使用uniapp生成小程序,后端使用springboot ...

  5. 关于解决Incorrect padding错误提示

    例子: bg = driver.find_element(By.XPATH,'/html/body/div[5]/div/div/div[2]/div/div[4]').get_attribute(' ...

  6. phpMyadmin出现错误提示

    在浏览器地址栏中输入数据库的IP地址后出现Existing configuration file (./config.inc.php) is not readable.错误时需要的解决办法: 错误提示 ...

  7. Mac--技巧:修复“闪烁的问号”错误提示

    Mac出现一个"闪烁的问号"的标志,是什么问题?这是因为苹果电脑无法找到系统软件.很多用户受到过闪烁问号这一常见的错误提示的影响,如何解决这个问题呢,和大家分享以下4个方法: 修复 ...

  8. powerdesigner错误提示实体属性名称唯一性_WPS导致加载DLL错误的解决方案

    [Access与WPS并存引起的问题]作为事件属性设置而输入的表达式"加载"产生了如下错误:加载DLL错误的解决方法. 一.问题描述: 用Access开发的一个程序,一共四台电脑使 ...

  9. 【我的Android进阶之旅】解决魅族手机USB调试时,无法授权出现“Because an app is obscuring a permission request.”错误提示的问题

    一.问题描述 今天用一个魅族手机进行USB调试的时候,一直无法授权USB调试,调试授权时出现错误提示"Because an app is obscuring a permission req ...

  10. 文件大于50M的上传到阿里云的OSS时浏览器中会出现如下错误提示:Failed to load resource: net::ERR_CONNECTION_RESET解决

    近期做文件上传到阿里云的OSS时,开始上传小文件没有任何问题,后来无意间上传了一些大于50M的文件, 浏览器中会出现如下错误提示:Failed to load resource: net::ERR_C ...

最新文章

  1. mac 安装 python mysqlclient 遇到的问题及解决方法
  2. python3.7下载安装教程-CentOS 7 下 安装 Python3.7
  3. python类中方法的执行顺序-python 函数或者类 代码的执行顺序
  4. IntelliJ IDEA 2021.1更新了好多实用功能,赶紧下载吧!
  5. mysql current_MySQL中CURRENT_TIMESTAMP数据类型详解
  6. cad与连接mySQL数据库_跨服务器操作数据库?其实很简单!(下)
  7. 谷歌云服务器支持udp,谷歌浏览器扩展使用UDP
  8. javascript滚动条响应鼠标滑轮的实现上下滚动事件
  9. Web测试中性能测试基础
  10. python合成gif动图
  11. 《Java并发编程的艺术》一一2.1 volatile的应用
  12. 基于拉格朗日差值算法的BMP图像缩放
  13. 3D资产大掌柜—Connecter
  14. 手把手教你玩转 Excel 数据透视表
  15. 虚拟服务器上磁盘没有初始化,Parallels Desktop使用教程--初始化新添加的磁盘
  16. 计算机组成原理时序发生器qd,计算机组成原理—微程序控制器组成实验
  17. 数据可视化--Superset使用示例
  18. 三款主流文件校验码工具HashCalc、WinMD5、Hasher
  19. b开头的跟计算机相关的英文单词,信息英语词汇(B)
  20. 计算机专业学电路分析,计算机专业电路系列课程教学改革调查分析

热门文章

  1. element合并表格?
  2. XSHELL 绝佳配色方案, 保护你的眼睛
  3. php能转换音频采样率吗,音频采样率转换 如何转换音频采样率
  4. latex sign_让女朋友一周学会 LaTeX(1):第一个 LaTeX 文档,Oh darling!
  5. 图像质量评价:感知建模vs机器学习【VALSE Webinar】Panel实录
  6. CMat格式转QImage格式时出现图片歪斜的情况(已解决)
  7. python图书馆抢座_Python爬虫——教你如何在大学图书馆抢座
  8. 事务(进程 ID 115)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重
  9. SQL 2008 R2 启动失败 提示 请求失败或服务未及时响应 SQL SERVER 2008禁用 VIA协议
  10. Fraud Busters + Arrangement of Contest(ICPC 字符串模拟题)