springboot 获取到的inputStream为空的问题
springboot在接收http请求的时候读取的request的inputStream,造成我们想自己读取inputStream的时候发现inputStream已经无法读取了。
为了读取inputStream,我们应该在springboot读取之前把inputStream的内容暂存先来。
1 这里要使用一个类HttpServletRequestWrapper,我们写一个类继承这个类,把传入的request中的inputStream转为byte[] 暂存下来,重写其中的getInputStream方法,每次返回由暂存的byte转换而来的 inputStream。
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors; import javax.servlet.ReadListener;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.Part; import org.springframework.web.bind.annotation.RequestMethod; public class InputStreamHttpServletRequestWrapper extends HttpServletRequestWrapper {
private final byte[] streamBody;
private static final int BUFFER_SIZE = 4096; public InputStreamHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
byte[] bytes = new byte[0];
String uri = request.getRequestURI();
if (Objects.isNull(request.getHeader("Content-Type")) || request.getHeader("Content-Type").contains("multipart/form-data;")) {
bytes = inputStream2Byte(request.getInputStream());
} else if (isFormPost(request)) {
// 从ParameterMap获取参数,并保存以便多次获取
bytes = params2Byte(request);
} else {
bytes = inputStream2Byte(request.getInputStream());
} streamBody = bytes;
// this.setRequest(this);
} private boolean isFormPost(HttpServletRequest request) {
return RequestMethod.POST.name().equals(request.getMethod());
} private byte[] params2Byte(HttpServletRequest request) {
byte[] bytes = request.getParameterMap().entrySet().stream().map(entry -> {
String result;
String[] value = entry.getValue();
if (value != null && value.length > 1) {
result = Arrays.stream(value).map(s -> entry.getKey() + "=" + s).collect(Collectors.joining("&"));
} else {
result = entry.getKey() + "=" + value[0];
} return result;
}).collect(Collectors.joining("&")).getBytes();
return bytes;
} private byte[] inputStream2Byte(InputStream inputStream) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] bytes = new byte[BUFFER_SIZE];
int length;
while ((length = inputStream.read(bytes, 0, BUFFER_SIZE)) != -1) {
outputStream.write(bytes, 0, length);
} return outputStream.toByteArray();
} @Override
public ServletInputStream getInputStream() throws IOException {
ByteArrayInputStream inputStream = new ByteArrayInputStream(streamBody); return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
} @Override
public boolean isReady() {
return false;
} @Override
public void setReadListener(ReadListener listener) { } @Override
public int read() throws IOException {
return inputStream.read();
}
};
} @Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
}
2.这里要使用一个神奇的filter:HiddenHttpMethodFilter
在这个类中调用之前定义的 InputStreamHttpServletRequestWrapper类,并把实例化之后的类传入以后的filter中,这样以后所有的 ServletRequest 都是我们自己定义的了。
import java.io.IOException; import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.filter.OncePerRequestFilter; import com.esri.rest.configure.helper.InputStreamHttpServletRequestWrapper; public class InputStreamWrapperFilter extends HiddenHttpMethodFilter { @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException { ServletRequest servletRequest = new InputStreamHttpServletRequestWrapper(request); filterChain.doFilter(servletRequest, response); } }
3,最后一步:把filter加入springboot 配置
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.filter.HiddenHttpMethodFilter; import com.esri.rest.filter.InputStreamWrapperFilter; @Configuration
public class RequestConfig { @Bean
@Order(1)
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new InputStreamWrapperFilter();
}
}
springboot 获取到的inputStream为空的问题的更多相关文章
- springboot 获取控制器参数的几种方式
这里介绍springboot 获取控制器参数有四种方式 1.无注解下获取参数 2.使用@RequestParam获取参数 3.传递数组 4.通过URL传递参数 无注解下获取参数无注解下获取参数,需要控 ...
- request.getParameter("name")获取参数为null和空字符串的区别
1.获取到的值为空字符串 当url里有name属性,但是没有值的时候,后台用request.getParameter("name")获取到的是空字符串 2.获取到的值为null 当 ...
- 使用paginate方法分页无法判断获取的数据是否为空
问题:使用paginate方法分页无法判断获取的数据是否为空,在模板里面无法判断数据是否为空,比如在商品列表当中,当没有商品时无法判断生成的对象为空,所有就什么都不显示了. 解决办法: $newsDa ...
- springboot获取项目的绝对路径和根目录
springboot获取当前项目路径的地址 System.getProperty("user.dir") 输出目录: G:\outshine\wangsoso //获取class ...
- SpringBoot获取http请求参数的方法
SpringBoot获取http请求参数的方法 原文:https://www.cnblogs.com/zhanglijun/p/9403483.html 有七种Java后台获取前端传来参数的方法,稍微 ...
- SpringBoot获取配置文件,就这么简单。
在讲SpringBoot 获取配置文件之前我们需要对SpringBoot 的项目有一个整体的了解,如何创建SpringBoot 项目,项目结构等等知识点,我在这里就不一一讲述了,没有学过的小伙伴可以自 ...
- Java bean 链式获取成员变量无需判空的工具设计
Java bean 链式获取成员变量无需判空的工具设计 本篇文章已发布至公众号 Hollis 对于Java程序员来说,null是令人头痛的东西.时常会受到空指针异常(NPE)的骚扰.连Java的发明者 ...
- @PostConstruct +getapplicationcontext.getbean springboot获取getBean
Componentpublic class SpringContextUtils implements ApplicationContextAware { public static Applicat ...
- SpringBoot获取resource下证书失败
1.第一种失败的情况: 本来使用Spring的上下文容器获取文件,将证书文件放在resource下,编译后获取文件会出现报错 java.security.spec.InvalidKeySpecE ...
随机推荐
- python安装扩展”unable to find vcvarsall.bat“的解决办法
产生原因: python3.4用的是msvs2010编译的,所以python3.4默认只能认出msvs2010以上版本 python2.7用的是msvs2008编译的,所以python2.7默认只能认 ...
- Jenkins配置LDAP认证
managerdn即为连接到AD的账号
- C 数组、枚举类型enum
传递数组给函数 告诉编译器函数要接受一个指针 skip //函数声明,数组的长度无需声明,因为编译器不会对形式参数进行边界检查 void myFunction(int param[]) //或者 vo ...
- 阿里Jvm必问面试题及答案
什么是Java虚拟机?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件. Java被设计 ...
- 安装Yapi时,出现json-schema-faker模块找不到问题
今天换了一台机器按以前的方式安装Yapi工具时,竟然出现了错误. 一 安装yapi时,出现了下面的报错,一开始以为没安装json-schema-faker模块.后面通过找资料,发现是权限问题, 使用c ...
- Java生鲜电商平台-高并发的设计与架构
Java生鲜电商平台-高并发的设计与架构 说明:源码下载Java开源生鲜电商平台以及高并发的设计与架构文档 对于高并发的场景来说,比如电商类,o2o,门户,等等互联网类的项目,缓存技术是Java项目中 ...
- Java异常相关知识总结
异常: 概述:java程序运行过程中出现的错误 常见的异常: StackOverflowError ArrayIndexOutOfBoundsException NullPointerExceptio ...
- Linux出现You have new mail in /var/spool/mail/root提示,关闭邮件提示清理内容的解决方案
Linux出现You have new mail in /var/spool/mail/root提示,关闭邮件提示的解决方案 有的时候敲一下回车,就出来You have new mail in /va ...
- https申请证书并部署到网站流程,浏览器验证证书流程
https申请证书并部署到网站流程: 1.生成一对秘钥,设公钥为pubk1,私钥为prik12.假设发布的网站地址为https://www.example.com3.生成一个CSR文件(Cerific ...
- 章节十四、5- web页面的截图
一.以雅虎网站为例,当我们在登录时,输入错误的用户名然后点击“下一步”,用户名输入框会提示红色字体,这个时候我们就将页面进行截图. http://commons.apache.org/proper/c ...