文档章节

获取通过body传输的postdata数据

北有风雪
 北有风雪
发布于 2017/02/16 13:55
字数 1032
阅读 0
收藏 0
点赞 0
评论 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
关于模拟http请求的三种方法

一、模拟请求代码 (1) import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.URL; import java.......

任璐
2016/01/22
38
1
【深入浅出Node.js系列八】一个基于Node.js完整的Web应用实战

深入浅出Node.js系列 【深入浅出Node.js系列一】什么是Node.js 【深入浅出Node.js系列二】Node.js&NPM的安装与配置 【深入浅出Node.js系列三】深入Node.js的模块机制 【深入浅出Node.js系列四...

陶邦仁
2016/01/13
369
0
node.js如何接受客户端put的数据?

昨天发起了一个问题,跟了下源码,发现问的不太准确更改如下。 客户端 采用ajax的put 向服务发送一段数据, 如 xhr.open("put","123.html",true); xhr.send("aaaaaaaaa"); 服务端为node.js 怎...

听风者
2013/04/28
852
2
HTTP POST GET 本质区别详解

HTTP POST GET 本质区别详解 一 原理区别 一般在浏览器中输入网址访问资源都是通过GET方式;在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认为GET提交 Http定义了与服务器交互...

黑衣李白
2012/12/27
0
0
pyhton实现翻译

root@ubuntu:/data/server/spider# cat fanyi2.py #coding:utf-8 import json import requests import sys class FanYi: def init(self,query_str): # 准备语言检测的url和数据 self.headers......

xxl714
2017/11/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

about git flow

  昨天元芳做了git分支管理规范的分享,为了拓展大家关于git分支的认知,这里我特意再分享这两个关于git flow的链接,大家可以看一下。 Git 工作流程 Git分支管理策略   git flow本质上是...

qwfys
今天
2
0
Linux系统日志文件

/var/log/messages linux系统总日志 /etc/logrotate.conf 日志切割配置文件 参考https://my.oschina.net/u/2000675/blog/908189 dmesg命令 dmesg’命令显示linux内核的环形缓冲区信息,我们可...

chencheng-linux
今天
1
0
MacOS下给树莓派安装Raspbian系统

下载镜像 前往 树莓派官网 下载镜像。 点击 最新版Raspbian 下载最新版镜像。 下载后请,通过 访达 双击解压,或通过 unzip 命令解压。 检查下载的文件 ls -lh -rw-r--r-- 1 dingdayu s...

dingdayu
今天
1
0
spring boot使用通用mapper(tk.mapper) ,id自增和回显等问题

最近项目使用到tk.mapper设置id自增,数据库是mysql。在使用通用mapper主键生成过程中有一些问题,在总结一下。 1、UUID生成方式-字符串主键 在主键上增加注解 @Id @GeneratedValue...

北岩
今天
2
0
告警系统邮件引擎、运行告警系统

告警系统邮件引擎 cd mail vim mail.py #!/usr/bin/env python#-*- coding: UTF-8 -*-import os,sysreload(sys)sys.setdefaultencoding('utf8')import getoptimport smtplibfr......

Zhouliang6
今天
1
0
Java工具类—随机数

Java中常用的生成随机数有Math.random()方法及java.util.Random类.但他们生成的随机数都是伪随机的. Math.radom()方法 在jdk1.8的Math类中可以看到,Math.random()方法实际上就是调用Random类...

PrivateO2
今天
2
0
关于java内存模型、并发编程的好文

Java并发编程:volatile关键字解析    volatile这个关键字可能很多朋友都听说过,或许也都用过。在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果。在...

DannyCoder
昨天
1
0
dubbo @Reference retries 重试次数 一个坑

在代码一中设置 成retries=0,也就是调用超时不用重试,结果DEBUG的时候总是重试,不是0吗,0就不用重试啊。为什么还是调用了多次呢? 结果在网上看到 这篇文章才明白 https://www.cnblogs....

奋斗的小牛
昨天
2
0
数据结构与算法3

要抓紧喽~~~~~~~放羊的孩纸回来喽 LowArray类和LowArrayApp类 程序将一个普通的Java数组封装在LowArray类中。类中的数组隐藏了起来,它是私有的,所以只有类自己的方法才能访问他。 LowArray...

沉迷于编程的小菜菜
昨天
1
0
spring boot应用测试框架介绍

一、spring boot应用测试存在的问题 官方提供的测试框架spring-boot-test-starter,虽然提供了很多功能(junit、spring test、assertj、hamcrest、mockito、jsonassert、jsonpath),但是在数...

yangjianzhou
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部