HttpServletRequest.getParameter();
debug看到HttpServletRequest这个类的实例其实是RequestFacade。
到tomcat源码中可以看到该类。
RequestFacade外观模式实现,包装了Request。
RequestFacade.getParameter(String name),该方法调用了Request的方法。
org.apache.catalina.connector.Request.getParameter(String name), 该方法调用了parseParameters()。
/**
* Parse request parameters.
*/
protected void parseParameters() {
parametersParsed = true;
//解析的body封装在Parameters类中,coyoteRequest(org.apache.coyote.Request)封装了Parameters
Parameters parameters = coyoteRequest.getParameters();
boolean success = false;
try {
/**
* 省略。。。
* 处理报文头,在此之前报文头已解析完成
* */
//读取body放到formData中,formData为byte数组
if (readPostBody(formData, len) != len) {
parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE);
return;
}
//省略。。。
//处理解析body
parameters.processParameters(formData, 0, len);
//省略。。。
}
}
org.apache.tomcat.util.http.Parameters.processParameters()主要就是通过while循环解析formData byte数组。并且把结果以key-value的形式放再Map中。
while(pos < end) {
//省略...
switch(bytes[pos]) {
case '=':
//省略...
break;
case '&':
//省略...
break;
case '%':
case '+':
//省略...
break;
default:
pos ++;
break;
}
//省略...
}
所以Servlet其实在doPost,doGet之前已经解析完毕http协议的请求行和请求头。
并且request.getParameter(),request.getInputStream(),request.getReader()这三种方法是有冲突的,因为流只能读取一次。