Tomcat源码分析--HTTP,AJP请求内部处理流程

HTTP 1.1
server.xml配置使用HTTP1.1处理请求
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>

[color=green]AJP1.3协议[/color]([color=red]Apache和Tomcat集成时使用[/color],Apache处理静态内容,使用Apache的SSL,在很多应用环境下,比通过HTTP协议来访问单独的Tomcat有更加好的性能。在用户[color=red]结合Engine的jvmRoute属性做loadbalance的时候[/color]使用到)
配置:
<Connector address="localhost" port="8081" protocol="AJP/1.3" redirectPort="8443" connectionTimeout="600000"/>

Tomcat内部处理流程
1,HTTP请求发过来后,Tomcat从自己的线程池中提起出一个线程来处理
2,入口org.apache.tomcat.util.net.JIoEndpoint,该类用来处理传递进来的TCP连接,它实现了一个简单的[color=red]服务器模式:一个监听线程用来接收socket以及为每个进来的连接创建一个worker来处理[/color]。更加高级的功能会涉及到线程重用,如队列等。
[color=green]2#,入口org.apache.tomcat.util.net.AprEndpoint[/color](APR定制线程池,提供Socket接收线程,Socket轮询线程,文件传输线程,Workers线程池);主方法run()监听进来的TCP/IP连接,并用合适的processor来处理。
3,根据Server.xml中配置的协议HTTP/1.1,调用org.apache.coyote.http11.Http11Protocol来后续处理。该类是HTTP1.1协议的实现类,包括线程功能。[color=red]它处理单个线程和基于流的协议。但是不适用与JK协议如JNDI。[/color]主方法process(Socket socket)的内容如下:
[list]
[*]a.从recycledProcessors中提取已有的processor,如果提取不到,那么创建一个(创建的时候会设置上HTTP1.1相应的一些属性如keepAliveTimeout以及生成request和response信息。[color=red]注意此时request中还不包括画面提交上来的HTTP Header和Parameters[/color]等信息)
[*]b.SSL相关设置
[*]c.调用processor的process方法进行处理
[/list]
[color=green]3#,根据Server.xml中配置的协议AJP/1.3,调用org.apache.coyote.ajp.AjpAprProtocol来后续处理。[/color]主方法process(long socket)处理类似,如果从池中提取不到合适的processor,就生成并设置先关属性,然后调用processor的process方法。
4,org.apache.coyote.http11.Http11Processor该类用来处理HTTP请求。主方法process(Socket socket)的内容如下:
[list]
[*]a.设置socket相关的地址变量和IO信息,即把socket.getInputStream()和socket.getOutputStream()转进来。其他socket.getInputStream()设置给InternalInputBuffer
[*]b.调用InternalInputBuffer的parseRequestLine和parseHeader方法,把HTTP请求头内的相关信息读取处理,并使用prepareRequest方法保存到request中的相关变量上去。这时,[color=red]HTTP Method, HTTP URI, HTTP QUERY STRING, HTTP PROTOCOL的值都是在这里被读取进来,这时候的URI还是没有被解码的,即还含有%XX的信息。[/color]
[*]c.调用org.apache.catalina.connector.CoyoteAdapter的service方法继续处理
[/list]
[color=green]4#,org.apache.coyote.ajp.AjpAprProcessor的处理类似[/color]
5,CoyoteAdapter类实现了一个请求处理器(request processor),用来代理处置Coyote processor。主方法service(org.apache.coyote.Request req, org.apache.coyote.Response res)主要内容如下:
[list]
[*]a.根据Connector来创建相应的Servlet Request和Servlet Response,并把connector配置中的getURIEncoding保存读取出来设置到QueryStringEncoding中,后面给QueryString解码的时候可能使用到,也可能被useBodyEncodingForURI覆盖!
[*]b.调用[color=red]postParseRequest方法处理其他的请求参数, 如果参数是通过HTTP POST方式传递进来的,那么把对应的比特数组存储起来,在第一次通过Request.getParameterValue()访问的时候解码得到真正的参数值[/color],如果参数是通过HTTP GET方式传递进来,那么看connector.getURIEncoding有值,有的话在就用指定的字符集把未解码的URI对应的比特数组解码得到相应的值,否则直接读取未解码的字符,这也不会有问题,因为根据URI规范,URI采用US-ACSII编码,这时候的读取的char,还是有意义的,如%xx的形式。
[*]c.调用Catalina引擎继续处理
[/list]
6,org.apache.catalina.core.StandardEngineValve(默认的StandardEngine引擎实现)
[list]
[*]a.主方法invoke(Request request, Response response),根据请求的server name,选取合适的Host继续处理请求
[/list]
7,StandHost选择
[list]
[*]a.org.apache.catalina.valves.AccessLogValve处理访问日志
[*]b.org.apache.catalina.valves.ErrorReportValve根据response状态,输出相应的错误页面
[/list]
8,org.apache.catalina.core. StandardContextValve(默认的StandardContext实现),处理和webapps下面具体项目的情况,如不允许请求直接访问项目下的/WEB-INF和/WEB-INF目录
9,org.apache.catalina.core. StandardWrapperValve(默认的StandardWrapper实现),[color=red]调用和请求匹配的Servlet并Servlet的生命周期(如果Servlet有对应的filter,那么就调用它)和SingleThreadModel单线程模式的支持[/color]
10,org.apache.catalina.core. ApplicationFilterChain,实现了javax.servlet.FilterChain用来管理每个请求对应的Filter链的执行,所有Filter执行完成后调用servlet的service方法
11,javax.servlet.http.HttpServlet把ServletRequest请求转换成HttpServletRequest,调用相应Servlet的service方法提供服务。如果使用的是Struts框架,那么使用的是org.apache.struts.action. ActionServlet
12,Struts1.1框架使用[color=red]RequestProcessor[/color]来处理真实的请求内容
13,后续就是调用相应的Action进行业务处理
14,[color=red]注意,在第一次调用Request.getParameterValue("item")的时候,会进行转码操作,转码后相应的参数就是以Unicode的形式存在在jvm中,再根据需要可以传递各种形式的编码给客户端!(Unicode可以转换成任意字符集后,再输出[输出的其实是对应字符集的Byte数组])[/color]

[color=green]调用RequestDispatcher.forward方法前后,对应的Request实现类不同[/color],RequestDispatcher.forward前使用的是org.apache.catalina.connector.RequestFacade类而RequestDispatcher.forward后使用的是org.apache.catalina.core.ApplicationHttpRequest,他们内部在ParseParameter的时候, 用来解码的默认的编码逻辑不同,使用不同的协议时,影响乱码的因素不同! (request.getParameter和request.getParameterValues取值时,第一次请求需要解码!)

具体参考[url=http://desert3.iteye.com/admin/blogs/1420119]Tomcat源码分析--ServletRequest.getParameterValues内部分析,Request字符集&QueryStringEncoding[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值