Tomcat是如何處理請(qǐng)求參數(shù)的,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
成都創(chuàng)新互聯(lián)專注于楚雄州企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站建設(shè),成都商城網(wǎng)站開發(fā)。楚雄州網(wǎng)站建設(shè)公司,為楚雄州等地區(qū)提供建站服務(wù)。全流程按需設(shè)計(jì)網(wǎng)站,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)
url請(qǐng)求中帶參數(shù)的形式(即我們常說的GET請(qǐng)求),是在請(qǐng)求目標(biāo)后以問號(hào)開始,后面是參數(shù)名值對(duì),多個(gè)名值對(duì)間以和號(hào)(&)分隔。
通過URL傳遞的參數(shù),在Tomcat中是怎么解析出來的呢?
我們一般在Servlet中要獲取某個(gè)參數(shù),一般通過如下的方式
String value = request.getParameter("paramName");
我們?cè)谛枰臅r(shí)候通過參數(shù)名直接取,這個(gè)值又是什么設(shè)置的?名值對(duì)又是如何對(duì)應(yīng)起來的?
我們順著getParameter方法這個(gè)藤,來摸摸實(shí)現(xiàn)這個(gè)瓜。
我們?cè)谑褂肏ttpServletRequest這個(gè)對(duì)象時(shí),其實(shí)一直在使用的是其一個(gè)門面對(duì)象(RequestFacade),此對(duì)象使用了設(shè)計(jì)模式中的門面模式,封裝了HttpServletRequest中的一些細(xì)節(jié),只暴露出一些必要的API。
實(shí)際請(qǐng)求處理時(shí),則調(diào)用其封裝的request對(duì)象。
getParameter方法的代碼是下面這個(gè)樣子:
/ * Return the value of the specified request parameter, if any; otherwise,
* return null
. If there is more than one value defined,
* return only the first one.
* @param name Name of the desired request parameter
*/
public String getParameter(String name) {
if (!parametersParsed) {
parseParameters();
}
return coyoteRequest.getParameters().getParameter(name);
}
每次請(qǐng)求時(shí),會(huì)先判斷參數(shù)是否已經(jīng)解析過,如果已經(jīng)解析過就直接返回。
protected void parseParameters() {
parametersParsed = true; //注意這里,解析之后就設(shè)為true了。
Parameters parameters = coyoteRequest.getParameters();
boolean success = false;
try {
// Set this every time in case limit has been changed via JMX
parameters.setLimit(getConnector().getMaxParameterCount());
}
...
parameters.handleQueryParameters();
}
所以,這個(gè)名值對(duì)的配置,初始化,是發(fā)生在第一次調(diào)用getParameter方法時(shí)。
再向下,這個(gè)handleQueryParameters是具體處理的方法。這里我們假設(shè)請(qǐng)求如下url:
http://localhost:8080/test?abc=1&def=2
在handleQueryParameters方法中,我們通過debug界面觀察。
此處parameters包含一個(gè)屬性queryMB,其值剛好是我們傳進(jìn)來的字符串。所以后面的參數(shù)處理,是基于這個(gè)屬性進(jìn)行的。
再之后,在Parameter這個(gè)類的processParameter方法中,
我們看到,基本是遍歷字符串中的各個(gè)char,遇到特定字符=和&之后,再?gòu)母鱾€(gè)index獲取等號(hào)前后的名和值。
中間特別的一個(gè)地方是,遇到%和+時(shí),是出現(xiàn)了像漢字一類的,其實(shí)是需要轉(zhuǎn)義的,所以處理也是在此進(jìn)行的。
解析后,名值對(duì)是存放在ArrayList這樣一個(gè)數(shù)據(jù)結(jié)構(gòu)中??聪旅娴拇a,
public void addParameter( String key, String value ) {
ArrayList
if (values == null) {
values = new ArrayList<>(1);
paramHashValues.put(key, values);
}
values.add(value);
}
是執(zhí)行完上面的方法后,代碼向下執(zhí)行,看到的parameters這個(gè)對(duì)象,值已經(jīng)變成了這樣:
abc=1,\n def=2,\n
注意上面代碼標(biāo)紅加粗的這兩行,
你是否還記得上面提到,如果多個(gè)參數(shù),對(duì)于重名的只返回第一個(gè)符合的項(xiàng)這件事?
具體request的參數(shù)請(qǐng)求中,如果不涉及初次處理,那執(zhí)行的是下面的代碼,很簡(jiǎn)單,就是直接從Map里取對(duì)應(yīng)key的ArrayList,有值的話就從中取第一個(gè)值。
public String getParameter(String name ) {
handleQueryParameters();
ArrayList
if (values != null) {
if(values.size() == 0) {
return "";
}
return values.get(0); //注意這里,就是在兌現(xiàn)只返回第一個(gè)的承諾!!!
} else {
return null;
}
}看完上述內(nèi)容,你們掌握Tomcat是如何處理請(qǐng)求參數(shù)的的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!