精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

分享Tomcat源碼系列三部曲

開發 后端
本文主要和大家分享一下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.              // 反射調用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是通過參數的不同進行相應的命令調用。

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

啟動之前要進行相應的init()初始化,進行相應的環境設置以及包的加,以下是init()方法。(org.apache.catalina.startup.Bootstrap.init())

Java代碼

 

  1. public void init()      
  2.         throws Exception      
  3.     {      
  4.         setCatalinaHome();//設置Catalina安裝目錄      
  5.         setCatalinaBase();//設置Catalina工作目錄      
  6.         initClassLoaders();//加載jar包      
  7.     
  8.        // 將classload設置進線程,以便我們使用時進行調用            
  9.         Thread.currentThread().      
  10.                       setContextClassLoader(catalinaLoader);      
  11.         SecurityClassLoad.securityClassLoad(catalinaLoader);      
  12.     
  13.         // 加載啟動類和調用它的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.         // 設置共享擴張類加載器      
  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是公共類加載器,負責加載tomcat內部和web應用程序可以看到的類(%CATALINA_HOME%/bin/common下的jar文件),Catalina負責加載的是tomcat內部使用的類(%CATALINA_HOME%/server下的jar文件),這些類對web應用程序不可見。Shared負責加載的是web應用程序之間共享的類(%CATALINA_BASE%/shared下的jar文件),這些類對于tomcat內部是不可見的。如果%CATALINA_HOME%/conf/catalina.Properties中沒有指定Common的搜索路徑,則用當前的類的類加載器即系統類加載器作為Common。

★2 裝載相應的資源

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

 

 

(1) 從上面的時序圖可以看出首先調用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進行解析      
  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()方法中需要進行server的初始化工作,下圖為Catalina.initialize的時序圖,從圖中可以看出server初始化所完成的工作。

 

 

至此,load方法結束,初期化的工作結束,下面開始進入start方法。

★3 容器啟動

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

 

 

1. Bootstrap調用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調用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調用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()方法主要實現了兩個功能,standardEngine的啟動和connector的啟動,下面分別來介紹。

#p#

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

● standardEngine的啟動

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

Java代碼

 

 

  1. public void start() throws LifecycleException {      
  2.        // Standard container startup        
  3.       //進行logger,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中配置應用組件的啟動         
  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()被調用

Java代碼

 

 

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

 

(4) StandardPipeline#start

Java代碼

 

 

  1. public synchronized void start() throws LifecycleException {      
  2.        // 將會調用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.         //以下這一步跟進去,,StandardContext的啟動        
  12.         host.addChild(context);              
  13.   }   

 

(9) StandardContext#start

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

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

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

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

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

d) 為context創建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.             //到了終點的啟動        
  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.           //這里進行了accept(),等待客戶端消息,進行接收        
  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方法調用完畢。整個server啟動完畢。

#p#

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

一. Tomcat 總體結構

Tomcat采用模塊化管理,下面是 Tomcat 的總體結構圖:

 

 

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

① Server

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

② Service

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

③ Connector

Connector將在某個指定的端口上監聽客戶的請求,把從socket傳遞過來的數據,封裝成Request,傳遞給Engine來處理,并從Engine處獲得響應并返回給客戶。

Tomcat通常會用到兩種Connector:

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

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

二、請求處理過程解析

1. Connector處理請求

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

 

 

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

(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 的 一個實例      
  10. }    

 

(3) 在 Http11Processor 中處理 http11 協議相關的信息(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 協議頭在此方法中被取出      
  7.         adapter.service(request, response);         
  8.       //adapter 是org.apache.catalina.connector.CoyoteAdapter 的 一個實例      
  9. }   

 

接下來的流程交由容器進行處理。

2. 容器處理請求

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

 

 

Tomcat的主要處理組件Engine、Host、Context和Wrapper的實現都會實現Pipeline接口,實際對請求的處理是一個Adpater,Tomcat中Adapter的實現是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傳來的請求調用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.      //創建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) 默認StandardEngine的Pipeline會有StandardEngineValve處理單元(參照StandardEngine構造函數)。(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類似,接下來請求進入到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()方法調用Filter的同時,servlet.service()方法也將會被調用。

(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);                   //調用此servlet的filterchain      
  11.        }   

 

(6) 調用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) 調用internalDoFilter()處理請求。(org.apache.catalina.core.ApplicationFilterChain)

Java代碼

 

  1. void internalDoFilter(ServletRequest request, ServletResponse response) throws      
  2.                         IOException, ServletException{      
  3.      // 此處省略filter 處理的代碼,filter 被一個一個調用。      
  4.      // 如果http請求的是一個jsp頁面, 下面的 servlet 會是 org.apache.jasper.servlet.JspServlet 類的一個實例      
  5.      // 若是 html 頁面, 下面的 servlet 會是 org.apache.catalina.servlets.DefaultServlet 類的一個實例      
  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()方法被調用。

【編輯推薦】

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

2011-03-25 09:56:40

Nagios 安裝

2009-09-14 09:04:17

CCNA考試CCNA

2010-07-17 01:12:31

Telnet服務

2010-09-26 14:39:40

DHCP故障分析

2011-03-09 09:30:52

Mina

2022-10-10 09:10:51

家庭網絡網絡

2010-09-06 09:22:26

CSS語法

2013-06-28 09:35:04

Hypervisor虛擬化成本

2012-09-10 16:19:00

云計算公共云

2015-05-12 10:42:53

程序員代碼

2017-04-11 09:07:20

互聯網

2017-02-07 14:50:39

華為

2011-08-29 16:26:50

魔獸世界LUA

2010-05-12 10:51:06

2019-03-28 14:45:33

數據安全數據泄露信息安全

2011-08-03 10:33:05

網絡管理網絡拓撲管理

2018-03-19 09:35:37

人工智能

2018-03-18 15:51:59

人工智能潛力首席數據官

2010-09-14 16:54:18

2009-10-22 13:09:19

VB.NET動態控件數
點贊
收藏

51CTO技術棧公眾號

久久精品成人| 精品资源在线| 一区二区三区在线视频免费| 国产视色精品亚洲一区二区| 亚洲欧洲在线观看| 亚洲三级色网| 日韩123区| 男人天堂视频在线| 国产99在线观看| 久久精品综合网| 国产一区视频在线| 久久综合色综合| 激情五月色综合国产精品| 91精品国产自产拍在线观看蜜| 一区二区三区四区不卡在线 | 欧美羞羞视频| 欧美激情综合网| 国产精品av一区| 波多野结衣视频在线看| 欧美精品麻豆| 中文字幕免费精品一区| 制服丝袜在线第一页| 成人在线观看免费视频| 午夜精品免费在线观看| 一区二区在线中文字幕电影视频| 亚洲av成人无码久久精品老人| 久久精品国产第一区二区三区| 欧美一区视频在线| 免费一级片在线观看| 日本一本不卡| 日韩精品视频免费专区在线播放| 天天操狠狠操夜夜操| 都市激情亚洲综合| 亚洲一区av在线| 国产高潮呻吟久久久| 黄色电影免费在线看| 高清在线观看日韩| 成人午夜小视频| 中文字幕一区二区三区四区视频| 亚洲一区二区成人| 久久久久久久久中文字幕| 国产老头老太做爰视频| 清纯唯美日韩| 伊人av综合网| 免费观看a级片| 国产剧情一区| 亚洲老头老太hd| 中出视频在线观看| 九色丨蝌蚪丨成人| 精品成人在线观看| 中文字幕天堂网| 粉嫩的18在线观看极品精品| 精品少妇一区二区三区日产乱码| 国产黑丝在线视频| 激情久久免费视频| 91精品国产欧美一区二区18| 中国黄色片一级| 国产精品国产亚洲精品| 欧美一区二区性放荡片| 午夜激情影院在线观看| 日韩精品一区二区三区中文在线| 7777精品伊人久久久大香线蕉超级流畅| 六月丁香激情网| 亚洲欧美韩国| 91黄色在线观看| 一区二区xxx| 色综合一区二区日本韩国亚洲 | 无码内射中文字幕岛国片| 白浆视频在线观看| 色综合久久精品| 网站一区二区三区| avtt久久| 亚洲精品在线观| aa一级黄色片| 91综合在线| 欧美精品video| 西西44rtwww国产精品| 久久精品人人| 91精品视频在线免费观看| 国产人妻精品一区二区三| 丰满少妇久久久久久久| 免费在线观看一区二区| 第一福利在线| 亚洲另类在线制服丝袜| 免费观看美女裸体网站| 粉嫩一区二区三区| 欧美日本一道本| 日韩女优在线视频| 国产日产精品一区二区三区四区的观看方式| 中文字幕日韩免费视频| 久久久美女视频| 久久天堂成人| 9a蜜桃久久久久久免费| 你懂的在线视频| 最新国产の精品合集bt伙计| 男人和女人啪啪网站| 国产精品原创视频| 精品乱人伦小说| av永久免费观看| 欧美~级网站不卡| 国产精品av免费在线观看| 国产熟女一区二区三区四区| www欧美成人18+| 日韩国产精品毛片| 一区二区三区短视频| 欧美一区二区在线免费播放| 爱爱免费小视频| 欧美搞黄网站| 国产精品一区二区三区在线播放| 天堂国产一区二区三区| 中文字幕一区二区三区乱码在线 | 亚洲国产一区二区三区四区| 久久久久久久久福利| 99在线精品视频在线观看| 91精品久久久久久久久久| 日韩二区三区| 洋洋成人永久网站入口| xx欧美撒尿嘘撒尿xx| 日韩高清在线免费观看| 久久99视频免费| 在线免费观看一区二区| 91丝袜美腿高跟国产极品老师 | 正在播放一区二区三区| 自拍一区在线观看| 精品国产91亚洲一区二区三区婷婷 | 国产va亚洲va在线va| 91丨精品丨国产| 在线视频精品一| 国产精品视频123| 成人精品视频一区二区三区| 欧美大片免费播放| 99精品美女视频在线观看热舞| 亚洲最新在线视频| 亚洲午夜18毛片在线看| av一区二区三区四区| 国产精品igao激情视频| 蜜桃精品在线| 亚洲欧美变态国产另类| 亚洲欧美在线视频免费| 丰满放荡岳乱妇91ww| 久久久久亚洲av无码专区喷水| 成人av色网站| 中文日韩在线视频| 亚洲国产无线乱码在线观看| 国产视频亚洲色图| 99视频精品免费| 国产最新精品| 国产精品久久国产精品99gif| 欧美女优在线| 日韩欧美精品中文字幕| 熟女少妇一区二区三区| 久久久夜精品| 偷拍视频一区二区| 精品国产黄a∨片高清在线| 曰本色欧美视频在线| 亚洲天堂视频在线播放| 中文在线免费一区三区高中清不卡| 97视频在线免费播放| 欧美**vk| 国产精品永久在线| 久cao在线| 日韩欧美电影一区| 国产精选第一页| 91伊人久久大香线蕉| 亚洲中文字幕无码不卡电影| 国产精品片aa在线观看| 国产精品亚洲片夜色在线| 男人天堂手机在线| 日韩一区二区在线免费观看| 久久久精品99| xnxx国产精品| 亚洲精品免费一区亚洲精品免费精品一区 | 二区视频在线观看| 国产欧美在线观看一区| 性欧美在线视频| 亚洲小说欧美另类社区| 久热国产精品视频一区二区三区| 国产麻豆久久| 美女av一区二区| 天天插天天干天天操| 在线精品视频一区二区三四| 夫妻性生活毛片| kk眼镜猥琐国模调教系列一区二区| 国产xxxxx在线观看| 国产韩国精品一区二区三区| 99一区二区| 欧美羞羞视频| 九九热精品视频国产| 欧美孕妇性xxxⅹ精品hd| 欧美剧情片在线观看| 国产一国产二国产三| 国产喷白浆一区二区三区| 欧美体内she精高潮| aa国产精品| 樱花www成人免费视频| 欧美91在线| 91精品国产综合久久香蕉最新版 | 五月激情四射婷婷| 国产福利不卡视频| 欧美日韩在线免费播放| 国产精品久久| 一区二区精品免费视频| 精品福利一区| 96pao国产成视频永久免费| 69久成人做爰电影| 免费av在线一区| 国产在线视频网| 精品三级在线观看| 色婷婷久久综合中文久久蜜桃av| 亚洲国产精品久久久男人的天堂 | 亚洲一区二区在线免费看| 欧美大波大乳巨大乳| 成人少妇影院yyyy| 91pony九色| 蜜臀久久99精品久久久久久9| 九一国产精品视频| 亚洲国产精品久久久天堂| 日本午夜精品电影| 另类在线视频| 成人一区二区三区四区| 欧洲成人一区| 91超碰中文字幕久久精品| 直接在线观看的三级网址| 中文字幕亚洲自拍| 东凛在线观看| 一本一本久久a久久精品综合小说| 少妇人妻精品一区二区三区| 日韩一区二区三区视频在线| 一级淫片免费看| 欧美午夜片在线观看| 无码人妻精品一区二区蜜桃色欲| 亚洲国产日韩a在线播放| 国产第一页浮力| 国产精品久久二区二区| 夫妇露脸对白88av| 国产欧美日韩三区| 女人又爽又黄免费女仆| 26uuu精品一区二区在线观看| 国产精品久久久久久在线观看| 国产精品一区三区| 欧美污在线观看| 国产一区二区三区国产| 污污的视频免费观看| 国产在线麻豆精品观看| 中文字幕第一页在线视频| 久久超碰97中文字幕| 久久久久久久久久久久91| 日韩精品免费专区| 日韩精品无码一区二区三区免费 | 国产精品扒开腿做爽爽爽男男| 中文在线а√在线8| 欧美在线播放视频| 久久r热视频| 日本视频久久久| 韩国精品主播一区二区在线观看 | 国产精品亚洲lv粉色| 欧美一区二区三区播放老司机| 国产毛片毛片毛片毛片毛片| 日韩视频123| 亚洲av永久纯肉无码精品动漫| 精品免费一区二区三区| 黄色www视频| 亚洲人成绝费网站色www| 成人影视在线播放| www.亚洲一区| 影音先锋中文在线视频| 国模精品视频一区二区三区| 91超碰在线播放| 国产99久久久欧美黑人 | 国产乱码精品一区二区三区中文 | 国产不卡在线播放| 国产性生活毛片| 久久久综合九色合综国产精品| 日本一道本视频| 亚洲精品久久嫩草网站秘色| 亚洲国产综合久久| 欧美自拍偷拍一区| av 一区二区三区| 亚洲精品乱码久久久久久按摩观| 欧美伦理影视网| 日韩网站免费观看| 丁香花在线电影| 国产精品成人一区二区三区吃奶| 日韩国产91| 精品国产乱码久久久久久88av | 无码人妻精品一区二区三区9厂 | 亚洲一区二区免费在线| 精品精品国产三级a∨在线| 日本不卡免费新一二三区| 91精品91| 日本一极黄色片| 国产美女久久久久| 91中文字幕永久在线| 亚洲欧美另类小说视频| 日本特级黄色片| 91精品欧美综合在线观看最新| 天天操天天干天天插| 日韩中文字在线| 久久影院午夜精品| 成人高h视频在线| 亚洲丁香日韩| 日韩欧美一级在线| 免费观看在线综合色| 少妇精品无码一区二区三区| 中文字幕 久热精品 视频在线| 国产又大又黑又粗免费视频| 欧美精品日韩一区| 男操女在线观看| 久久久久久久久久久亚洲| 99久久999| 性刺激综合网| 性欧美videos另类喷潮| 亚洲精品一区二区18漫画 | 欧洲猛交xxxx乱大交3| 日本韩国一区二区| 亚洲欧美另类综合| 日韩中文字幕视频在线观看| 最新中文字幕在线播放| av一本久道久久波多野结衣| 欧美成人自拍| 亚州精品一二三区| av在线不卡免费看| 精品无码一区二区三区电影桃花| 欧美人妇做爰xxxⅹ性高电影 | 美女性感视频久久久| av激情成人网| 欧美精品123| 在线亚洲观看| 精品影片一区二区入口| 亚洲精品成人少妇| 国产男男gay网站| 啊v视频在线一区二区三区| av一区在线播放| 日韩国产精品一区二区| 另类天堂av| 精品无码人妻一区| 欧美视频在线视频| 无码精品在线观看| 亚州成人av在线| 加勒比视频一区| 国产妇女馒头高清泬20p多| 成人丝袜视频网| 国产91av视频| 日韩高清a**址| www.成人爱| 奇米精品在线| 日本不卡视频在线| 又色又爽的视频| 欧美日韩国产中文| 免费观看在线午夜影视| 成人羞羞国产免费| 五月天久久网站| 4438x全国最大成人| 亚洲国产日日夜夜| 天天干天天操av| 日本sm极度另类视频| 国产伦精品一区二区三区千人斩| 久久久久久香蕉| 国产精品三级av在线播放| 中文字幕在线观看第二页| 精品国产视频在线 | 国产中文一区二区| 国产精品视区| 亚洲一级黄色录像| 欧美精品日韩一区| 国产精品69xx| 久久精品日产第一区二区三区| 久久九九电影| 欧美肥妇bbwbbw| 亚洲成年人在线| 一区二区电影免费观看| 亚洲激情一区二区| 国产盗摄女厕一区二区三区| 日本在线观看视频网站| 亚洲天堂免费观看| 日韩电影精品| 国产无限制自拍| 国产丝袜欧美中文另类| 99在线观看免费| 热99久久精品| 欧美一区二区三区久久精品| 一级欧美一级日韩片| 欧美色涩在线第一页| 青青草原av在线| 日本一区二区三不卡| 国产精品一区在线| 免费黄色网址在线| 久久久国产视频91| 欧美电影免费网站| www.超碰97.com| 精品国产999| 国产在线观看av| 久久艳妇乳肉豪妇荡乳av| 韩日av一区二区| 欧美另类一区二区| 久久精品99国产精品酒店日本| 美女一区二区在线观看| 视频在线观看免费高清| 婷婷综合另类小说色区| 黄色网在线播放|