最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Tomcat處理http請(qǐng)求之源碼分析

 更新時(shí)間:2023年05月29日 10:30:09   作者:京東云開發(fā)者  
本文將從請(qǐng)求獲取與包裝處理、請(qǐng)求傳遞給Container、Container處理請(qǐng)求流程,這3部分來講述一次http穿梭之旅,感興趣的同學(xué)可以跟著小編一起學(xué)習(xí)

1 請(qǐng)求包裝處理

tomcat組件Connector在啟動(dòng)的時(shí)候會(huì)監(jiān)聽端口。以JIoEndpoint為例,在其Acceptor類中:

protected class Acceptor extends AbstractEndpoint.Acceptor {
    @Override
    public void run() {
        while (running) {
            ……
            try {
                //當(dāng)前連接數(shù)
                countUpOrAwaitConnection();
                Socket socket = null;
                try {
                    //取出隊(duì)列中的連接請(qǐng)求
                    socket = serverSocketFactory.acceptSocket(serverSocket);
                } catch (IOException ioe) {
                    countDownConnection();
                }
                if (running && !paused && setSocketOptions(socket)) {
                    //處理請(qǐng)求
                    if (!processSocket(socket)) {
                        countDownConnection();
                        closeSocket(socket);
                    }
                } else {
                    countDownConnection();
                    // Close socket right away
                    closeSocket(socket);
                }
            } 
            ……
        }
    }
}

在上面的代碼中,socket = serverSocketFactory.acceptSocket(serverSocket);與客戶端建立連接,將連接的socket交給processSocket(socket)來處理。在processSocket中,對(duì)socket進(jìn)行包裝一下交給線程池來處理:

protected boolean processSocket(Socket socket) {
    try {
        SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
        wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
        wrapper.setSecure(isSSLEnabled());
        //交給線程池處理連接
        getExecutor().execute(new SocketProcessor(wrapper));
    } 
    ……
    return true;
}

線程池處理的任務(wù)SocketProccessor,通過代碼分析:

protected class SocketProcessor implements Runnable {
    protected SocketWrapper<Socket> socket = null;
    protected SocketStatus status = null;
    @Override
    public void run() {
        boolean launch = false;
        synchronized (socket) {
            SocketState state = SocketState.OPEN;
            try {
                serverSocketFactory.handshake(socket.getSocket());
            } 
            ……
            if ((state != SocketState.CLOSED)) {
                //委派給Handler來處理
                if (status == null) {
                    state = handler.process(socket, SocketStatus.OPEN_READ);
                } else {
                    state = handler.process(socket,status);
                }
            }}}
            ……
}

即在SocketProcessor中,將Socket交給handler處理,這個(gè)handler就是在Http11Protocol的構(gòu)造方法中賦值的Http11ConnectionHandler,在該類的父類process方法中通過請(qǐng)求的狀態(tài),來創(chuàng)建Http11Processor處理器進(jìn)行相應(yīng)的處理,切到Http11Proccessor的父類AbstractHttp11Proccessor中。

public SocketState process(SocketWrapper socketWrapper) {
    RequestInfo rp = request.getRequestProcessor();
    rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
    // Setting up the I/O
    setSocketWrapper(socketWrapper);
    getInputBuffer().init(socketWrapper, endpoint);
    getOutputBuffer().init(socketWrapper, endpoint);
    while (!getErrorState().isError() && keepAlive && !comet && !isAsync() &&
            upgradeInbound == null &&
            httpUpgradeHandler == null && !endpoint.isPaused()) {
        ……
        if (!getErrorState().isError()) {
            // Setting up filters, and parse some request headers
            rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
            try {
                //請(qǐng)求預(yù)處理
                prepareRequest();
            } 
            ……
        }
        ……
        if (!getErrorState().isError()) {
            try {
                rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
                //交由適配器處理
                adapter.service(request, response);
                if(keepAlive && !getErrorState().isError() && (
                        response.getErrorException() != null ||
                                (!isAsync() &&
                                statusDropsConnection(response.getStatus())))) {
                    setErrorState(ErrorState.CLOSE_CLEAN, null);
                }
                setCometTimeouts(socketWrapper);
            } 
        }
    }
    ……
}          

可以看到Request和Response的生成,從Socket中獲取請(qǐng)求數(shù)據(jù),keep-alive處理,數(shù)據(jù)包裝等等信息,最后交給了CoyoteAdapter的service方法

2 請(qǐng)求傳遞給Container

在CoyoteAdapter的service方法中,主要有2個(gè)任務(wù):

•第一個(gè)是org.apache.coyote.Request和
org.apache.coyote.Response到繼承自HttpServletRequest的org.apache.catalina.connector.Request和org.apache.catalina.connector.Response轉(zhuǎn)換,和Context,Wrapper定位。

•第二個(gè)是將請(qǐng)求交給StandardEngineValve處理。

public void service(org.apache.coyote.Request req,
                        org.apache.coyote.Response res) {
    ……
    postParseSuccess = postParseRequest(req, request, res, response);
    ……
    connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
    ……
}

在postParseRequest方法中代碼片段:

connector.getMapper().map(serverName, decodedURI, version,
                                      request.getMappingData());
request.setContext((Context) request.getMappingData().context);
request.setWrapper((Wrapper) request.getMappingData().wrapper);

request通過URI的信息找到屬于自己的Context和Wrapper。而這個(gè)Mapper保存了所有的容器信息,不記得的同學(xué)可以回到Connector的startInternal方法中,最有一行代碼是mapperListener.start(); 在MapperListener的start()方法中,

public void startInternal() throws LifecycleException {
    setState(LifecycleState.STARTING);
    findDefaultHost();
    Engine engine = (Engine) connector.getService().getContainer();
    addListeners(engine);
    Container[] conHosts = engine.findChildren();
    for (Container conHost : conHosts) {
        Host host = (Host) conHost;
        if (!LifecycleState.NEW.equals(host.getState())) {
            registerHost(host);
        }
    }
}

MapperListener.startInternal()方法將所有Container容器信息保存到了mapper中。那么,現(xiàn)在初始化把所有容器都添加進(jìn)去了,如果容器變化了將會(huì)怎么樣?這就是上面所說的監(jiān)聽器的作用,容器變化了,MapperListener作為監(jiān)聽者。他的生成圖示

通過Mapper找到了該請(qǐng)求對(duì)應(yīng)的Context和Wrapper后,CoyoteAdapter將包裝好的請(qǐng)求交給Container處理。

3 Container處理請(qǐng)求流程

從下面的代碼片段,我們很容易追蹤整個(gè)Container的調(diào)用鏈: 用時(shí)序圖畫出來則是:

最終StandardWrapperValve將請(qǐng)求交給Servlet處理完成。至此一次http請(qǐng)求處理完畢。

到此這篇關(guān)于Tomcat處理http請(qǐng)求之源碼分析的文章就介紹到這了,更多相關(guān)Tomcat請(qǐng)求處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Tomcat內(nèi)存泄漏檢測(cè)和預(yù)防策略

    Tomcat內(nèi)存泄漏檢測(cè)和預(yù)防策略

    內(nèi)存泄漏是Java應(yīng)用程序中常見的問題,尤其是在使用如Tomcat這樣的應(yīng)用服務(wù)器時(shí),檢測(cè)和預(yù)防內(nèi)存泄漏需要結(jié)合代碼審查、工具監(jiān)控和良好的編程習(xí)慣,以下是一些詳細(xì)的步驟和示例代碼,需要的朋友可以參考下
    2024-11-11
  • Tomcat默認(rèn)程序發(fā)布路徑的使用與修改方法講解

    Tomcat默認(rèn)程序發(fā)布路徑的使用與修改方法講解

    今天小編就為大家分享一篇關(guān)于Tomcat默認(rèn)程序發(fā)布路徑的使用與修改方法講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Tomcat啟動(dòng)時(shí)如何設(shè)置JVM參數(shù)

    Tomcat啟動(dòng)時(shí)如何設(shè)置JVM參數(shù)

    這篇文章主要介紹了Tomcat啟動(dòng)時(shí)如何設(shè)置JVM參數(shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • HBuilderX配置tomcat外部服務(wù)器查看編輯jsp界面的方法詳解

    HBuilderX配置tomcat外部服務(wù)器查看編輯jsp界面的方法詳解

    這篇文章主要介紹了HBuilderX配置tomcat外部服務(wù)器查看編輯jsp界面的方法,本文通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Tomcat中指定JDK版本的方法實(shí)現(xiàn)

    Tomcat中指定JDK版本的方法實(shí)現(xiàn)

    在Tomcat中指定JDK版本可以通過設(shè)置環(huán)境變量或修改啟動(dòng)腳本來實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • tomcat 安全規(guī)范(tomcat安全加固和規(guī)范)

    tomcat 安全規(guī)范(tomcat安全加固和規(guī)范)

    tomcat是一個(gè)開源Web服務(wù)器,基于Tomcat的Web運(yùn)行效率高,可以在一般的硬件平臺(tái)上流暢運(yùn)行,因此,頗受Web站長(zhǎng)的青睞。不過,在默認(rèn)配置下其存在一定的安全隱患,可被惡意攻擊
    2019-11-11
  • Tomcat 是如何管理Session的方法示例

    Tomcat 是如何管理Session的方法示例

    這篇文章主要介紹了Tomcat 是如何管理Session的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 關(guān)于tomcat部署應(yīng)用無法訪問前端頁(yè)面的問題

    關(guān)于tomcat部署應(yīng)用無法訪問前端頁(yè)面的問題

    這篇文章主要介紹了關(guān)于tomcat部署應(yīng)用無法訪問前端頁(yè)面的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • 詳解Tomcat常用的過濾器

    詳解Tomcat常用的過濾器

    過濾器Filter是定義于tomcat的servlet-api.jar中的一個(gè)接口,接口路徑為javax.servlet.Filter。tomcat過濾器采用了典型的過濾器設(shè)計(jì)模式,過濾器鏈FilterChain由tomcat維持,鏈條是可以支持多個(gè)過濾器的
    2021-06-06
  • 深入了解tomcat中servlet的創(chuàng)建方式實(shí)現(xiàn)

    深入了解tomcat中servlet的創(chuàng)建方式實(shí)現(xiàn)

    這篇文章主要介紹了深入了解tomcat中servlet的創(chuàng)建方式實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10

最新評(píng)論

汉阴县| 博罗县| 巨野县| 明水县| 蒙城县| 南投县| 武安市| 于都县| 汤原县| 隆昌县| 宁陵县| 双江| 如皋市| 宁河县| 阿克陶县| 垦利县| 泰安市| 敦化市| 容城县| 泗阳县| 瑞丽市| 赞皇县| 英山县| 平顺县| 大渡口区| 杭锦旗| 资源县| 南开区| 新邵县| 龙州县| 古交市| 称多县| 虞城县| 长顺县| 连平县| 永宁县| 和顺县| 湾仔区| 依兰县| 马龙县| 荔浦县|