`
desert3
  • 浏览: 2140573 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

Tomcat源码分析--ServletRequest.getParameterValue分析,Request字符集&QueryStringEncoding

 
阅读更多
总结:
HTTP GET方式
无forward操作,解码只受Connector参数影响(URIEncoding或者UseBodyEncondig)
有forward操作,解码只受HTTP Header中ContentType指定的字符集或者Filter设置影响
多次forward的话,forward后,第一次从请求取值后,tomcat进行了参数解码,后面就不会再次解码(即多次forward的情况,只有2次解码动作,forward之前和forward之后第一次从request取值)

HTTP GET方式
不管有无forward操作,解码只受HTTP Header中ContentType指定的字符集或者Filter设置影响(第一次从request取值时对应应用环境下的Filter)

request.getParameterValues和request.getParameter的逻辑是类似的,都是看相应的Request参数是否已经转换过(调用getParameter, getParameterValues, getParameterMap, getParameterNames这4个方法都会触发参数转换操作),没有那么调用相应的转换程序,否则就直接操作转换好的paramters(HashMap)

ApplicationDispatcher是RequestDispatcher接口的final标准实现,允许请求forward到其他资源进行服务(include也使用该类)。这个实现是在Application应用程序级别的Servlet中对请求和响应进行包装(ServletRequest,ServletResponse或者ServletRequestWrapper,ServletResponseWrapper)
参考:final class: ApplicationDispatcher

RequestDispatcher.forward前使用的是,RequestFacade;forward之后使用的是ApplicationHttpRequest。它们对用来给请求解码的编码的默认值处理不同,具体参考如下。而如果在forward之前,调用过request.getParameter方法来取值,那么forward后,CoyteRequest内的信息可能被解码,但是当前请求ApplicationHttpRequest对应的参数还没有解码!2部分参数会合成并且当前请求ApplicationHttpRequest对应的参数是放在前面的!注意:此时重新解码的参数是Get方式的QueryString的参数,POST提交的参数还是在RequestFacade进行解码!!!

forward之前从RequestFacade取值
1,调用request.getParameterValues方法
2,对应org.apache.catalina.connector.RequestFacade类的getParameterValues方法(RequestFacade是一个HttpServletRequest实现类,他包含一个叫Coyote request的属性,具体请求执行内容由具体的Coyote request决定)
3,调用org.apache.catalina.connector.Request的getParameterValues方法,如果第一次取调用该方法(即还没有做过参数转换----把QueryString或者POST上来的比特数组通过设定的编码转成真正的值),那么进行参数转换操作,否则直接从已经转换好的参数列表中提取相应参数的值
4,参数转换:
  • a.取得Request字符集enc:1,看请求本身是否已经被设置了字符集(通过request.setCharacterEncoding设置),如果有直接返回,如果没有,那么根据请求的Content-Type,看Content-Type中是否通过charset=xxx设置了字符集,有就起作用,没有就返回null
  • b.取得Connect参数UseBodyEncodingForURI对应的值
  • c.如果a)步骤取得的Request字符集enc非空,那么Parameters字符集等于Request字符集,如果UseBodyEncodingForURI为true,那么QueryString解码使用的字符集QueryStringEncoding的值也设置为请求字符集(和Parameters一致)
  • d.如果a)步骤取得的Request字符集enc为空,那么Parameters字符集等于默认的字符集ISO-8859-1,如果UseBodyEncodingForURI为true,那么QueryString解码使用的字符集QueryStringEncoding的值也设置为默认的字符集ISO-8859-1(和Parameters一致)
  • e.对QueryString所传递的参数进行解码操作(根据QueryStringEncoding)
  • f.看HTTP METHOD是否等于POST,同时看Content-Type是否以application/x-www-form-urlencoded开始,是的话,对通过POST方式上传的比特数组byte[] postData,用d)步骤取得的Parameters字符集进行解码(如果没有值,就默认用ISO-8859-1),并把解码后的参数值保存到参数列表中等待下次复用(只解码一次!!!)


forward之后从ApplicationHttpRequest取值注意,forward之后,这个Request中解码的只有QueryString的参数,且从request取值的时候刚解码的参数优先级高(数组下标),而post提交的参数,会直接调用ApplicationHttpRequest中嵌套的RequestFacade的相应方法取值,即Post方式提交的参数的解码,受到forward之前请求的相关环境的影响!!!
1,调用request.getParameterValues方法
2,对应8, org.apache.catalina.core.ApplicationHttpRequest类的getParameterValues方法(ApplicationHttpRequestS有一个ServletRequest的属性,而RequestFacade是ServletRequest的一个属性),由此可以看出,对于参数取值,forward后的Request多一层包装。
3,调用org.apache.catalina.core.ApplicationHttpRequest的getParameterValues方法,如果参数还没有被转换过那么进行参数转换操作,否则直接从已经转换好的参数列表中提取相应参数的值
4,参数转换:
  • a.取得已有的参数(即从当前request中取得CoyteRequest中已有的参数,注意:如果一个url前面做过forward的话,并且在forward之前已经从Request取过值的话,CoyteRequest中的取得的参数是已经转换过的!!!但是ApplicationHttpRequest本身的Parameter并没有被转换过!!!)代码如下:parameters = new HashMap();parameters = copyMap(getRequest().getParameterMap());
  • b.调用mergeParameters方法,把ApplicationHttpRequest自己的参数QueryString对应的参数值解码出来,并和CoyteRequest中已有的参数合并,刚解码出来的参数放到数组前面,这样你使用Request.getParametr来取字段的值的时候,取出来的是刚解码的值,而如果用取数组的方法,那么取出来是整个数组。

  • ApplicationHttpRequest解码自己参数的逻辑:
    取得Request字符集,如果取不到,就直接使用ISO-8859-1字符集来解码。然后调用RequestUtil.parseParameters(queryParameters, queryParamString, encoding)来进行解码操作。表明此时,Connector的参数UseBodyEncodingForURI和URIEncoding并没有影响QueryString的解码

5,总结:
  • a.QueryStringEncoding:用来解码QueryString信息
  • b.Request字符集Content-Type中的字符集影响的是Request字符集,并不影响QueryStringEncoding,间接影响Parameters字符集
  • c.Parameters字符集:用来解码POST参数【比特数组】时使用的字符集,如果Request字符集非空,那么Parametr是字符集=Request字符集,否则等于默认字符集ISO-8859-1。Parameters字符集用来解码POST DATA对应的比特数组(解码后在JVM中以Unicode的形式存在)
  • d.参考Tomcat源码分析--HTTP,AJP请求内部处理流程,可以看出对于RequestFacade请求,QueryStringEncoding的值首先从Connector中的参数URIEncoding中取,同时参考下面的说明,可知useBodyEncodingForURI的优先级 大于URIEncoding
  • e.Request字符集:如果没有通过request.setCharacterEncoding方法设置字符集,那么默认从Content-Type中提取charset=xxx的值,如果通过request.setCharacterEncoding方法设置了新的字符集,那么新的字符集会覆盖Content-Type中的字符集
  • f.如果设置了Connector的参数useBodyEncodingForURI=true,那么把QueryStringEncoding值设置为和Request字符集相同!
分享到:
评论

相关推荐

    servlet-api-2.4.jar.zip

    javax.servlet.ServletRequest javax.servlet.http.HttpUtils javax.servlet.ServletResponse javax.servlet.ServletException javax.servlet.http.HttpServlet javax.servlet.http.HttpSession javax.servlet....

    tomcat-8.5.51.rar

    Tomcat简介 Tomcat Tomcat工作原理 当客户请示某个资源时, Servlet容器使 用 ServletRequest对象把客户的请求信 息封装起来,然后调用 Java servlet ap 中定义的一些 Servlet方法,完成 Servlet 的执行,接着把 Servlet...

    java-servlet-api.doc

    Servlet被初始化之后,它已经可以处理来自客户端的请求,每一个来自客户端的请求都被描述成一个ServletRequest对象,Servlet的响应被描述成一个ServletResponse对象。 当客户端发出请求时,Servlet引擎传递给Servlet...

    servlet2.4doc

    The doFilter method of the Filter is called by the container each time a request/response pair is passed through the chain due to a client request for a resource at the end of the chain. doGet...

    登录过滤器

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; ...

    servlet电子书籍 pdf格式

    2.5 ServletRequest ....................................................................8 request.getInputStream()方法................................................8 request.getReader()方法 ..........

    javaWEB总结(6):ServletRequest

    javaWEB总结(6):ServletRequest测试代码

    javax.servlet.jar下载

    javax.servlet.ServletRequest.class javax.servlet.ServletResponse.class javax.servlet.ServletConfig.class javax.servlet.ServletInputStream.class javax.servlet.ServletOutputStream.class javax.servlet....

    jboss中access 日志的配置

    deploy/jbossweb-tomcat55.sar/server.xml <Valve className="org.apache.catalina.valves.FastCommonAccessLogValve" prefix="access_log." suffix=".log" pattern="%h %t %r %s %D" directory="${jboss....

    tomcat技术文档.doc

    Tomacat是一种servlet/jsp容器。... servletRequest包含请求,-----servlet容器吧这两个对象传给所请求的servlet,-----servlet将相应的结果写入servletResponse,----返回给容器----,有容器反馈给客户

    java web 修改request携带的参数信息

    一个非常棒的程序,用于修改request携带的参数信息。使用了filter等技术。

    filter-源代码.rar

    doFilter(ServletRequest,ServletResponse,FilterCha):代表filter执行过滤的核心方法,如果某资源在已经被配置到这个filter进行过滤的话,那么每次访问这个资源都会执行doFilter方法 destory():代表是filter销毁...

    java sql注入l

    44 throw new IOException("您发送请求中的参数中含有非法字符"); 45 //String ip = req.getRemoteAddr(); 46 } else { 47 chain.doFilter(args0,args1); 48 } 49 } 50 51 //效验 52 protected ...

    request.setAttribute 语句前总显示红色感叹号解决办法 HTTP Status 500 -

    description The server encountered an internal error () that prevented it from fulfilling this request. exception javax.servlet.ServletException: Servlet execution threw an exception root cause ...

    Java™ Servlet 规范.

    目录 前言 ............................... 3 其他资料 ....................................................................................................................Request .............................

    5.Tomcat服务器运行原理.doc

    Tomcat服务器创建一个ServletRequest对象,在ServletRequest对象中包含了客户请求信息及其他关于客户的信息,如请求头,请求正文,以及客户机的IP地址等

    Servlet3.1规范(最终版) PDF

    Servlet3.1规范(最终版) JavaTM Servlet 规范 版本 3.1(最终版) Shing Wai Chan Rajiv Mordani [作者] 穆茂强 张开涛 [译者] 2012年6月翻译 2013年7月修订 目录 前言 ..................................

    JSP2.0技术手册pdf(带示例源码).zip

    1-2 安装 Tomcat 5.0.16 1-3 安装 JSPBook 站台范例 1-4 安装 Ant 1.6 第二章 Servlet 2.4 简介 2-1 Servlet 简介 2-2 First Servlet Sample Code 2-3 Servlet 的生命周期 2-4 Servlet 范例程序 2-5 Servlet 2.4 的...

    servlet-api.jar

    当然这个jar的接口是按照servlet规范编写的,面向标准接口编程的好处就是我们开发出的一个web工程即可以部署到tomcat、也可以部署到weblogic或其他servlet容器下运行,所有的servlet容器都使用了相同接口所以我们...

    EL表达式的详细使用

    将请求参数名称映射到单个字符串参数值(通过调用 ServletRequest.getParameter (String name) 获得)。getParameter (String) 方法返回带有特定名称的参数。表达式 $(param.name) 相当于 request.getParameter ...

Global site tag (gtag.js) - Google Analytics