(五)连接器

&emps; 连接器最主要的作用就是等待HTTP请求,并依据请求创建Request和Response对象。所以连接器也包含两个部分:

  1. 等待HTTP请求的Connector;
  2. 依据请求创建Request和Response的Processor
org.apache.catalina.connector.http.HttpConnector类

  在Tomcat4中仍存在的一个类,后面已经舍弃了,但基本思路仍在沿用

public final class HttpConnector
    implements Connector, Lifecycle, Runnable {
    
    //1. 初始化
    public void initialize()
    throws LifecycleException {
        //....
    
        // Establish a server socket on the specified port
        //开启侦听端口
        serverSocket = open();
        
        //...
    }
    
    //启动
    public void start() throws LifecycleException {
        //...

        // Start our background thread
        threadStart();

        // Create the specified minimum number of processors
        //会启动一定初始数目的线程处理请求
        while (curProcessors < minProcessors) {
            if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
                break;
            HttpProcessor processor = newProcessor();
            //使用堆栈来存储空闲的processor
            recycle(processor);
        }
        
        //...
    }
    
    //启动自身的线程
    private void threadStart() {
        log(sm.getString("httpConnector.starting"));
        thread = new Thread(this, threadName);
        thread.setDaemon(true);
        thread.start();
    }
    public void run() {
        // Loop until we receive a shutdown command
        while (!stopped) {
            // Accept the next incoming connection from the server socket
            Socket socket = null;
            try {
                socket = serverSocket.accept();
              
                if (connectionTimeout > 0)
                    socket.setSoTimeout(connectionTimeout);
                socket.setTcpNoDelay(tcpNoDelay);
            } catch (IOException e) {
                //...
            
                continue;
            }

            // Hand this socket off to an appropriate processor
            // 调用processor
            HttpProcessor processor = createProcessor();
            if (processor == null) {
                try {
                    log(sm.getString("httpConnector.noProcessor"));
                    socket.close();
                } catch (IOException e) {
                    ;
                }
                continue;
            }
            //通知processor去执行
            processor.assign(socket);
        }

        // Notify the threadStop() method that we have shut ourselves down
        //        if (debug >= 3)
        //            log("run: Notifying threadStop() that we have shut down");
        synchronized (threadSync) {
            threadSync.notifyAll();
        }
    }
    
    private HttpProcessor newProcessor() {
        //穿件Processor
        HttpProcessor processor = new HttpProcessor(this, curProcessors++);
        if (processor instanceof Lifecycle) {
            try {
                ((Lifecycle) processor).start();
            } catch (LifecycleException e) {
                log("newProcessor", e);
                return (null);
            }
        }
        created.addElement(processor);
        return (processor);
    }
}

HttpConnector主要包含以下几个内容:

  1. 初始化,开启侦听端口,监听传入的协议;
  2. 启动,开启HttpConnecotr自身的线程,开启一定数量的Processor线程,用于处理不同的连接请求;
  3. HttpConnector自身线程将建立连接的socket分配给空闲的Processor去处理。
HttpProcessor

  这个类主要关注两点:

  1. HttpConnector和HttpProcessor的交互(connector将socket交给processor的配合);
  2. HttpProcessor读取socket将请求转换为Request和Response;
final class HttpProcessor
    implements Lifecycle, Runnable {
    
    public void start() throws LifecycleException {
        //重复启动判断
        
        threadStart();
    }
    private void threadStart() {
        log(sm.getString("httpProcessor.starting"));
        thread = new Thread(this, threadName);
        thread.setDaemon(true);
        thread.start();
        if (debug >= 1)
            log(" Background thread has been started");
    }
    
    public void run() {
        // Process requests until we receive a shutdown signal
        while (!stopped) {
            // Wait for the next socket to be assigned
            Socket socket = await();
            if (socket == null)
                continue;
            // Process the request from this socket
            try {
                process(socket);
            } catch (Throwable t) {
                log("process.invoke", t);
            }
            // Finish up this request
            connector.recycle(this);
        }
        // Tell threadStop() we have shut ourselves down successfully
        synchronized (threadSync) {
            threadSync.notifyAll();
        }
    }
    private synchronized Socket await() {
        // Wait for the Connector to provide a new Socket
        while (!available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        // Notify the Connector that we have received this Socket
        Socket socket = this.socket;
        available = false;
        notifyAll();
        if ((debug >= 1) && (socket != null))
            log("  The incoming request has been awaited");

        return (socket);
    }
    
    synchronized void assign(Socket socket) {
        // Wait for the Processor to get the previous Socket
        while (available) {
            try {
                wait();
            } catch (InterruptedException e) {
            }
        }
        // Store the newly available Socket and notify our thread
        this.socket = socket;
        available = true;
        notifyAll();
        if ((debug >= 1) && (socket != null))
            log(" An incoming request is being assigned");
    }
}

  available的初始值为false,流程如下:

  1. 当线程开始执行run(), 直接调用await()函数,进入wait()状态,放开对象锁;
  2. Connecotr调用processor.assign(), 先获得锁,因为availabe为false,跳过while循环,设置socket, available=true, 通知其他所有正在等待的地方;
  3. await()得到通知,因为此时available为true,跳出循环,置available为fasle,通知所有wait()的地方(此时没有),run执行后续的处理流程;
  4. 处理完了,connector回收这个processor,然后又进入run()的循环,进入await(), 进入wait();

若3和4之间的时候,connector再次调用assign(), 也不会有问题的. available为false,设置其为true,通知其他地方,但若前一次未处理完,此时是没有进入到await()函数里面的;并且,对于仍在处理中的processor,不可用,也不能调用其assign()

HttpProcessor.process(socket)

  处理流程,将接口的请求转换为Request和Response的过程.
  转换的依据就是HTTP协议内容。

HTTP请求转换为Request和Response的源码分析

//TODO
//TODO

  转换成功后,通过connector.getContainer().invoke(request, response);便可调用servlet容器来处理http请求了,后面讲详细介绍关于容器的知识。

后记
门面模式

   Tomcat4中有org.apache.catalina.connector.HttpRequestFacade,Tomcat7中是org.apache.catalina.connector.RequestFacade

//Tomcat4
public final class HttpRequestFacade
    extends RequestFacade
    implements HttpServletRequest {
}
public class RequestFacade implements ServletRequest {
}


//Tomcat7
public class RequestFacade implements HttpServletRequest {
}
public interface HttpServletRequest extends ServletRequest {
}

设计模式-门面模式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值