日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Tomcat源碼分析

 燮羽 2010-12-02

1.Tomcat共有五類ClassLoader: 
  commonLoader: 
      用于加載公共jar包,比如servlet規(guī)范包,servlet-api.jar,位于/common 
  catalinaLoader: 
      用于加載Tomcat的實(shí)現(xiàn)jar包,比如catalina.jar,位于/server 
  sharedLoader: 
      用于加載所有應(yīng)用的共享jar包,比如struts核心包就可以放在下面,位于/shared 
  webappClassLoader 
      用于加載web應(yīng)用下的class,一個(gè)web應(yīng)用有一個(gè)webappClassLoader 
  JasperLoader 
      用于加載web應(yīng)用下由jsp編譯后的servlet,一個(gè)web應(yīng)用有一個(gè)JasperLoader 

它們的父子代理關(guān)系如下: 

                     JREClassLoader 
                               | 
                     commonLoader 
                     /                       \  
          catalinaLoader        sharedLoader   
                                              /                      \ 
                          webappClassLoader ........webappClassLoader 
                                     |                                         | 
                           JasperLoader                   JasperLoader 

2.WebAppClassLoader加載策略 
  1.首先判斷class是否已經(jīng)加載,若已加載,則直接返回,若沒加載,則進(jìn)行第2步 
  2.使用系統(tǒng)加載器加載class,若加載成功,則返回,若失敗,則進(jìn)行第3步 
  3.如果webAppClassLoader設(shè)置了代理模式,則用父加載器進(jìn)行加載;否則直接加載 
  4.如果webAppClassLoader未設(shè)置代理模式,則自己先加載,失敗后再使用父加載器加載 

WebappClassLoader類loadClass方法

Java代碼 
  1. public Class loadClass(String name, boolean resolve)  
  2.         throws ClassNotFoundException {  
  3.   
  4.         if (log.isDebugEnabled())  
  5.             log.debug("loadClass(" + name + ", " + resolve + ")");  
  6.         Class clazz = null;  
  7.   
  8.         // Log access to stopped classloader  
  9.         if (!started) {  
  10.             try {  
  11.                 throw new IllegalStateException();  
  12.             } catch (IllegalStateException e) {  
  13.                 log.info(sm.getString("webappClassLoader.stopped", name), e);  
  14.             }  
  15.         }  
  16.   
  17.         // (0) Check our previously loaded local class cache  
  18.         clazz = findLoadedClass0(name);  
  19.         if (clazz != null) {  
  20.             if (log.isDebugEnabled())  
  21.                 log.debug("  Returning class from cache");  
  22.             if (resolve)  
  23.                 resolveClass(clazz);  
  24.             return (clazz);  
  25.         }  
  26.   
  27.         // (0.1) Check our previously loaded class cache  
  28.         clazz = findLoadedClass(name);  
  29.         if (clazz != null) {  
  30.             if (log.isDebugEnabled())  
  31.                 log.debug("  Returning class from cache");  
  32.             if (resolve)  
  33.                 resolveClass(clazz);  
  34.             return (clazz);  
  35.         }  
  36.   
  37.         // (0.2) Try loading the class with the system class loader, to prevent  
  38.         //       the webapp from overriding J2SE classes  
  39.         try {  
  40.             clazz = system.loadClass(name);  
  41.             if (clazz != null) {  
  42.                 if (resolve)  
  43.                     resolveClass(clazz);  
  44.                 return (clazz);  
  45.             }  
  46.         } catch (ClassNotFoundException e) {  
  47.             // Ignore  
  48.         }  
  49.   
  50.         // (0.5) Permission to access this class when using a SecurityManager  
  51.         if (securityManager != null) {  
  52.             int i = name.lastIndexOf('.');  
  53.             if (i >= 0) {  
  54.                 try {  
  55.                     securityManager.checkPackageAccess(name.substring(0,i));  
  56.                 } catch (SecurityException se) {  
  57.                     String error = "Security Violation, attempt to use " +  
  58.                         "Restricted Class: " + name;  
  59.                     log.info(error, se);  
  60.                     throw new ClassNotFoundException(error, se);  
  61.                 }  
  62.             }  
  63.         }  
  64.   
  65.         boolean delegateLoad = delegate || filter(name);  
  66.   
  67.         // (1) Delegate to our parent if requested  
  68.         if (delegateLoad) {  
  69.             if (log.isDebugEnabled())  
  70.                 log.debug("  Delegating to parent classloader1 " + parent);  
  71.             ClassLoader loader = parent;  
  72.             if (loader == null)  
  73.                 loader = system;  
  74.             try {  
  75.                 clazz = loader.loadClass(name);  
  76.                 if (clazz != null) {  
  77.                     if (log.isDebugEnabled())  
  78.                         log.debug("  Loading class from parent");  
  79.                     if (resolve)  
  80.                         resolveClass(clazz);  
  81.                     return (clazz);  
  82.                 }  
  83.             } catch (ClassNotFoundException e) {  
  84.                 ;  
  85.             }  
  86.         }  
  87.   
  88.         // (2) Search local repositories  
  89.         if (log.isDebugEnabled())  
  90.             log.debug("  Searching local repositories");  
  91.         try {  
  92.             clazz = findClass(name);  
  93.             if (clazz != null) {  
  94.                 if (log.isDebugEnabled())  
  95.                     log.debug("  Loading class from local repository");  
  96.                 if (resolve)  
  97.                     resolveClass(clazz);  
  98.                 return (clazz);  
  99.             }  
  100.         } catch (ClassNotFoundException e) {  
  101.             ;  
  102.         }  
  103.   
  104.         // (3) Delegate to parent unconditionally  
  105.         if (!delegateLoad) {  
  106.             if (log.isDebugEnabled())  
  107.                 log.debug("  Delegating to parent classloader at end: " + parent);  
  108.             ClassLoader loader = parent;  
  109.             if (loader == null)  
  110.                 loader = system;  
  111.             try {  
  112.                 clazz = loader.loadClass(name);  
  113.                 if (clazz != null) {  
  114.                     if (log.isDebugEnabled())  
  115.                         log.debug("  Loading class from parent");  
  116.                     if (resolve)  
  117.                         resolveClass(clazz);  
  118.                     return (clazz);  
  119.                 }  
  120.             } catch (ClassNotFoundException e) {  
  121.                 ;  
  122.             }  
  123.         }  
  124.   
  125.         throw new ClassNotFoundException(name);  
  126.     }  
 
 
Tomcat的過濾器主要由Filter、FilterChain組成,F(xiàn)ilterChain包含一個(gè)Filter數(shù)組.當(dāng)Wrapper執(zhí)行FilterChain的doFilter(request,response)方法時(shí),F(xiàn)ilterChain首先調(diào)用第一個(gè)Filter的doFilter(request,response,filterchain)方法,當(dāng)?shù)谝粋€(gè)filter做完過濾操作后,它又會(huì)調(diào)用filterchain的doFilter方法,此時(shí)filterchain的當(dāng)前filter已變?yōu)榈诙€(gè)filter,第二個(gè)filter又執(zhí)行dofilter方法,依此類推,直至所有過濾器都執(zhí)行完畢 

1.接口 
Java代碼 
  1. public interface Filter {  
  2.         .....         
  3.         //執(zhí)行過濾  
  4.         public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException;  
  5.   
  6. }  
  7.   
  8. public interface FilterChain {  
  9.     public void doFilter ( ServletRequest request, ServletResponse response ) throws IOException, ServletException;  
  10. }  


2.實(shí)現(xiàn)例子 
Java代碼 
  1. class ApplicationFilterChain implements FilterChain {  
  2.      
  3.    //pos為當(dāng)前filter的所在位置,n為filters數(shù)組的長度  
  4.    if (pos < n) {  
  5.             //pos++執(zhí)行后,把filterchain的當(dāng)前filter指向下一個(gè)  
  6.             ApplicationFilterConfig filterConfig = filters[pos++];  
  7.             Filter filter = null;  
  8.             try {  
  9.                 filter = filterConfig.getFilter();  
  10.   
  11.                 //filter執(zhí)行過濾操作  
  12.                 filter.doFilter(request, response, this);  
  13.             }  
  14.             ...  
  15.    }  
  16. }  
  17.   
  18.   
  19. class SampleFilter implements Filter {  
  20.       ........  
  21.       public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)  
  22.         throws IOException, ServletException {  
  23.            
  24.          //do something   
  25.          .....  
  26.          //request, response傳遞給下一個(gè)過濾器進(jìn)行過濾  
  27.          chain.doFilter(request, response);  
  28.     }  
  29.         
  30. }  


過濾器可以在web.xml中進(jìn)行配置
 

Tomcat源碼分析(閥門)

關(guān)鍵字: tomcat源碼分析
1.Tomcat組件及關(guān)系 

Server 
   --Service 
        --Connector 
        --Engine 
            --Host 
                 --Context 
                     --Wrapper(Servlet) 

Server代表Tomcat應(yīng)用服務(wù)器,它可以包含多個(gè)Service服務(wù);一個(gè)Service服務(wù)包含多個(gè)Connector和一個(gè)Engine;一個(gè)Engine可以包含多個(gè)虛擬主機(jī)Host;一個(gè)Host可以包含多個(gè)Web應(yīng)用Context,而每個(gè)Web下有可以包含多個(gè)Wrapper(Servlet的包裝器) 
組件及其關(guān)系可以參考Tomcat的Server.xml及Web.xml文件 


2.當(dāng)一個(gè)請(qǐng)求到達(dá)時(shí),Connector會(huì)把它包裝成Request對(duì)象,同時(shí)生成Response對(duì)象;然后Connector會(huì)調(diào)用Engine的invoke方法,它又會(huì)調(diào)用Host的invoke 方法,Host的invoke方法又會(huì)調(diào)用Context的invoke方法,最后,Context的invoke方法調(diào)用Wrapper的invoke方法,至此,責(zé)任鏈調(diào)用結(jié)束。 


接口及實(shí)現(xiàn): 
a.Pipeline , 此接口的實(shí)現(xiàn)主要用于維護(hù)閥門及先后關(guān)系,實(shí)現(xiàn)見  org.apache.catalina.core.StandardPipleline 
Java代碼 
  1. public interface Pipeline {  
  2.      
  3.    //獲取最后一個(gè)閥門   
  4.    public Valve getBasic();  
  5.      
  6.    //設(shè)置最后一個(gè)閥門  
  7.    public void setBasic(Valve valve);  
  8.   
  9.    //添加閥門  
  10.    public void addValve(Valve valve);  
  11.   
  12.    public Valve[] getValves();  
  13.   
  14.    public void removeValve(Valve valve);  
  15.   
  16.    //獲取第一個(gè)閥門  
  17.    public Valve getFirst();  
  18.   
  19.     


b.Valve , 閥門接口,主要用于做過濾工作 
Java代碼 
  1.   public interface Valve {  
  2.   
  3.     public String getInfo();  
  4.   
  5.     //獲取下一個(gè)閥門  
  6.     public Valve getNext();  
  7.   
  8.     //設(shè)置下一個(gè)閥門  
  9.     public void setNext(Valve valve);  
  10.   
  11.     public void backgroundProcess();  
  12.   
  13.     //閥門過濾  
  14.     public void invoke(Request request, Response response)  
  15.         throws IOException, ServletException;  
  16.   
  17. }  


c.下面是與責(zé)任鏈有關(guān)的實(shí)現(xiàn)代碼,以Engine的標(biāo)準(zhǔn)實(shí)現(xiàn)StandardEngine為例 
Java代碼 
  1. StandardEngine{  
  2.       
  3.     public StandardEngine() {  
  4.         super();  
  5.         //設(shè)置StandardEngineValve為Engine的最后一個(gè)閥門  
  6.         pipeline.setBasic(new StandardEngineValve());   
  7.     }  
  8.       
  9.    //添加閥門  
  10.     public synchronized void addValve(Valve valve) {  
  11.         pipeline.addValve(valve);  
  12.     }  
  13.   
  14.     //此方法被Connector調(diào)用  
  15.     public void invoke(Request request, Response response)  
  16.         throws IOException, ServletException {  
  17.         pipeline.getFirst().invoke(request, response);  
  18.     }  
  19. }  

   
d.StandardEngine簡單閥門的實(shí)現(xiàn) 
Java代碼 
  1. SimpleValve implements Valve{  
  2.    ....  
  3.    //閥門過濾方法  
  4.     public void invoke(Request request, Response response)  
  5.         throws IOException, ServletException{  
  6.        //do something  
  7.        //調(diào)用下一個(gè)閥門的invoke方法  
  8.        getNext().invoke(Request request, Response response);  
  9.        //do something  
  10.    }  
  11. }  


e.StandardEngine最后一個(gè)閥門(StandardEngineValve)的實(shí)現(xiàn) 
Java代碼 
  1. StandardEngineValve extends ValveBase{  
  2.    ...  
  3.    public void invoke(Request request, Response response)  
  4.         throws IOException, ServletException{  
  5.         Host host = request.getHost();  
  6.           
  7.         //至此,StandardEngine中的閥門都已處理完畢,下面把request、  
  8.          //response對(duì)象交給host處理  
  9.         host.getPipeline().getFirst().invoke(request, response);  
  10. }  


c,d,e代碼即為StandardEngine責(zé)任鏈調(diào)用的主要代碼,Host、Context、Wrapper的責(zé)任鏈調(diào)用相關(guān)代碼與其類似,閥門可以在Server.xml及Web.xml中配置 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多