tomcat源码阅读-1

tomcat源码系列文章开始!!(不是为了说教,市面上讲tomcat的很多,我只是做笔记而已。。。)

虽然是tomcat源码系列的第一篇,但是其实是从第三章开始写的,原因嘛。。。因为我愿意这么写。。。


第三章源码分析:

主要类有以下几个:
1.启动类Bootstrap.class
2.连接器相关类HttpConnector.class和HttpProcessor.class
3.HTTP请求相关类HttpRequest.class,HttpResponse.class(以及两个facade类,主要是出于安全考虑,封装了组件内部的通信部分,只暴漏必要的部分)
4.请求处理类:静态资源处理类StaticResourceProcessor.class和动态资源处理类ServletProcessor.class

启动和处理请求流程如下:
1.首先Bootstrap启动类创建一个HttpConnector实例,该实例的类是一个实现了多线程接口的类,通过启动额外线程来监听相应地址和端口,并且阻塞等待请求到来:

    while (!stopped) {
      // Accept the next incoming connection from the server socket
      Socket socket = null;
      try {
        socket = serverSocket.accept();
      }
      catch (Exception e) {
        continue;
      }
      // Hand this socket off to an HttpProcessor
      HttpProcessor processor = new HttpProcessor(this);
      processor.process(socket);
    }

以上代码通过一个while循环来接受请求,这几乎是所有web服务器的实现方式(在一个循环中阻塞等待请求),每次接收到一个请求都会创建一个HttpProcessor实例来处理请求,该类的职责就是解析http请求并且创建和填充HttpRequest和HttpResponse对象,注意这个时候只是把http请求解析到了Httprequest中,具体请求参数等步骤并没有做,而是等到具体servlet实例调用getParamter()等方法的时候才会去解析,这样的好处就是不做不必要的解析,在需要的时候再解析,减少了CPU等开销。代码如下:

      input = new SocketInputStream(socket.getInputStream(), 2048);
      output = socket.getOutputStream();

      // create HttpRequest object and parse
      request = new HttpRequest(input);

      // create HttpResponse object
      response = new HttpResponse(output);
      response.setRequest(request);

      response.setHeader("Server", "Pyrmont Servlet Container");

      parseRequest(input, output);
      parseHeaders(input);

接下来的一步就是根据请求的类型将请求传递给相应的动/静态处理器来处理:
      //check if this is a request for a servlet or a static resource
      //a request for a servlet begins with "/servlet/"
      if (request.getRequestURI().startsWith("/servlet/")) {
        ServletProcessor processor = new ServletProcessor();
        processor.process(request, response);
      }
      else {
        StaticResourceProcessor processor = new StaticResourceProcessor();
        processor.process(request, response);
      }

静态处理器就不说了,这里再说一下动态(servlet)处理器部分的处理步骤:
1.首先通过解析url识别出请求的servlet名字
    String uri = request.getRequestURI();
    String servletName = uri.substring(uri.lastIndexOf("/") + 1);

2.然后创建一个类加载器,并且加载请求的servlet

URLClassLoader loader = null;
try {
// create a URLClassLoader
URL[] urls = new URL[1];
URLStreamHandler streamHandler = null;
File classPath = new File(Constants.WEB_ROOT);
String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;
urls[0] = new URL(null, repository, streamHandler);
loader = new URLClassLoader(urls);
}
catch (IOException e) {
System.out.println(e.toString() );}
Class myClass = null;
try {
myClass = loader.loadClass(servletName);
}
catch (ClassNotFoundException e) {
System.out.println(e.toString());
}


3.实例化servlet,调用service方法处理request(注意这里传入的是facade类)

      servlet = (Servlet) myClass.newInstance();
      HttpRequestFacade requestFacade = new HttpRequestFacade(request);
      HttpResponseFacade responseFacade = new HttpResponseFacade(response);
      servlet.service(requestFacade, responseFacade);


4.最后返回结果,结束请求


这里再次提一下,只有在加载的servlet方法中调用了request.getParameters()等方法,才会解析请求内容,并且只会解析一次。
解析步骤可以在HttpRequest类中找到,是调用了 parseParameters()方法

ok,基本上一个请求流程就是这样了,另外HttpRequest类中的很多方法值得细看,特别是一些同步的部分


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值