获取referer中的请求参数_Servlet获取AJAX POST请求中参数以form data和request payload形式传输的方法...

本文实例讲述了Servlet获取AJAX POST请求中参数以form data和request payload形式传输的方法。分享给大家供大家参考,具体如下:

HTTP请求中,如果是get请求,那么表单参数以name=value&name1=value1的形式附到url的后面,如果是post请求,那么表单参数是在请求体中,也是以name=value&name1=value1的形式在请求体中。通过chrome的开发者工具可以看到如下(这里是可读的形式,不是真正的HTTP请求协议的请求格式):

get请求:

RequestURL:http://127.0.0.1:8080/test/test.do?name=mikan&address=street

Request Method:GET

Status Code:200 OK

Request Headers

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Accept-Encoding:gzip,deflate,sdch

Accept-Language:zh-CN,zh;q=0.8,en;q=0.6

AlexaToolbar-ALX_NS_PH:AlexaToolbar/alxg-3.2

Connection:keep-alive

Cookie:JSESSIONID=74AC93F9F572980B6FC10474CD8EDD8D

Host:127.0.0.1:8080

Referer:http://127.0.0.1:8080/test/index.jsp

User-Agent:Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36

Query String Parameters

name:mikan

address:street

Response Headers

Content-Length:2

Date:Sun, 11 May 2014 10:42:38 GMT

Server:Apache-Coyote/1.1

Post请求:

RequestURL:http://127.0.0.1:8080/test/test.do

Request Method:POST

Status Code:200 OK

Request Headers

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Accept-Encoding:gzip,deflate,sdch

Accept-Language:zh-CN,zh;q=0.8,en;q=0.6

AlexaToolbar-ALX_NS_PH:AlexaToolbar/alxg-3.2

Cache-Control:max-age=0

Connection:keep-alive

Content-Length:25

Content-Type:application/x-www-form-urlencoded

Cookie:JSESSIONID=74AC93F9F572980B6FC10474CD8EDD8D

Host:127.0.0.1:8080

Origin:http://127.0.0.1:8080

Referer:http://127.0.0.1:8080/test/index.jsp

User-Agent:Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36

Form Data

name:mikan

address:street

Response Headers

Content-Length:2

Date:Sun, 11 May 2014 11:05:33 GMT

Server:Apache-Coyote/1.1

这里要注意post请求的Content-Type为application/x-www-form-urlencoded,参数是在请求体中,即上面请求中的Form Data。

在servlet中,可以通过request.getParameter(name)的形式来获取表单参数。

而如果使用原生AJAX POST请求的话:

function getXMLHttpRequest() {

var xhr;

if(window.ActiveXObject) {

xhr= new ActiveXObject("Microsoft.XMLHTTP");

}else if (window.XMLHttpRequest) {

xhr= new XMLHttpRequest();

}else {

xhr= null;

}

return xhr;

}

function save() {

var xhr = getXMLHttpRequest();

xhr.open("post","http://127.0.0.1:8080/test/test.do");

var data = "name=mikan&address=street...";

xhr.send(data);

xhr.onreadystatechange= function() {

if(xhr.readyState == 4 && xhr.status == 200) {

alert("returned:"+ xhr.responseText);

}

};

}

通过chrome的开发者工具看到请求头如下:

RequestURL:http://127.0.0.1:8080/test/test.do

Request Method:POST

Status Code:200 OK

Request Headers

Accept:*/*

Accept-Encoding:gzip,deflate,sdch

Accept-Language:zh-CN,zh;q=0.8,en;q=0.6

AlexaToolbar-ALX_NS_PH:AlexaToolbar/alxg-3.2

Connection:keep-alive

Content-Length:28

Content-Type:text/plain;charset=UTF-8

Cookie:JSESSIONID=C40C7823648E952E7C6F7D2E687A0A89

Host:127.0.0.1:8080

Origin:http://127.0.0.1:8080

Referer:http://127.0.0.1:8080/test/index.jsp

User-Agent:Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.149 Safari/537.36

Request Payload

name=mikan&address=street

Response Headers

Content-Length:2

Date:Sun, 11 May 2014 11:49:23 GMT

Server:Apache-Coyote/1.1

注意请求的Content-Type为text/plain;charset=UTF-8,而请求表单参数在RequestPayload中。

那么servlet中通过request.getParameter(name)却是空。为什么呢?而这样的参数又该怎么样获取呢?

为了搞明白这个问题,查了些资料,也看了Tomcat7.0.53关于请求参数处理的源码,终于搞明白了是怎么回事。

HTTP POST表单请求提交时,使用的Content-Type是application/x-www-form-urlencoded,而使用原生AJAX的POST请求如果不指定请求头RequestHeader,默认使用的Content-Type是text/plain;charset=UTF-8。

由于Tomcat对于Content-Type multipart/form-data(文件上传)和application/x-www-form-urlencoded(POST请求)做了“特殊处理”。下面来看看相关的处理代码。

Tomcat的HttpServletRequest类的实现类为org.apache.catalina.connector.Request(实际上是org.apache.coyote.Request),而它对处理请求参数的方法为protected void parseParameters(),这个方法中对Content-Type multipart/form-data(文件上传)和application/x-www-form-urlencoded(POST请求)的处理代码如下:

protectedvoid parseParameters() {

//省略部分代码......

parameters.handleQueryParameters();// 这里是处理url中的参数

//省略部分代码......

if ("multipart/form-data".equals(contentType)) { // 这里是处理文件上传请求

parseParts();

success = true;

return;

}

if(!("application/x-www-form-urlencoded".equals(contentType))) {// 这里如果是非POST请求直接返回,不再进行处理

success = true;

return;

}

//下面的代码才是处理POST请求参数

//省略部分代码......

try {

if (readPostBody(formData, len)!= len) { // 读取请求体数据

return;

}

} catch (IOException e) {

// Client disconnect

if(context.getLogger().isDebugEnabled()) {

context.getLogger().debug(

sm.getString("coyoteRequest.parseParameters"),e);

}

return;

}

parameters.processParameters(formData, 0, len); // 处理POST请求参数,把它放到requestparameter map中(即request.getParameterMap获取到的Map,request.getParameter(name)也是从这个Map中获取的)

// 省略部分代码......

}

protected int readPostBody(byte body[], int len)

throws IOException {

int offset = 0;

do {

int inputLen = getStream().read(body, offset, len - offset);

if (inputLen <= 0) {

return offset;

}

offset += inputLen;

} while ((len - offset) > 0);

return len;

}

从上面代码可以看出,Content-Type不是application/x-www-form-urlencoded的POST请求是不会读取请求体数据和进行相应的参数处理的,即不会解析表单数据来放到request parameter map中。所以通过request.getParameter(name)是获取不到的。

那么这样提交的参数我们该怎么获取呢?

当然是使用最原始的方式,读取输入流来获取了,如下所示:

privateString getRequestPayload(HttpServletRequest req) {

StringBuildersb = new StringBuilder();

try(BufferedReaderreader = req.getReader();) {

char[]buff = new char[1024];

intlen;

while((len = reader.read(buff)) != -1) {

sb.append(buff,0, len);

}

}catch (IOException e) {

e.printStackTrace();

}

returnsb.toString();

}

当然,设置了application/x-www-form-urlencoded的POST请求也可以通过这种方式来获取。

所以,在使用原生AJAX POST请求时,需要明确设置Request Header,即:

xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");

另外,如果使用jquery,我使用1.11.0这个版本来测试,$.ajax post请求是不需要明确设置这个请求头的,其他版本的本人没有亲自测试过。相信在1.11.0之后的版本也是不需要设置的。不过之前有的就不一定了。这个没有测试过。

后记:

最近在看书时才真正搞明白,服务器为什么会对表单提交和文件上传做特殊处理,因为表单提交数据是名值对的方式,且Content-Type为application/x-www-form-urlencoded,而文件上传服务器需要特殊处理,普通的post请求(Content-Type不是application/x-www-form-urlencoded)数据格式不固定,不一定是名值对的方式,所以服务器无法知道具体的处理方式,所以只能通过获取原始数据流的方式来进行解析。

jquery在执行post请求时,会设置Content-Type为application/x-www-form-urlencoded,所以服务器能够正确解析,而使用原生ajax请求时,如果不显示的设置Content-Type,那么默认是text/plain,这时服务器就不知道怎么解析数据了,所以才只能通过获取原始数据流的方式来进行解析请求数据。

希望本文所述对大家java程序设计有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573535.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

prim求最短路径C语言,[图论]Prim算法求最小支撑树和最短路径

这个是以前所学&#xff0c;现在总结成博文一篇。对于图论中的求解最小支撑树问题和最短路径问题都有比较经典的算法&#xff0c;比如最小支撑树可以采用“破圈法”&#xff0c;求解最短路径可以用“Dijkstra算法”。这里笔者将回顾下求解最小支撑树的Prim算法和最短路径算法。…

后台服务器端技术点(前沿了解)

1. OpenResty nginx lua 模式解决 高性能与开发效率 平衡。转载于:https://www.cnblogs.com/jhj117/p/5520250.html

pycharm镜像源_pycharm安装第三方库

点击蓝字关注我们hello&#xff0c;大家好&#xff0c;我是你们的小编大飞。小编一直在学习编程语言&#xff0c;挑选了很久之后决定入了python的坑(bushi)。而python之所以火&#xff0c;是因为它专注于如何解决问题、自由开放的社区环境以及丰富的第三方库。几乎可以这么说&a…

c语言实验指导,C语言实验指导

c语言实验用说,分享快乐!!!!《C语言程序设计》实验指导一、教师指导的实验实验1 (1)C语言上机指南和Visual C 6.0 的基本用法1. 实验目的了解VC开发环境。熟练掌握程序的基本开发过程。 掌握简单程序的设计。2. 实验内容和步骤 2.1. 进入C工作环境建立个人子目录&#xff1a;第…

JAVA并发七(多线程环境中安全使用集合API)

在集合API中&#xff0c;最初设计的Vector和Hashtable是多线程安全的。例如&#xff1a;对于Vector来说&#xff0c;用来添加和删除元素的方法是同步的。如果只有一个线程与Vector的实例交互&#xff0c;那么&#xff0c;要求获取和释放对象锁便是一种浪费&#xff0c;另外在不…

iptables nat表含义_十(4)iptables语法、iptables filter表小案例、iptables nat表应用

iptables语法filter表&#xff1a;INPUT链&#xff1a;作用于进入本机的包OUTPUT链&#xff1a;作用于送出本机的包FORWARD链&#xff1a;作用于和本机无关的包nat表&#xff1a;PREROUTING链&#xff1a;作用是包在刚刚到达防火墙时改变包的目标地址OUTPUT链&#xff1a;改变本…

c语言Max错误,C语言编程常见错误.pdf

C 语言常见错误版权声明&#xff1a;以下内容来自互联网C 语言的最大特点是&#xff1a;功能强、使 方便灵活。C 编译的程序对语法检查并不象其它高级语言那么严格&#xff0c;这就给编程人员留下 “灵活的余地”&#xff0c;但还是由于这个灵活给程序的调试带来了许多不便&…

算法训练 连续正整数的和

问题描述78这个数可以表示为连续正整数的和&#xff0c;123&#xff0c;18192021&#xff0c;252627。输入描述输入一个正整数 n(<10000)输出描述输出 m 行(n有m种表示法)&#xff0c;每行是两个正整数a&#xff0c;b&#xff0c;表示a(a1)...bn。对于多种表示法&#xff0c…

android libev 编译,libev-4.20编译安装及简单使用

1.源码下载地址:链接&#xff1a;https://pan.baidu.com/s/1fxotILo3oTMC65z4qFAh9Q 密码&#xff1a;oc312.库的编译与安装解压文件&#xff0c;进入文件目录编译的时候需要首先切换为管理员(root)账户&#xff0c;然后执行以下命令&#xff1a;./configuremakemake install编…

android系统源码的环境下用make来编译,Android源码编译系统入门

做过 Android 平台开发的朋友对make&#xff0c;mm或make clean命令应该很熟悉&#xff0c;但也许大家只是熟知这些命令的作用却不知道这些命令底下有些什么原理&#xff1f;那么今天我就带着大家推开Android编译系统的大门&#xff0c;探索一下这片未知的恐怖之森(问啥要用恐怖…

bootsrap 外边距_Bootstrap CSS 概览

Bootstrap CSS 概览在这一章中&#xff0c;我们将讲解 Bootstrap 底层结构的关键部分&#xff0c;包括我们让 web 开发变得更好、更快、更强壮的最佳实践。HTML 5 文档类型(Doctype)Bootstrap 使用了一些 HTML5 元素和 CSS 属性。为了让这些正常工作&#xff0c;您需要使用 HTM…

jstl表达式替换某些字符

转自:http://www.yiibai.com/jsp/jstl_function_replace.html fn:replace() 函数替换一个字符串与另一个字符串的所有匹配。 语法 fn:replace () 函数语法如下&#xff1a; boolean replace(java.lang.String, java.lang.String, java.lang.String) 例子&#xff1a; 下面是一个…

android socket 闪退,android客户端闪退

老师&#xff0c;我把客户端的代码放在android程序里&#xff0c;给一个button监听事件&#xff0c;就是调用这个socket方法&#xff0c;但是一点button就闪退了&#xff0c;没连接上~protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState)…

(mac)阿里云ECS服务器配置过程

-----首先本人是半只脚入门的iOS开发者&#xff0c;弄这个只是单纯想多学点东西。 -----阿里云服务器的配置选择&#xff1a;既然是学习用的&#xff0c;最最基础的配置就行了。1M带宽&#xff0c;1核1G...这就不详述了。没啥可选的&#xff0c;&#xff08;其中有个创建实例&a…

android 换到iphone,从安卓换到苹果到底是什么感受?最后一个让我彻底放弃了iPhone!...

原标题&#xff1a;从安卓换到苹果到底是什么感受&#xff1f;最后一个让我彻底放弃了iPhone&#xff01;iPhone X是近几年来苹果最具创新力的iPhone&#xff0c;然而高昂的售价让很多消费者望而却步。随着今年苹果秋季新品发布会的临近&#xff0c;苹果即将发布价格更低廉&…

mac谷歌浏览器怎么登陆账户_mac怎么下chrome浏览器

mac怎么下chrome浏览器&#xff1f;首先打开Safari浏览器百度搜一下谷歌浏览器官网&#xff0c;进入官网页面下载或者也可以直接打开下面的网址进入官网https://www.google.cn/intl/zh-CN/chrome/点击网页上的”下载Chrome“弹出提示&#xff0c;选择”接受并安装“等待软件下载…

php 5.5 xhprof for windows

今天看到一个好的性能优软件xhprof&#xff08;有facebook开发的类库)在国内找了很多网站都没有找到相关php5.5的扩展&#xff0c;只好FQ还是外面的世界精彩一下就找到了link (http://windows.php.net/downloads/pecl/releases/xhprof/0.10.6/)如果不能FQ的小伙伴可以到我的百度…

鸿蒙分布式体验,一张图看懂鸿蒙OS 2.0 分布式能力升级构筑全场景体验

原标题&#xff1a;一张图看懂鸿蒙OS 2.0 分布式能力升级构筑全场景体验【手机中国新闻】9月10日下午&#xff0c;华为召开HDC2020大会&#xff0c;全新的HarmonyOS 2.0正式发布。新系统的分布式能力全面升级&#xff0c;同时还为开发者提供了完整分布式设备与应用开发生态&…

怎么卸载python 旧版本_Python 如何移除旧的版本特性,如何迎接新的特性?

2020 年 4 月 20 日&#xff0c;Python 2 的最后一个版本 2.7.18 发布了&#xff0c;这意味着 Python 2 是真正的 EOL(end of life)了&#xff0c;一个时代终于落幕了。Python 2.0 版本是在 2000 年发布的&#xff0c;至今正好到 20 周年(差半年)&#xff0c;一代版本竟然持续了…

如何在android模拟器中安装apk

1. 启动android模拟器 2. 将要安装的apk&#xff0c;拷贝在与adb.exe同文件夹中。我的路径&#xff1a;D:\android\android-sdk-windows\platform-tools 3. 在cmd中&#xff0c;进入上目录&#xff0c;输入adb install xxx.apk&#xff0c;最后可看见success 4. 回到android模拟…