文档章节

获取通过body传输的postdata数据

北有风雪
 北有风雪
发布于 2017/02/16 13:55
字数 1032
阅读 1
收藏 0

    目前基于rest风格的很多API开始使用通过body data来传输来代替之前的key-value传输方式。在java servlet或者springmvc中可以通过如下代码来获取并图片通过流方式传输的数据:

 

1 InputStream is= null; String contentStr=""
2 try {
3      is = request.getInputStream();
4           contentStr= IOUtils.toString(is, "utf-8");
5    catch (IOException e) {
6       e.printStackTrace(); 
7   }


 

 

单纯的如上代码可以获取通过POST或PUT等方法传输的数据,但有时候也有例,如果你现在有如下请求的时候:

 

POST http://127.0.0.1:8085/test?id=12564564654

POST data:

01001512a101a203a303a

 

可以看到这里不但会通过post data流的方式发送数据,同时也通过key-value发送了数据,那现在的代码是什么样的呢?如下:

01 @RequestMapping(value = "posttest", method = RequestMethod.POST) 
02 @ResponseBody 
03 public String test(HttpServletRequest request,@RequestParam(value = "id") String id ) {
04      InputStream is= null;     
05      String contentStr="";     
06      try {         
07          is = request.getInputStream();         
08          contentStr= IOUtils.toString(is, "utf-8");     
09          catch (IOException e) { 
10                  e.printStackTrace();     
11          }     
12          return contentStr; 
13 }


 

通过测试你会发现contentStr中并未获取到任何值,同时也不会报任务错误,这是怎么回事呢?会不会是springmvc的问题?答案是否定的。这个时候获取不到postdata的数据与springmvc没有任务关系,同样的把上面的代码进行修改,如下:


01 @RequestMapping(value = "posttest", method = RequestMethod.POST) 
02 @ResponseBody
03 public String test(HttpServletRequest request) {
04      String id=request.getParameter("id");     
05      InputStream is= null;     
06      String contentStr="";     
07      try 
08              is = request.getInputStream();         
09              contentStr= IOUtils.toString(is, "utf-8");     
10          catch (IOException e) {
11                   e.printStackTrace();     
12          }     
13          return contentStr; 
14 }


 

经过测试getInputStream仍然没有数据。

 

那问题出在哪呢?经过查找终于找到问了问答的原因,答案在servlet规范中:

3.1.1 When Parameters Are Available
The following are the conditions that mustbe met before post form data will be 
populated to the parameter set:
1. The request is an HTTP or HTTPS request.
2.  The HTTP method is POST.
3.  The content type is application/x-www-form-urlencoded.
4.  The servlet has made an initial call of any of the getParameterfamily of methods 
on the request object.
If the conditions are not met and the post form data is not included in the parameter 
set, the post data must still be available to the servlet via the request object’s input 
stream. If the conditions are met, post form data will no longer be available for 
reading directly from the request object’s input stream.

 

经过翻译servlet上面一段规范如下:

根据Servlet规范,如果同时满足下列条件,则请求体(Entity)中的表单数据,将被填充到request的parameter集合中(request.getParameter系列方法可以读取相关数据):
1 这是一个HTTP/HTTPS请求
2 请求方法是POST(querystring无论是否POST都将被设置到parameter中)
3 请求的类型(Content-Type头)是application/x-www-form-urlencoded
4 Servlet调用了getParameter系列方法


如果上述条件没有同时满足,则相关的表单数据不会被设置进request的parameter集合中,相关的数据可以通过request.getInputStream()来访问。反之,如果上述条件均满足,相关的表单数据将不能再通过request.getInputStream()来读取。

 

根据这个规范的说明,当我们在调用request.getParameter(“id”)的方法时,通过post data交的数据(请求体)被填充到了parameter集合中了,所以后面的通过request.getInputStream获取数据流时就为空。通过测试打印断点我们可以看到如下图:

2.jpg

 

原本我们只提交了一个参数id,但是在执行过request.getParameter(“id”)的方法后,我们的parameterNames里就有了两个参数,其中第二个参数的key就是我们通过body请求体传输的数据,值也是body请求体的post data数据。

 

最终这个问题的解决方案是把string id= request.getParameter(“id”);放到request.getInputStream之后,这样就回避了servlet的规范,代码调整后为:


01 @RequestMapping(value = "posttest", method = RequestMethod.POST) 
02 @ResponseBody
03 public String test(HttpServletRequest request) {
04      InputStream is= null;     
05      String contentStr="";     
06      try {         
07          is = request.getInputStream();         
08          contentStr= IOUtils.toString(is, "utf-8");     
09          catch (IOException e) {
10                   e.printStackTrace();     
11              }     
12        String id=request.getParameter("id");     
13   return contentStr; 
14 }


 

在servlet规范中已经说明是post请求时才会有这个获取post提交数据的顺序问题,而在其它的如put中不会出现这种顺序问题。


© 著作权归作者所有

共有 人打赏支持
北有风雪
粉丝 2
博文 33
码字总数 55091
作品 1
程序员
私信 提问
URL太长导致参数被截断的问题

做Web开发时经常涉及到页面之间的转跳,页面之间的转跳就会涉及到页面之间参数的传递,通过URL传递参数是常用的方法之一,但是微软 说:"Maximum URL length is 2,083 characters in Intern...

donny945
2014/09/10
0
0
微信支付成功后返回postData xml 用户信息java怎么获取

通知URL返回有二部分信息,一部分订单信息在notify_url参数里面(这是get方式告知我们服务器),另一部分在body PostData里面主要是支付者的用户信息如OpenID(这时post方式告诉我们服务器)...

JeremyYang
2014/05/16
2.2K
2
如何使用javascript向服务器提交数据(post)

1 引言 编写Web程序的时候,客户端跟服务器必然有数据的传输,因此很多情况下,客户端需要向服务器提交大量的参数,包括中文和英文。这样一来就会有下面的问题:第一,这些参数很可能在页面的...

Daniel_s
2016/01/31
178
0
django1.7处理jquery.post的json数据问题

django1.7如何处理jquery.post的json数据问题? 在JS里,我提交一个json对像结构是这样的: mkSetInfo = { ptMacro:'', //产品 ptMacroSet:[], //数组产品公宏公共属性 csMacro: '', //客户宏...

jhting
2015/08/03
1K
2
记录今天学习到的 --- 如何获取微信access_token及微信二维码ticket。

借用了 appid和appsecret // printr($accesstoken); // $ticket = urlencode($ticket); // print_r($ticket);// print $qrcode_img; // header('Content-type: image/jpeg');// echo $qrcode......

林伟盛
2016/01/27
57
0

没有更多内容

加载失败,请刷新页面

加载更多

epoll中使用

1、一个线程epoll_wait时,另一个线程调用epoll_ctl是安全的。 2、使用edge触发,在socket有数据到来后,不收取数据,再次调用epoll_ctl将socket加入,仍会触发下一次动作。 asio用该方法来发...

gelare
29分钟前
1
0
PHP规范PSR2

PSR标准 - PSR-2 为了尽可能的提升阅读其他人代码时的效率,下面例举了一系列的通用规则,特别是有关于PHP代码风格的。 各个成员项目间的共性组成了这组代码规范。当开发者们在多个项目中合作...

geek土拨鼠
45分钟前
5
0
【极简】如何在服务器上安装SSL证书?

本文适合任何人了解,图形化操作。下面以腾讯云为例,并且服务器(linux)也安装了宝塔面板。 1.登陆腾讯云账号进入控制台,找到SSL的产品 2.按要求申请并填写表单,记住私钥密码 3.提交后,待...

皇冠小丑
53分钟前
1
0
深入理解编译器

深入理解编译器 原文出处 欢迎向Rust中文社区投稿,投稿地址,好文将在以下地方直接展示 1 Rust中文社区首页 2 Rust中文社区Rust文章栏目 3 知乎专栏Rust语言 编程语言是如何工作的 从内部理解...

krircc
55分钟前
1
0
Centos7&docker-ce&compose&wordpress

如题,最近帮人装个WordPress,想起来用docker方便,这里做个记录。 因为docker要求linux内核版本3.10以上我记得,所以直接用的centos7省去很多麻烦。 主机在国内的先把yum源改成国内的阿里云...

虚拟世界的懒猫
59分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部