您好,登錄后才能下訂單哦!
Tomcat是如何處理請(qǐng)求參數(shù)的,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
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 <code>null</code>. 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)中。看下面的代碼,
public void addParameter( String key, String value ) {
ArrayList<String> values = paramHashValues.get(key);
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<String> values = paramHashValues.get(name);
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)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。