自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

分享Tomcat源碼系列三部曲

開發(fā) 后端
本文主要和大家分享一下Tomcat的源代碼,希望對大家有所幫助。

最近在看Tomcat的源碼,下面用博客記下看源碼的一些心得。

Tomcat是從org.apache.catalina.startup.Bootstrap#main()開始啟動. 大致分為三個步驟,即init、load和start。代碼如下:

Java代碼

  1. public static void main(String args[]) {      
  2.         try {      
  3.             // Attempt to load JMX class      
  4.             new ObjectName("test:foo=bar");      
  5.         } catch (Throwable t) {      
  6.             System.out.println(JMX_ERROR_MESSAGE);      
  7.             try {      
  8.                 // Give users some time to read the message before exiting      
  9.                 Thread.sleep(5000);      
  10.             } catch (Exception ex) {      
  11.             }      
  12.             return;      
  13.         }      
  14.         if (daemon == null) {      
  15.             daemon = new Bootstrap();      
  16.             try {      
  17.                 daemon.init();   ★1      
  18.             } catch (Throwable t) {      
  19.                 t.printStackTrace();      
  20.                 return;      
  21.             }      
  22.         }      
  23.         try {      
  24.             String command = "start";      
  25.             if (args.length > 0) {      
  26.                 command = args[args.length - 1];      
  27.             }      
  28.             if (command.equals("startd")) {      
  29.                 args[0] = "start";      
  30.                 daemon.load(args);      
  31.                 daemon.start();      
  32.             } else if (command.equals("stopd")) {      
  33.                 args[0] = "stop";      
  34.                 daemon.stop();      
  35.             } else if (command.equals("start")) {      
  36.                 daemon.setAwait(true);      
  37.                 daemon.load(args);   ★2      
  38.     
  39.              // 反射調(diào)用Catalina的start方法      
  40.                 daemon.start();        ★3      
  41.             } else if (command.equals("stop")) {      
  42.                 daemon.stopServer(args);      
  43.             }      
  44.         } catch (Throwable t) {      
  45.             t.printStackTrace();      
  46.         }      
  47.     }      

 

從以上可以很清楚的看出tomcat是通過參數(shù)的不同進(jìn)行相應(yīng)的命令調(diào)用。

★1 啟動、初始化(加載類)

啟動之前要進(jìn)行相應(yīng)的init()初始化,進(jìn)行相應(yīng)的環(huán)境設(shè)置以及包的加,以下是init()方法。(org.apache.catalina.startup.Bootstrap.init())

Java代碼

 

  1. public void init()      
  2.         throws Exception      
  3.     {      
  4.         setCatalinaHome();//設(shè)置Catalina安裝目錄      
  5.         setCatalinaBase();//設(shè)置Catalina工作目錄      
  6.         initClassLoaders();//加載jar包      
  7.     
  8.        // 將classload設(shè)置進(jìn)線程,以便我們使用時進(jìn)行調(diào)用            
  9.         Thread.currentThread().      
  10.                       setContextClassLoader(catalinaLoader);      
  11.         SecurityClassLoad.securityClassLoad(catalinaLoader);      
  12.     
  13.         // 加載啟動類和調(diào)用它的process方法      
  14.         if (log.isDebugEnabled())      
  15.             log.debug("Loading startup class");      
  16.         Class startupClass =      
  17.             catalinaLoader.loadClass      
  18.             ("org.apache.catalina.startup.Catalina");      
  19.         Object startupInstance = startupClass.newInstance();      
  20.     
  21.         // 設(shè)置共享擴(kuò)張類加載器      
  22.         if (log.isDebugEnabled())      
  23.             log.debug("Setting startup class properties");      
  24.         String methodName = "setParentClassLoader";      
  25.         Class paramTypes[] = new Class[1];      
  26.         paramTypes[0] = Class.forName("java.lang.ClassLoader");      
  27.         Object paramValues[] = new Object[1];      
  28.         paramValues[0] = sharedLoader;      
  29.         Method method =      
  30.         startupInstance.getClass().getMethod(methodName,      
  31.                                                           paramTypes);      
  32.         method.invoke(startupInstance, paramValues);      
  33.         catalinaDaemon = startupInstance;      
  34.     }  

 

在加載jar的時候,需要初始化classloader,代碼如下:(org.apache.catalina.startup.Bootstrap)

Java代碼

 

  1. private void initClassLoaders() {      
  2.         try {      
  3.             commonLoader = createClassLoader("common"null);      
  4.             catalinaLoader= createClassLoader("server", commonLoader);      
  5.             sharedLoader = createClassLoader("shared", commonLoader);      
  6.         } catch (Throwable t) {      
  7.             log.error("Class loader creation threw exception", t);      
  8.             System.exit(1);      
  9.         }      
  10.     }   

 

tomcat中的加載方式是:

|-------commonLoader (common)-> System Loader

|-------sharedLoader (shared)-> commonLoader -> System Loader

|-------catalinaLoader(server) -> commonLoader -> System Loader

Common是公共類加載器,負(fù)責(zé)加載tomcat內(nèi)部和web應(yīng)用程序可以看到的類(%CATALINA_HOME%/bin/common下的jar文件),Catalina負(fù)責(zé)加載的是tomcat內(nèi)部使用的類(%CATALINA_HOME%/server下的jar文件),這些類對web應(yīng)用程序不可見。Shared負(fù)責(zé)加載的是web應(yīng)用程序之間共享的類(%CATALINA_BASE%/shared下的jar文件),這些類對于tomcat內(nèi)部是不可見的。如果%CATALINA_HOME%/conf/catalina.Properties中沒有指定Common的搜索路徑,則用當(dāng)前的類的類加載器即系統(tǒng)類加載器作為Common。

★2 裝載相應(yīng)的資源

下面主要講解tomcat的load()方法。下圖是Catalina.load方法的時序圖。

 

 

(1) 從上面的時序圖可以看出首先調(diào)用Catalina類的load()方法,具體代碼如下:

(org.apache.catalina.startup.Catalina)。

Java代碼

 

  1. public void load() {      
  2.         initDirs();      
  3.     
  4.         // Before digester - it may be needed      
  5.         initNaming();      
  6.     
  7.         // Create and execute our Digester      
  8.         Digester digester = createStartDigester();      
  9.             
  10.         try {      
  11.             inputSource.setByteStream(inputStream);      
  12.             digester.push(this);      
  13.             digester.parse(inputSource); //對server.xml進(jìn)行解析      
  14.             inputStream.close();      
  15.         }      
  16.        ......      
  17.         // Start the new server      
  18.         if (server instanceof Lifecycle) {      
  19.             try {      
  20.                 server.initialize();  //server初始化工作      
  21.             } catch (LifecycleException e) {      
  22.                 log.error("Catalina.start", e);      
  23.             }      
  24.         }      
  25.         long t2 = System.currentTimeMillis();      
  26.         log.info("Initialization processed in " + (t2 - t1) + " ms");      
  27.     
  28.     }     

 

(2) 在上面的load()方法中需要進(jìn)行server的初始化工作,下圖為Catalina.initialize的時序圖,從圖中可以看出server初始化所完成的工作。

 

 

至此,load方法結(jié)束,初期化的工作結(jié)束,下面開始進(jìn)入start方法。

★3 容器啟動

容器啟動時,會調(diào)用Catalina.start(),下圖為它的時序圖。從圖中可以看出StandardService的start方法被調(diào)用后會分別對Container和Connector進(jìn)行start方法的調(diào)用。

 

 

1. Bootstrap調(diào)用Catalina的start方法

Catalina.start()方法(org.apache.catalina.startup.Catalina.start())

Java代碼

 

  1. public void start() {      
  2.     // 啟動server      
  3.     if (server instanceof Lifecycle) {      
  4.         try {      
  5.             ((Lifecycle) server).start();      
  6.                     ......      
  7.    }     

 

2. Catalina調(diào)用StandardServer的start方法

StandardServer.start() (org.apache.catalina.core.StandardServer.start() )

Java代碼

 

  1. public void start() throws LifecycleException {            
  2.         synchronized (services) {      
  3.             for (int i = 0; i < services.length; i++) {      
  4.                 if (services[i] instanceof Lifecycle)      
  5.                     ((Lifecycle) services[i]).start();      
  6.             }       
  7. }   

 

3. StandardServer調(diào)用StandardService的start方法

Java代碼

 

  1. org.apache.catalina.core.StandardService.start() )      
  2.         public void start() throws LifecycleException {      
  3.                   if (container != null) {      
  4.             synchronized (container) {      
  5.                 if (container instanceof Lifecycle) {      
  6.               //  standardEngine的啟動      
  7.                     ((Lifecycle) container).start();      
  8.                 }      
  9.             }      
  10.        //兩個connector的啟動,8080和8009        
  11.        synchronized (connectors) {        
  12.            for (int i = 0; i < connectors.length; i++) {        
  13.                if (connectors[i] instanceof Lifecycle)        
  14.                    ((Lifecycle) connectors[i]).start();        
  15.                   }        
  16.        }        
  17. }  

 

以上StandardService.start()方法主要實(shí)現(xiàn)了兩個功能,standardEngine的啟動和connector的啟動,下面分別來介紹。

#p#

下面是standardEngine的啟動和connector的啟動

● standardEngine的啟動

(1) 首先是StandardEngine.start()被調(diào)用

Java代碼

 

 

  1. public void start() throws LifecycleException {      
  2.        // Standard container startup        
  3.       //進(jìn)行l(wèi)ogger,manager,cluster,realm,resource的啟動        
  4.        super.start();      
  5. }  

 

(2) super.start()--->org.apache.catalina.core.ContainerBase#start()

Java代碼

 

 

  1. public synchronized void start() throws LifecycleException {      
  2. //(省略)  server.xml中配置應(yīng)用組件的啟動         
  3. //StandardHost容器的啟動,        
  4.         Container children[] = findChildren();        
  5.         for (int i = 0; i < children.length; i++) {        
  6.             if (children[i] instanceof Lifecycle)        
  7.                 ((Lifecycle) children[i]).start();        
  8.         }          
  9.     
  10.     //StandardPipeline的啟動(容器與容器間的管道)        
  11.         if (pipeline instanceof Lifecycle)        
  12.             ((Lifecycle) pipeline).start();       
  13. }   

 

(3) StandardHost.start()被調(diào)用

Java代碼

 

 

  1. public synchronized void start() throws LifecycleException {      
  2. //返回到以上的containerBase#start執(zhí)行pipeline        
  3.       super.start();       
  4. }  

 

(4) StandardPipeline#start

Java代碼

 

 

  1. public synchronized void start() throws LifecycleException {      
  2.        // 將會調(diào)用HostConfig#start方法        
  3.        lifecycle.fireLifecycleEvent(START_EVENT, null);        
  4.        
  5.        // Notify our interested LifecycleListeners        
  6.        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);        
  7. }    

 

(5) HostConfig#start

Java代碼

 

 

  1. public void start() {       
  2.           //部暑webapps        
  3.           deployApps();                 
  4.   }     

 

(6) HostConfig#deployApps

Java代碼

 

 

  1. protected void deployApps() {        
  2.     File appBase = appBase();        
  3.     File configBase = configBase();        
  4.     // Deploy XML descriptors from configBase        
  5.     deployDescriptors(configBase, configBase.list());        
  6.     // Deploy WARs, and loop if additional descriptors are found        
  7.     deployWARs(appBase, appBase.list());        
  8.     // Deploy expanded folders        
  9.     deployDirectories(appBase, appBase.list());                  
  10. }    

 

(7) deployWARs

Java代碼

 

 

  1. protected void deployWARs(File appBase, String[] files) {      
  2. ……      
  3. deployWAR(contextPath, dir, file);               
  4.   }  

 

(8) deployWAR

Java代碼

 

 

  1. protected void deployWAR(String contextPath, File war, String file) {      
  2. if (context instanceof Lifecycle) {        
  3.   // (省略)      
  4.             Class clazz = Class.forName(host.getConfigClass());        
  5.             LifecycleListener listener =        
  6.                 (LifecycleListener) clazz.newInstance();        
  7.             ((Lifecycle) context).addLifecycleListener(listener);        
  8.         }        
  9.         context.setPath(contextPath);        
  10.         context.setDocBase(file);        
  11.         //以下這一步跟進(jìn)去,,StandardContext的啟動        
  12.         host.addChild(context);              
  13.   }   

 

(9) StandardContext#start

在Context的啟動過程中,主要完成了以下任務(wù)。

----------------------------------------------------------------------------------------------------------------------

a) 設(shè)置web app的具體目錄webappResources。

b) postWorkDirectory (),創(chuàng)建臨時文件目錄。Tomcat下面有一個work目錄,用來存放臨時文件。

c) 觸發(fā)START_EVENT事件監(jiān)聽,在這個事件監(jiān)聽里面會啟動ContextConfig的start()事件,ContextConfig是用來配置web.xml的。

d) 為context創(chuàng)建welcome files,通常是這三個啟動文件:index.html、index.htm、index.jsp

e) 配置filter

f) 啟動帶有的Servlet。

g) 注冊JMX。

----------------------------------------------------------------------------------------------------------------------

至此,Container啟動完畢,下面是connector的啟動。

● connector的啟動

(1) org.apache.catalina.connector.Connector.start()

Java代碼

 

 

  1. public void start() throws LifecycleException {      
  2.            // Http11Protocol的啟動      
  3.             protocolHandler.start();      
  4. }   

 

(2) Http11Protocol#start

Java代碼

 

 

  1. public void start() throws Exception {      
  2. try {        
  3.             //到了終點(diǎn)的啟動        
  4.             endpoint.start();        
  5.         } catch (Exception ex) {        
  6.             log.error(sm.getString("http11protocol.endpoint.starterror"), ex);        
  7.             throw ex;        
  8.         }    

 

(3) JIoEndPoint#start

Java代碼

 

 

  1. public void start()        
  2.         throws Exception {                 
  3.                    
  4.             for (int i = 0; i < acceptorThreadCount; i++) {        
  5.         //這里的acceptor是一個線程,里面是一個serversocket的啟動        
  6.                 Thread acceptorThread = new Thread(new Acceptor(), getName() + "-Acceptor-" + i);        
  7.                 acceptorThread.setPriority(threadPriority);        
  8.                 acceptorThread.setDaemon(daemon);        
  9.                 acceptorThread.start();        
  10.             }        
  11.         }  

 

(4) Acceptor#run

Java代碼

 

 

  1. public void run() {                    
  2. // Accept the next incoming connection from the server socket        
  3.                try {        
  4.           //這里進(jìn)行了accept(),等待客戶端消息,進(jìn)行接收        
  5.                    Socket socket = serverSocketFactory.acceptSocket(serverSocket);        
  6.                    serverSocketFactory.initSocket(socket);        
  7.                    // Hand this socket off to an appropriate processor        
  8.                    if (!processSocket(socket)) {        
  9.                        // Close socket right away        
  10.                        try {        
  11.                            socket.close();        
  12.                        } catch (IOException e) {        
  13.                            // Ignore        
  14.                        }        
  15.                    }        
  16.                }catch ( IOException x ) {        
  17.                    if ( running ) log.error(sm.getString("endpoint.accept.fail"), x);        
  18.                } catch (Throwable t) {        
  19.                    log.error(sm.getString("endpoint.accept.fail"), t);        
  20.                }        
  21. }    

 

至此Connector.start方法調(diào)用完畢。整個server啟動完畢。

#p#

本次講解一下Tomcat請求處理的流程,不當(dāng)之處還請comment。

一. Tomcat 總體結(jié)構(gòu)

Tomcat采用模塊化管理,下面是 Tomcat 的總體結(jié)構(gòu)圖:

 

 

從上圖中可以看出 Tomcat 的核心是兩個組件:Connector 和 Container。下面是一些概念的介紹。

① Server

一個server代表了整個catalina servlet容器,在Tomcat里面的Server的用處是啟動和監(jiān)聽服務(wù)端事件(諸如重啟、關(guān)閉等命令)。

② Service

Service是由一個或多個Connector與一個Engine的組合。

③ Connector

Connector將在某個指定的端口上監(jiān)聽客戶的請求,把從socket傳遞過來的數(shù)據(jù),封裝成Request,傳遞給Engine來處理,并從Engine處獲得響應(yīng)并返回給客戶。

Tomcat通常會用到兩種Connector:

a) Http Connector 在端口8080處偵聽來自客戶browser的http請求。

b) AJP Connector 在端口8009處偵聽來自其它WebServer(Apache)的servlet/jsp代理請求。

二、請求處理過程解析

1. Connector處理請求

Connector處理請求的流程大致如下:

 

 

Connector組件啟動后,會偵聽相關(guān)的端口的客戶端請求。

(1) 接受一個新的連接請求(org.apache.tomcat.util.net.TcpWorkerThread)

Java代碼

 

  1. void runIt(Object[] perThrData){      
  2.        Socket s = null;      
  3.             try {      
  4.                 s = endpoint.acceptSocket();  //獲取一個請求      
  5.             } finally {      
  6.                 if (endpoint.isRunning()) {      
  7.                     endpoint.tp.runIt(this);      
  8.   // 此處啟動另一個TcpWorkerTread去接受其他請求,此線程處理已接受的請求      
  9.                 }      
  10.             }                      
  11.       TcpConnection con = null;      
  12.       con = (TcpConnection) perThrData[0];      
  13.       con.setEndpoint(endpoint);      
  14.       con.setSocket(s);endpoint.getConnectionHandler().processConnection(con,(Object[]) perThrData[1]);          
  15. }    

 

(2) 新接收的請求被傳到Http11ConnectionHandler中處理。(org.apache.coyote.http11.Http11Protocol.Http11ConnectionHandler)

Java代碼

 

  1. void processConnection(TcpConnection connection, Object[] thData){          
  2.     Http11Processor  processor=null;      
  3.     processor=(Http11Processor)thData[Http11Protocol.THREAD_DATA_PROCESSOR];        
  4.     socket=connection.getSocket();                           
  5.     InputStream in = socket.getInputStream();        
  6.     OutputStream out = socket.getOutputStream();      
  7.     processor.setSocket(socket );      
  8.     processor.process(in, out);        
  9. //processor是org.apache.coyote.http11.Http11Processor 的 一個實(shí)例      
  10. }    

 

(3) 在 Http11Processor 中處理 http11 協(xié)議相關(guān)的信息(org.apache.coyote.http11.Http11Processor)

Java代碼

 

  1. void process(InputStream input, OutputStream output) throws IOException{      
  2.         ~~略~~      
  3.         inputBuffer.setInputStream(input);      
  4.         outputBuffer.setOutputStream(output);      
  5.         inputBuffer.parseHeaders();      
  6.       //http11 協(xié)議頭在此方法中被取出      
  7.         adapter.service(request, response);         
  8.       //adapter 是org.apache.catalina.connector.CoyoteAdapter 的 一個實(shí)例      
  9. }   

 

接下來的流程交由容器進(jìn)行處理。

2. 容器處理請求

容器交由Pipeline處理,這個Pipeline里面會放置一些vavle,請求沿著pipeline傳遞下去并且vavle對其進(jìn)行相關(guān)的處理。比如說日志等,valve還可以自定義,具體需要查看server.xml配置文件。相關(guān)類圖如下:

 

 

Tomcat的主要處理組件Engine、Host、Context和Wrapper的實(shí)現(xiàn)都會實(shí)現(xiàn)Pipeline接口,實(shí)際對請求的處理是一個Adpater,Tomcat中Adapter的實(shí)現(xiàn)是CoyoteAdapter,因此容器請求處理的入口是CoyoteAdapter的service方法。

1. CoyoteAdapter.service

--組裝好請求處理鏈

--StandardEngine. getPipeline().getFirst().invoke(request, response);

--StandardEngineValve.invoke

2. StandardEngineValve.invoke

--Host.getPipeline().getFirst().invoke(request, response);

--StandardHostValve.invoke

3. StandardHostValve.invoke

--Context. getPipeline().getFirst().invoke(request, response);

--StandardContextValve.invoke

4. StandardContextValve.invoke

--ServletRequestListener.requestInitialized

--Wrapper.getPipeline().getFirst().invoke(request, response);

--StandardWrapperValve.invoke

-- ServletRequestListener.requestDestroyed

5. StandardWrapperValve.invoke

--組裝Filter+Servlet

--處理請求

(1) Connector傳來的請求調(diào)用CoyoteAdapter.service()方法。(org.apache.catalina.connector.CoyoteAdapter)

Java代碼

 

  1. public void service(org.apache.coyote.Request req,         
  2.                     org.apache.coyote.Response res)        
  3.     throws Exception {        
  4.          ~~略~~       
  5.    if (request == null) {       
  6.         request = (Request) connector.createRequest();      
  7.         request.setCoyoteRequest(req);      
  8.         response = (Response) connector.createResponse();      
  9.      response.setCoyoteResponse(res);      
  10.      //創(chuàng)建request、response對象        
  11.          ~~略~~        
  12.     }              
  13.     try {         
  14.         if (postParseRequest(req, request, res, response)) {        
  15. connector.getContainer().getPipeline().getFirst().invoke(request, response);      
  16. //此處的Container是StandardEngine對象       
  17.            ~~略~~         
  18.     }        
  19. }    

 

(2) 默認(rèn)StandardEngine的Pipeline會有StandardEngineValve處理單元(參照StandardEngine構(gòu)造函數(shù))。(org.apache.catalina.core.StandardEngineValve)

Java代碼

 

  1. public final void invoke(Request request, Response response)        
  2.     throws IOException, ServletException {          
  3.      // Select the Host to be used for this Request        
  4.   Host host = request.getHost();        
  5.     if (host == null) {        
  6.          response.sendError        
  7.              (HttpServletResponse.SC_BAD_REQUEST,        
  8.              sm.getString("standardEngine.noHost",        
  9.                            request.getServerName()));        
  10.          return;        
  11.      }          
  12.      // Ask this Host to process this request        
  13.      host.getPipeline().getFirst().invoke(request, response);        
  14.    }    

 

(3) 同樣的,StandardHost的Pipeline會有StandardHostValve處理單元。StandardHostValve如何處理請求跟StandardEngineValve類似,接下來請求進(jìn)入到StandardContextValve.invoke

(4) 同樣的,StandardContext的Pipeline會有StandardContextValve處理單元。

Java代碼

 

  1. public final void invoke(Request request, Response response)        
  2.         throws IOException, ServletException {         
  3.         // Disallow any direct access to resources under WEB-INF or META-INF         MessageBytes requestPathMB = request.getRequestPathMB();        
  4.         if ((requestPathMB.startsWithIgnoreCase("/META-INF/"0))        
  5.             || (requestPathMB.equalsIgnoreCase("/META-INF"))        
  6.             || (requestPathMB.startsWithIgnoreCase("/WEB-INF/"0))        
  7.            || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {        
  8.             String requestURI = request.getDecodedRequestURI();        
  9.             notFound(requestURI, response);        
  10.             return;        
  11.         }          
  12.         // Wait if we are reloading        
  13.         while (context.getPaused()) {        
  14.             try {        
  15.                 Thread.sleep(1000);        
  16.             } catch (InterruptedException e) {        
  17.                 ;        
  18.             }        
  19.         }          
  20.         // Select the Wrapper to be used for this Request        
  21.         Wrapper wrapper = request.getWrapper();        
  22.         if (wrapper == null) {        
  23.             String requestURI = request.getDecodedRequestURI();        
  24.             notFound(requestURI, response);        
  25.             return;        
  26.         }          
  27. //ServletRequestListener. requestInitialized        
  28. ~~略~~        
  29.        
  30.    wrapper.getPipeline().getFirst().invoke(request, response);        
  31. //ServletRequestListener.requestDestroyed        
  32. ~~略~~        
  33.      }   

 

(5) 同樣的,StandardWrapper這個Pipeline會有StandardWrapperValve這個處理單元。在invoke()方法調(diào)用Filter的同時,servlet.service()方法也將會被調(diào)用。

(org.apache.catalina.core.StandardWrapperValve)

Java代碼

 

  1. void invoke(Request request, Response response, ValveContext valveContext)      
  2.                 throws IOException, ServletException{      
  3.          Servlet servlet = null;      
  4.           HttpServletRequest hreq = (HttpServletRequest) request.getRequest();           
  5. //org.apache.catalina.Request被封裝成javax.servlet.http.HttpServletRequest.      
  6.           HttpServletResponse hres =(HttpServletResponse) response.getResponse();       
  7. // org.apache.catalina.Response被封裝成javax.servlet.http.HttpServletResponse.      
  8.          servlet = wrapper.allocate();       // 裝載servlet      
  9.         if ((servlet != null) && (filterChain != null)) {      
  10.            filterChain.doFilter(hreq, hres);                   //調(diào)用此servlet的filterchain      
  11.        }   

 

(6) 調(diào)用servlet的filterchain 處理 request和response

(org.apache.catalina.core.ApplicationFilterChain)

Java代碼

 

  1. void doFilter(ServletRequest request, ServletResponse response) throws      
  2.                   IOException, ServletException{      
  3.              ~~略~~      
  4.            internalDoFilter(request,response);      
  5.              ~~略~~      
  6.        }    

 

(7) 調(diào)用internalDoFilter()處理請求。(org.apache.catalina.core.ApplicationFilterChain)

Java代碼

 

  1. void internalDoFilter(ServletRequest request, ServletResponse response) throws      
  2.                         IOException, ServletException{      
  3.      // 此處省略filter 處理的代碼,filter 被一個一個調(diào)用。      
  4.      // 如果http請求的是一個jsp頁面, 下面的 servlet 會是 org.apache.jasper.servlet.JspServlet 類的一個實(shí)例      
  5.      // 若是 html 頁面, 下面的 servlet 會是 org.apache.catalina.servlets.DefaultServlet 類的一個實(shí)例      
  6.      if ((request instanceof HttpServletRequest) &&      
  7.           (response instanceof HttpServletResponse)) {      
  8.       servlet.service((HttpServletRequest) request, (HttpServletResponse) response);      
  9.         servlet.service(request, response);      
  10.        } else {      
  11.         servlet.service(request, response);      
  12.       }      
  13.     }   

 

至此,servlet.service()方法被調(diào)用。

【編輯推薦】

  1. 配置Tomcat+SQL Server2000連接池流程
  2. 配置Tomcat 4使用SSL
  3. 深入剖析Subversion+Apache配置
  4. Fedora apache配置一個基于IP的虛擬主機(jī)
  5. Ubuntu Apache配置測試及安裝各種指令
責(zé)任編輯:金賀 來源: JavaEye博客
相關(guān)推薦

2009-09-14 09:04:17

CCNA考試CCNA

2011-03-25 09:56:40

Nagios 安裝

2010-07-17 01:12:31

Telnet服務(wù)

2010-09-26 14:39:40

DHCP故障分析

2011-03-09 09:30:52

Mina

2022-10-10 09:10:51

家庭網(wǎng)絡(luò)網(wǎng)絡(luò)

2013-06-28 09:35:04

Hypervisor虛擬化成本

2010-09-06 09:22:26

CSS語法

2012-09-10 16:19:00

云計算公共云

2015-05-12 10:42:53

程序員代碼

2017-02-07 14:50:39

華為

2017-04-11 09:07:20

互聯(lián)網(wǎng)

2011-08-29 16:26:50

魔獸世界LUA

2010-05-12 10:51:06

2011-08-03 10:33:05

網(wǎng)絡(luò)管理網(wǎng)絡(luò)拓?fù)涔芾?/a>

2019-03-28 14:45:33

數(shù)據(jù)安全數(shù)據(jù)泄露信息安全

2018-03-19 09:35:37

人工智能

2010-09-14 16:54:18

2018-03-18 15:51:59

人工智能潛力首席數(shù)據(jù)官

2009-10-22 13:09:19

VB.NET動態(tài)控件數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號