​ 项目中需要将每个请求的路径和请求参数以及响应结果,都记录在日志中,这样在出现问题时可以快速定位是哪里出现了问题。想到了使用过滤器来实现这个功能,当请求来到过滤器时,会有一个Request参数,通过该参数就能获取到请求路径和请求参数,以及相关内容

parameterMap = httpRequest.getParameterMap();
String requestMethod = httpRequest.getMethod();
String remoteAddr = httpRequest.getRemoteAddr();
int remotePort = httpRequest.getRemotePort();

上面的getParameterMap(),只能够获取到GET请求的参数,如果是POST方法传的JSON那就没法获取到,那如何获取呢,POST的请求是在请求体body中,而POST请求中的body参数是已流形式存在的,所以我们可以通过获取到输入流来获取body

ServletInputStream inputStream = httpRequest.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream,StandardCharsets.UTF_8);
BufferedReader bfReader = new BufferedReader(reader);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bfReader.readLine()) != null){sb.append(line);
}
System.out.println(sb.toString());

通过上面的方法,我们确实能在过滤器中获取到POST的JSON参数了,但是按照上面的方法实现的过滤器,我们会发现,当请求经过过滤器来到Controller的时候,请求参数不见了

可以看到,过滤器确实拿到JSON参数,但是接着报了一个request body missing的异常,也就是请求来到Controller时,参数没有了,这是为啥呢?我们先去源码看看,Controller平时是怎么拿到请求参数的吧

根据DeBug,可以看到SpringBoot处理请求的最主要的两个方法是上图红框的doServicedoDisparch方法,上面就是通过反射去获取参数名去匹配等

来到invokeForRequest方法,这里面的getMethodArgumentValues,就是SpringBoot获取请求参数的入口,进入入口后

再经过上面的红框,就能看到SpringBoot获取POST请求JSON的参数的真面目了

从源码我们可以看到,SpringBoot也是通过获取request的输入流来获取参数,这样上面的疑问就能解开了,为什么经过过滤器来到Controller请求参数就没了,这是因为 InputStream read方法内部有一个,postion,标志当前流读取到的位置,每读取一次,位置就会移动一次,如果读到最后,InputStream.read方法会返回-1,标志已经读取完了,如果想再次读取,可以调用inputstream.reset方法,position就会移动到上次调用mark的位置,mark默认是0,所以就能从头再读了。但是呢 是否能reset又是由markSupported决定的,为true能reset,为false就不能reset,从源码可以看到,markSupported是为false的,而且一调用reset就是直接异常

所以这也就代表,InputStream只能被读取一次,后面就读取不到了。因此我们在过滤器的时候,已经将InputStream读取过了一次,当来到Controller,SpringBoot读取InputStream的时候自然是什么都读取不到了


既然InputStream只能读取一次,那我们可以把InputStream给保存下来,然后完整的传下去SpringBoot就可以读取到了,这里就需要用到HttpServletRequest的包装类HttpServletRequestWrapper了,该类可以自定义一些方法。我们创建一个类并继承这个包装类

public class RequestWrapper extends HttpServletRequestWrapper {private final byte[] body;public RequestWrapper(HttpServletRequest request) throws IOException {super(request);//保存一份InputStream,将其转换为字节数组body = StreamUtils.copyToByteArray(request.getInputStream());}//转换成Stringpublic String getBodyString(){return new String(body,StandardCharsets.UTF_8);}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}//把保存好的InputStream,传下去@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic int read() throws IOException {return bais.read();}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}};}
}

通过保存一份流,就可实现在过滤器中能拿到JSON参数,同时Controller也不会丢失参数


有一点需要注意的,在过滤器放行的时候,放行的是包装类和而不是原来的Request

SpringBoot过滤器获取POST请求的JSON参数相关推荐

  1. curl发送post请求带Json参数、发送get请求

    文章目录 curl发送post请求带Json参数 curl发送get请求带参数 curl 参数 curl发送post请求带Json参数 1:linux下执行curl命令发送post请求 curl -X ...

  2. gin 获取post请求的json body操作详解

    本文主要介绍了gin 获取post请求的json body操作 代码如下 type KDRespBody struct {Errcode int `json:"errcode"`D ...

  3. java获取jsp页面参数_jsp页面中获取servlet请求中的参数方法总结

    jsp页面中获取servlet请求中的参数的办法详解 在JAVA WEB应用中,如何获取servlet请求中的参数,并传递给跳转的JSP页面?例如访问http://localhost:8088/bbs ...

  4. C#获取http请求的JSON数据并解析

    文章目录 1️⃣ C#获取http请求的JSON数据并解析 1.1 获取http的JSON数据 1.2 解析JSON数据 优质资源分享 C#获取http请求的JSON数据并解析,第一步,先拿到http ...

  5. 获取get请求中的参数

    需要获取get请求中的参数,将参数一一保存到数据库 方法一(只适合参数较少的情况): 使用 String a = request.getParameter("参数名");不适合参数 ...

  6. 获取http请求中的参数控制器给jsp传递数据的方式

    这里写自定义目录标题 获取http请求中的参数 直接参数名获取 通过对象的方式获取 通过Servlet API方式获取 当请求中的参数和方法中参数名不一致 直接在url中获取参数的方式 控制器给jsp ...

  7. 在jsp页面如何获取servlet请求中的参数的办法

    在JAVA WEB应用中,如何获取servlet请求中的参数 ,并传递给跳转的JSP页面?例如访问http://localhost:8088/bbs?id=1 当执行这个bbs servlet时,将u ...

  8. java如何通过client客戶端http实现get/ post请求传递json参数到restful 服务接口

    一.首先在client端,导入maven相关依赖(httpclient以及json相关依赖) <dependencies><dependency><groupId> ...

  9. php处理json请求(php获取post请求的json数据的实现方法)

    2019独角兽企业重金招聘Python工程师标准>>> PHP默认只识别application/x-www.form-urlencoded标准的数据类型,因此,对型如text/xml ...

最新文章

  1. HiCar SDK概述
  2. 【裴蜀定理】[HAOI2011]向量
  3. php model类,PHP培训之PHP Model类
  4. 元气森林网络推广外包来势汹汹,地毯式营销旨在打造国民品牌
  5. jedis远程连接linux报错
  6. CodeForces 11D(状压DP 求图中环的个数)
  7. js中this的指向问题
  8. [PY3]——IO——文件目录操作
  9. elementary os(ubuntu)开启ipv6 与走SwitchyOmega代理
  10. ContentLoadingProgressBar不显示问题
  11. 太原理工大学ICPC队介绍(2019版)
  12. 可以在手机预览ps设计稿的软件
  13. 通过Bottledwater同步PostgreSQL中的数据变化到Kafka消息队列
  14. 分享:Battle for Wesnoth 1.11.1 发布,韦诺之战
  15. 树莓派3b+串口配置
  16. 花卉商城APP开发详细方案
  17. 单元格内容分列多行_『如何将excel单个表格里的多行数据分列』
  18. 3D游戏模型教程系列:3D max安装
  19. Python实现群发邮件
  20. SelectObject和DeleteObject函数

热门文章

  1. 如何偷窃局域网其它电脑文件_偷窃工作
  2. 速算小天才 隐私政策协议
  3. java静态内部类单例模式
  4. bzoj 1242: Zju1015 Fishing Net 弦图判定
  5. “百城千校,百万英才”在杭隆重举行
  6. 免费高速图床————学习通网盘
  7. 拼多多网店运营推广技巧有哪些
  8. math@一元函数积分@换元法
  9. 开发ASP.NET博客的第四步——用VS2005建立解决方案(二)(转)
  10. 七牛云对象存储 Java使用