1. 程式人生 > >springboot中tomcat的啟動(八)監聽啟動,讀寫

springboot中tomcat的啟動(八)監聽啟動,讀寫

tomcat中所有的元件都啟動了之後,後面就需要繫結監聽埠了,監聽埠的地方是在ServletWebServerApplicationContext的finishRefresh()方法中,最後會進入了NioEndPoint的bind()方法,在這個方法中進行了埠的繫結和監聽

    @Override
    public void bind() throws Exception {

        serverSock = ServerSocketChannel.open();
        socketProperties.setProperties(serverSock.socket());
        InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
        serverSock.socket().bind(addr,getAcceptCount());
        serverSock.configureBlocking(true); //mimic APR behavior

        // Initialize thread count defaults for acceptor, poller
        if (acceptorThreadCount == 0) {
            // FIXME: Doesn't seem to work that well with multiple accept threads
            acceptorThreadCount = 1;
        }
        if (pollerThreadCount <= 0) {
            //minimum one poller thread
            pollerThreadCount = 1;
        }
        setStopLatch(new CountDownLatch(pollerThreadCount));

        // Initialize SSL if needed
        initialiseSsl();

        selectorPool.open();
    }

這段程式碼的功能就是開啟ServerSocketChannel,然後監聽埠。我們跟入程式碼看看監聽後是如何處理的,監聽其實是用到了Selector去輪詢的,監聽埠並處理邏輯的程式碼就在最後一行:selectorPool.open();這個方法後面進入了NioBlockingSelector的open()方法。

    public void open(Selector selector) {
        sharedSelector = selector;
        poller = new BlockPoller();
        poller.selector = sharedSelector;
        poller.setDaemon(true);
        poller.setName("NioBlockingSelector.BlockPoller-"+(++threadCounter));
        poller.start();
    }

這個open()方法中的BlockPoller類就是做了輪詢獲取接收到的訊息並處理的類。這個BlockPoller是Thread的子類,其run方法就是執行了本應用向channel中寫資料的邏輯。

而讀資料的邏輯是在NioEndPoint的內部類SocketProcessor的duRun()方法中,將讀取到的資訊封裝到了sockerWrapper,然後經過一系列路徑,進入到了spring的OncePerRequestFilter。其序列圖如下:

然後通過tomcat的ApplicationFilterChain進入了Spring的OncePerRequestFilter的doFilter()方法。

這裡有一個地方很奇怪,為什麼tomcat的FilterChain會進入Spring的Filter中呢,因為在Springboot的spring-boot-starter-web依賴了tomcat的tomcat-embed-core包。然後在AbstractFilterRegistrationBean中的addRegistration方法中,註冊了該filter。