application/x- www-form-urlencoded是post请求默认的请求体内容类型,也是form表单默认的类型。Servlet API规范中对该类型的请求内容提供了request.getParameter()方法来获取请求参数值。但当请求内容不是该类型时,需要调用request.getInputStream()或request.getReader()方法来获取请求内容值。
当请求体内容(注意:get请求没有请求体)类型是application/x- www-form-urlencoded时也可以直接调用request.getInputStream()或request.getReader()方法获取到请求内容再解析出具体都参数,但前提是还没调用request.getParameter()方法(先写了getParameter()方法,再用getReader()方法不能取到数据)。此时当request.getInputStream()或request.getReader()获取到请求内容后,无法再调request.getParameter()获取请求内容。即对该类型的请求,三个方法互斥,只能调其中一个。今天遇到一个Controller请求经过Spring MVC 的RequestMapping处理后,只能通过request.getParameter()获取到参数、无法通过request.getInputStream()和request.getReader()读取内容很可能就是因为在请求经过Spring MVC时已调用过request.getParameter()方法的原因。
注意:在一个请求链中,请求对象被前面对象方法中调用request.getInputStream()或request.getReader()获取过内容后,后面的对象方法里再调用这两个方法也无法获取到客户端请求的内容,但是调用request.getParameter()方法获取过内容后,后面的对象方法里依然可以调用它获取到参数的内容。
当请求体内容是其它类型时,比如 multipart/form-data或application/json时,无法通过request.getParameter()获取到请求内容,此时只能通过request.getInputStream()和request.getReader()方法获取请求内容,此时调用request.getParameter()也不会影响第一次调用request.getInputStream()或request.getReader()获取到请求内容。
request.getInputStream()返回请求内容字节流,多用于文件上传,request.getReader()是对前者返回内容的封装,可以让调用者更方便字符内容的处理(不用自己先获取字节流再做字符流的转换操作)。
测试代码
这里在servlet类中重写了HttpServlet的doPost()方法来接收请求体中的json数据
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(req.getInputStream(), REQUEST_ENCODING));
StringBuffer requestParameter = new StringBuffer();
String line;
while((line = br.readLine()) != null) {
requestParameter.append(line);
}
this.doHandler(requestParameter.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
doHandler解析了固定格式的json数据
protected void doHandler(String jsonParameter) {
System.out.println(jsonParameter);
Message message = JSON.parseObject(jsonParameter, Message.class);
System.out.println(message.getHeader().toString());
System.out.println(message.getUser().toString());
}
其中json数据格式为
{
"header": {
"language": "zh-cn",
"sendTime": "2020-09-07 11:08:34"
},
"user": {
"id": "1",
"userName": "admin",
"passWord": "123456"
}
}
最终效果
Header{language='zh-cn', sendTime=Mon Sep 07 11:08:34 CST 2020}
User{id=1, userName='admin', passWord='123456'}