get | post | |
获取url上的参数request.getQueryString(),能否取到值。 |
能 | 否 |
request.getParameter()能否取到值 | 能。无论contentType |
仅在contentType是application/x-www-form-urlencoded时可以 |
获取请求体中的字节流request.getInputStream() / request.getReader(),能否取到值。 |
否 | 能 |
1、request.getQueryString()只能获取GET请求的参数,即URL中的QueryString参数;request.getInputStream() / request.getReader()只能获取POST请求的参数,即请求体的参数。且请求体中的数据仅能调用 request.getInputStream(), request.getReader()和request.getParameter("key") 方法读取一次,即仅第一次能读到数据,后面读到的数据为null。
2、什么时候可以通过request.getParameter()获取参数值
(1)、所有get请求
(2)、contentType是application/x-www-form-urlencoded的post请求
tomcat只会对Get请求和Content-Type是application/x-www-form-urlencoded的POST请求的参数进行相应处理,即会解析表单数据到request parameter map中。而其他类型的请求不做处理,所以其他类型的请求通过request.getParameter(name)是获取不到的
3、application/x-www-form-urlencoded 参数形式:field1=a&field2=b&field3=c4、QueryString与请求体中有相同名称的参数,例如: /testServlet?name=a,接着又在请求体里附加name=b,然后post提交,这时候在后台Servlet调用request.getParameter("name");获取的是a还是b呢?
Tomcat解析Parameter的逻辑:parameter的name和value是一对多的关系,tomcat会先解析URI里的queryString,然后判断如果是post请求&&content-type=”aplication/x-www-form-urlencoded”不管之前有没有获取到需要的参数都会去解析body,也就是说如果不是post请求而是delete或者其它请求或者content-type不是”aplication/x-www-form-urlencoded”则不会去读取body,这种情况getInputSteam可以读取body得到数据,可以用request.getParameterValues(“name”)方法来获取所有name对应的值。
5、GET方法,无论Content-Type是什么类型, 都会以请求参数的形式加在url后面。后台都可通过request.getQueryString()参数串,此处有三种情况:
(1)、自己以&拼接请求参数字符串,后台可以通过request.getQueryString()获取到contract=a&appKey=b请求参数,request.getParameter()同样可以正常取值
(2)、传递一个json对象,后台同样可以通过request.getQueryString()获取到contract=a&appKey=b请求参数,request.getParameter()同样可以正常取值
(3)、将json对象转为json字符串之后传递,浏览器会将json字符串直接拼接到url后面,但是由于参数中含有特殊字符“{“,”}”以及引号,会报400错误。可以通过将参数进过一次编码后传输,后台通过request.getQueryString()获取请求参数后解码可以得到String类型的json串。tomcat在解析参数到parameterMap时会将整个请求字符串作为key,value=“”存入。即Content-Type指定为application/x-www-form-urlencoded且参数形似field1=a&field2=b,tomcat才能正确将其处理至parameterMap
十分重要:从以上可以总结(此处不考虑有文件的情况),不论Content-Type的类型,不论,get或post请求,只要参数不是字符串类型,浏览器都会对参数做field1=a&field2=b的处理,将参数转为此结构的字符串后传给服务端,所以有了5.(2)。但是如果参数本就是一串字符,浏览器便不会再对参数做处理,直接将原始字符串传到后台,get请求可以从QueryString中获取到原始字符串,post请求可以从请求体中取到原始字符串。
例若Content-Type指定为application/x-www-form-urlencoded,实际参数是非field1=a&field2=b格式的字符串,由于Content-Type是application/x-www-form-urlencoded类型,tomcat会将参数解析到ParameterMap,但此时格式非标准格式,在此例中,tomcat会将整个参数字符串作为key,value=“存入ParameterMap,所以有了5.(3)。
在ajax中,可以通过指定processData:false来禁止浏览器对数据进行&形式的序列化,这个参数是jquery独有的,默认为true。默认情况下,发送的数据会被序列化,原生的XMLHttpRequest对数据的处理是手动并无这个参数。
源码:
s = jQuery.ajaxSetup( {}, options ),
// Convert data if not already a string
if (s.data && s.processData && typeof s.data !== "string") {
s.data = jQuery.param( s.data, s.traditional );
}
它会调用返回值:StringjQuery.param把{ width:1680, height:1050 }参数对象序列化为width=1680&height=1050这样的字符串。
6、Content-Type只是浏览器告诉后台如何去处理数据,并不会帮我们将请求参数转为Content-Type指定的类型,需要我们自己将Content-Type指定的类型与实际的参数形式对应起来。若你的Content-Type指定的是application/json,但是参数格式却不是json,浏览器不会帮你转为json格式,只是到了后台,发现Content-Type是application/json,便以json格式来解析数据,但实际数据格式并非json,所以后台报错。
7、在向后台传输json数据(POST)时,且contentType:"application/json",在SpringMVC框架中我们可以通过@RequestBody注解在参数对象上,SpringMVC会将从页面传递来参数set到用@RequestBody注解的对象上,我们直接拿对象用就可以了。原理即是SpringMVC从请求体中获取json字符串,然后将json字符串封装成我们需要的对象(猜想)。
8、关于请求中的Form Data、Request Payload区别
Request Payload:Content-Type不为application/x-www-form-urlencoded的请求,只要是Request Payload类型的参数,后台的数据都需要我们自己处理,tomcat并不会处理。
Form Data:Content-Type为application/x-www-form-urlencoded的请求
Query String Parameters:所有get请求,无论Content-Type类型
9、contentType:multipart/form-data参数的请求,只支持post请求,tomcat不作处理,无法通过request.getParameter("name")取值,需要自己解析通过request.getInputStream()获取请求体数据进行解析,在springMVC中我们只需要配置一个文件处理器类就可以帮我们处理再传入到Controller中了。例如常用的CommonsMultipartResolver
10、关于ajax不能下载文件问题
ajax的返回值类型是json,text,html,xml类型,或者说ajax的接收类型只能是string字符串,不是流类型,所以无法实现文件下载。但用ajax仍然可以获得文件的内容,该文件将被保留在内存中,无法将文件保存到磁盘。这是因为JavaScript无法和磁盘进行交互,否则这会是一个严重的安全问题,说白点就是js无法调用到浏览器的下载处理机制和程序。所以我们要实现ajax下载,不能够使用相应的ajax函数进行文件下载。但可以用js生成一个form,用这个form提交参数,并返回“流”类型的数据。
参考:https://blog.csdn.net/shuangmulin45/article/details/78083992