`
desert3
  • 浏览: 2160696 次
  • 性别: 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字符集相同!
分享到:
评论

相关推荐

    commons-fileupload-1.4 jar包.rar

    List<FileItem> items = upload.parseRequest(request); for (FileItem item : items) { if (!item.isFormField()) { // 判断是否为文件字段 String fileName = item.getName(); // 处理文件,如保存到服务器 } ...

    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....

    servlet-api-3.0.jar包

    3. **微容器**:Servlet 3.0允许在没有完整应用服务器的情况下运行Servlet和Filter,只需要一个简单的“微容器”(例如Jetty或Tomcat的嵌入式版本)。这使得开发和测试环境更加轻量级。 4. **动态注册**:除了使用...

    servlet-api-src.jar

    在`servlet-api-src.jar`中,`javax`包下包含了一系列与Servlet相关的类和接口,如`ServletConfig`、`ServletRequest`、`ServletResponse`等。`ServletConfig`用于配置Servlet,它包含了Servlet的初始化参数;`...

    commons-fileupload-1.2.2.jar.zip

    2. **创建Servlet或其他处理请求的组件**:在处理请求的方法中,通过ServletRequest接口的isMultipartContent()检查请求是否包含文件上传。 3. **解析请求**:使用`DiskFileItemFactory`工厂类配置存储策略,然后用...

    tomcat-coyote.jar.zip

    《深入解析Tomcat Coyote组件》 在Java Web开发领域,Apache Tomcat是一个广泛应用的开源Web服务器和Servlet容器。而Tomcat Coyote是Tomcat核心组件之一,它负责处理HTTP请求和响应,扮演着关键的角色。本文将深入...

    解决Tomcat中文乱码

    1. **默认字符集问题**:Tomcat服务器默认采用ISO-8859-1字符集进行编码解码,该字符集并不支持中文字符。 2. **配置文件编码不一致**:Web应用中的`.jsp`文件、配置文件等可能采用了不同的编码格式,例如GBK或UTF-8...

    tomcat-8.5.51.rar

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

    servlet-api.jar.zip( 86 k).zip

    在部署到生产环境时,Web服务器如Tomcat、Jetty等会提供自己的Servlet容器实现。 LICENSE.txt文件可能包含了该jar包的许可协议信息,对于开源软件,这通常意味着Apache License、GPL、MIT等,具体取决于项目。这些...

    servlet源码 servlet-api-src javax.servlet.Servlet源码

    在Web应用启动时,Servlet容器(如Tomcat)会根据配置加载Servlet,并调用`init()`进行初始化。当收到请求时,容器会调用`service()`,根据请求类型分发到相应的do方法。当Web应用关闭或者Servlet不再需要时,容器会...

    java技术面试-----------javaWeb.md

    ### JavaWeb高频面试知识... - `service(ServletRequest req, ServletResponse res)`:服务方法。 - `destroy()`:销毁方法。 以上是JavaWeb领域内的一些核心知识点,这些知识点对于理解和掌握JavaWeb开发非常重要。

    filter-for-user.rar_判断登录

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

    javax.servlet-api-4.0.1.jar

    `Filter`接口定义了`doFilter(ServletRequest, ServletResponse, FilterChain)`方法,`FilterChain`用于传递请求给下一个Filter或Servlet。 7. **Listener**:Servlet API还支持事件监听器,如`...

    大家经常会用到的jar包servlet-api.jar&jsp-api.jar

    - 在Tomcat、Jetty等Java Web容器中,这些jar包通常是内建的,开发者不需要手动添加。但在某些情况下,如构建独立的可部署WAR文件时,需要将这两个jar包包含在项目中。 **注意事项** - 使用第三方库时,确保版本...

    java-servlet-api.doc

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

    tomcat编码问题

    首先,Tomcat默认的字符集可能并不包含GBK,GBK是中国大陆广泛使用的汉字编码标准,它包含了更多的中文字符。因此,当请求参数或响应内容包含GBK编码的中文字符时,如果不进行正确的转换,就会出现乱码。 1. **配置...

    Struts2-forbid-getrequest.zip_DEMO

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

    apache-tomcat-6.0.33-src tomcat6.0.33源代码

    源代码是理解任何软件内部运作的最佳方式,`apache-tomcat-6.0.33-src`即为Tomcat 6.0.33的源码包。通过阅读源码,开发者可以深入理解以下关键知识点: 1. **Servlet容器**:Tomcat作为Servlet容器,其主要职责是...

Global site tag (gtag.js) - Google Analytics