Tomcat是如何处理请求参数的,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。
url请求中带参数的形式(即我们常说的GET请求),是在请求目标后以问号开始,后面是参数名值对,多个名值对间以和号(&)分隔。
通过URL传递的参数,在Tomcat中是怎么解析出来的呢?
我们一般在Servlet中要获取某个参数,一般通过如下的方式
String value = request.getParameter("paramName");
我们在需要的时候通过参数名直接取,这个值又是什么设置的?名值对又是如何对应起来的?
我们顺着getParameter方法这个藤,来摸摸实现这个瓜。
我们在使用HttpServletRequest这个对象时,其实一直在使用的是其一个门面对象(RequestFacade),此对象使用了设计模式中的门面模式,封装了HttpServletRequest中的一些细节,只暴露出一些必要的API。
实际请求处理时,则调用其封装的request对象。
getParameter方法的代码是下面这个样子:
/ * 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);
}
每次请求时,会先判断参数是否已经解析过,如果已经解析过就直接返回。
protected void parseParameters() {
parametersParsed = true; //注意这里,解析之后就设为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();
}
所以,这个名值对的配置,初始化,是发生在第一次调用getParameter方法时。
再向下,这个handleQueryParameters是具体处理的方法。这里我们假设请求如下url:
http://localhost:8080/test?abc=1&def=2
在handleQueryParameters方法中,我们通过debug界面观察。
此处parameters包含一个属性queryMB,其值刚好是我们传进来的字符串。所以后面的参数处理,是基于这个属性进行的。
再之后,在Parameter这个类的processParameter方法中,
我们看到,基本是遍历字符串中的各个char,遇到特定字符=和&之后,再从各个index获取等号前后的名和值。
中间特别的一个地方是,遇到%和+时,是出现了像汉字一类的,其实是需要转义的,所以处理也是在此进行的。
解析后,名值对是存放在ArrayList这样一个数据结构中。看下面的代码,
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);
}
是执行完上面的方法后,代码向下执行,看到的parameters这个对象,值已经变成了这样:
abc=1,\n def=2,\n
注意上面代码标红加粗的这两行,
你是否还记得上面提到,如果多个参数,对于重名的只返回第一个符合的项这件事?
具体request的参数请求中,如果不涉及初次处理,那执行的是下面的代码,很简单,就是直接从Map里取对应key的ArrayList,有值的话就从中取第一个值。
public String getParameter(String name ) {
handleQueryParameters();
ArrayList<String> values = paramHashValues.get(name);
if (values != null) {
if(values.size() == 0) {
return "";
}
return values.get(0); //注意这里,就是在兑现只返回第一个的承诺!!!
} else {
return null;
}
}看完上述内容,你们掌握Tomcat是如何处理请求参数的的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。