Jetty之WebAppContext

http://blog.csdn.net/kobejayandy/article/details/20165937

前面的文章已经提到过,在servlet容器中,每一个webapplication都对应一个contextHandler,但是前面讲到的contextHandler的定义主要是实现了将http的请求进行路由,将其交给sessionHandler,然后再交给servletHandle然后转交给对应的servlet的来进行处理。。。

这里的WebAppContext是对其的一种补充,完善了webapp的启动和handler的管理。。。

先来看它的继承体系吧:



其实着了也可以看到它是对ContextHandler的一种扩展。。那么先来看看Context的定义吧,先来看看他的一些属性的定义:

[java] view plaincopy
  1. protected SecurityHandler _securityHandler;  //安全handler  
  2. protected ServletHandler _servletHandler;  //servlethandler,其用于将http请求路由给相应的servlet来处理  
  3. protected SessionHandler _sessionHandler;   //sessionhandler,其会对servlethandler进行一层包装  

这里定义了3个handler,每个是什么用基本上看名字就已经看出来了。。。

servletHandler是用于将http请求交给对应的servlet来处理。。。sessionHandler则是对servletHandler进行了一层包装(装饰器模式),用于一些session的预处理什么的。。。

接下来再来看看它的一些重要的方法定义:

[java] view plaincopy
  1. //添加servlet,这里将servlet的className与path对应起来。。。  
  2. public ServletHolder addServlet(String className,String pathSpec)  
  3. {  
  4.     return _servletHandler.addServletWithMapping(className, pathSpec);  
  5. }  
  6.   
  7. //将servlet的类型与path对象起来  
  8. public ServletHolder addServlet(Class servlet,String pathSpec)  
  9. {  
  10.     return _servletHandler.addServletWithMapping(servlet.getName(), pathSpec);  
  11. }  
  12.   
  13. //将servlet的holder与path对应起来。。  
  14. public void addServlet(ServletHolder servlet,String pathSpec)  
  15. {  
  16.     _servletHandler.addServletWithMapping(servlet, pathSpec);  
  17. }  
  18.   
  19. //添加filter  
  20. public void addFilter(FilterHolder holder,String pathSpec,int dispatches)  
  21. {  
  22.     _servletHandler.addFilterWithMapping(holder,pathSpec,dispatches);  
  23. }  
  24.   
  25. public FilterHolder addFilter(Class filterClass,String pathSpec,int dispatches)  
  26. {  
  27.     return _servletHandler.addFilterWithMapping(filterClass,pathSpec,dispatches);  
  28. }  
  29.   
  30. public FilterHolder addFilter(String filterClass,String pathSpec,int dispatches)  
  31. {  
  32.     return _servletHandler.addFilterWithMapping(filterClass,pathSpec,dispatches);  
  33. }  

这些方法就是用于在当前的context环境中添加servlet以及filter的。。。。这里也可以看出其实它是交给servletHandler来处理的。。这里也就知道servletHandler的重要作用了吧。。。

[java] view plaincopy
  1. //这里主要是初始化servletHandler  
  2. protected void startContext() throws Exception  
  3. {  
  4.     super.startContext();  
  5.       
  6.     // OK to Initialize servlet handler now  
  7.     if (_servletHandler != null && _servletHandler.isStarted())  
  8.         _servletHandler.initialize();  
  9. }  

这个方法用于启动context,它会在当前WebAppContext的doStart之中被调用,这里主要干的事情就是对servletHnandler进行初始化。。。


接下来我们来看WebAppContext的定义吧,这里就先不详细的看他的定义吧,因为以后webApp的创建和启动的时候会着重分析它。。。因为它封装了很多创建和启动的代码。。。来看看它的doStart方法:

[java] view plaincopy
  1. //这里可以理解为启动这个app,app都需要创建自己的classLoader  
  2. protected void doStart() throws Exception {  
  3.     try {  
  4.         loadConfigurations();  //加载器  
  5.           
  6.             //设置他们的context  
  7.         for (int i=0;i<_configurations.length;i++) {  
  8.             _configurations[i].setWebAppContext(this);  
  9.         }  
  10.   
  11.         // Configure classloader  
  12.         _ownClassLoader=false;  
  13.         if (getClassLoader()==null) {  
  14.             WebAppClassLoader classLoader = new WebAppClassLoader(this);  //创建classLoader  
  15.             setClassLoader(classLoader);  //设置当前的classLoader  
  16.             _ownClassLoader=true;  
  17.         }  
  18.   
  19.         if (Log.isDebugEnabled())   
  20.         {  
  21.             ClassLoader loader = getClassLoader();  
  22.             Log.debug("Thread Context class loader is: " + loader);  
  23.             loader=loader.getParent();  
  24.             while(loader!=null)  
  25.             {  
  26.                 Log.debug("Parent class loader is: " + loader);   
  27.                 loader=loader.getParent();  
  28.             }  
  29.         }  
  30.         //这个里面的操作会加压war文件  
  31.         for (int i=0;i<_configurations.length;i++) {  
  32.             _configurations[i].configureClassLoader();  
  33.         }  
  34.         getTempDirectory();  
  35.           
  36.         super.doStart();  
  37.   
  38.         if (isLogUrlOnStart())   
  39.             dumpUrl();  
  40.     }  
  41.     catch (Exception e)  
  42.     {  
  43.         //start up of the webapp context failed, make sure it is not started  
  44.         Log.warn("Failed startup of context "+this, e);  
  45.         _unavailableException=e;  
  46.         _unavailable = true;  
  47.     }  
  48. }  

这里主要是设置了当前的classLoader,然后还对一些配置对象进行了设置,然后让这些初始配置对象进行初始化。。。

他们都有如下:

[java] view plaincopy
  1. //一些默认的配置类,每一个配置类都有其要干的事情,都还挺重要的  
  2. private static String[] __dftConfigurationClasses =    
  3. {   
  4.     "org.mortbay.jetty.webapp.WebInfConfiguration",   //对webinfo的处理,主要用于载入class文件以及jar包  
  5.     "org.mortbay.jetty.webapp.WebXmlConfiguration",    //这个主要是对web.xml的处理  
  6.     "org.mortbay.jetty.webapp.JettyWebXmlConfiguration",  
  7.     "org.mortbay.jetty.webapp.TagLibConfiguration"   
  8. } ;  

另外来看一个方法:

[java] view plaincopy
  1. //相当于解压war包  
  2. protected void resolveWebApp() throws IOException  
  3. {  
  4.     Resource web_app = super.getBaseResource();  
  5.     if (web_app == null)  
  6.     {  
  7.         if (_war==null || _war.length()==0) {  
  8.             _war=getResourceBase();  
  9.         }  
  10.           
  11.         // Set dir or WAR  设置war的路径,相当于准备读war包了  
  12.         web_app= Resource.newResource(_war);    
  13.   
  14.         // Accept aliases for WAR files  
  15.         if (web_app.getAlias() != null) {  
  16.             Log.debug(web_app + " anti-aliased to " + web_app.getAlias());  
  17.             web_app= Resource.newResource(web_app.getAlias());  
  18.         }  
  19.   
  20.         if (Log.isDebugEnabled())  
  21.             Log.debug("Try webapp=" + web_app + ", exists=" + web_app.exists() + ", directory=" + web_app.isDirectory());  
  22.   
  23.         //这里将原来的war包包装为jar资源  
  24.         if (web_app.exists() && !web_app.isDirectory() && !web_app.toString().startsWith("jar:"))  
  25.         {  
  26.             // No - then lets see if it can be turned into a jar URL.  
  27.             Resource jarWebApp= Resource.newResource("jar:" + web_app + "!/");   //类似于jar:file:/F:/360云盘/jettywork/jetty/webapps/manager.war!/  
  28.             if (jarWebApp.exists() && jarWebApp.isDirectory())  
  29.             {  
  30.                 web_app= jarWebApp;  
  31.                 _war= web_app.toString();  
  32.             }  
  33.         }  
  34.   
  35.         // If we should extract or the URL is still not usable  
  36.         if (web_app.exists()  && (  
  37.            (_copyDir && web_app.getFile()!= null && web_app.getFile().isDirectory())   
  38.            ||  
  39.            (_extractWAR && web_app.getFile()!= null && !web_app.getFile().isDirectory())  
  40.            ||  
  41.            (_extractWAR && web_app.getFile() == null)  
  42.            ||  
  43.            !web_app.isDirectory()  
  44.            ))  
  45.         {  
  46.             // Then extract it if necessary.  
  47.             //获取解压的路径,解压之后将会放到这个地方  
  48.             File extractedWebAppDir= new File(getTempDirectory(), "webapp");  
  49.               
  50.             //如果app是文件夹的话,那么直接复制就好了  
  51.             if (web_app.getFile()!=null && web_app.getFile().isDirectory())  
  52.             {  
  53.                 // Copy directory  
  54.                 Log.info("Copy " + web_app.getFile() + " to " + extractedWebAppDir);  
  55.                 IO.copyDir(web_app.getFile(),extractedWebAppDir);  
  56.             }  
  57.             else  
  58.             {  
  59.                 //先要判断放app的路径是否已经存在  
  60.                 if (!extractedWebAppDir.exists())  {    
  61.                     //it hasn't been extracted before so extract it  
  62.                     extractedWebAppDir.mkdir();  //创建临时文件夹  
  63.                     Log.info("Extract " + _war + " to " + extractedWebAppDir);  
  64.                     JarResource.extract(web_app, extractedWebAppDir, false);   //解压  
  65.                 }  
  66.                 else  
  67.                 {  
  68.                     //only extract if the war file is newer  
  69.                     if (web_app.lastModified() > extractedWebAppDir.lastModified())  
  70.                     {  
  71.                         extractedWebAppDir.delete();  
  72.                         extractedWebAppDir.mkdir();  
  73.                         Log.info("Extract " + _war + " to " + extractedWebAppDir);  
  74.                         JarResource.extract(web_app, extractedWebAppDir, false);  
  75.                     }  
  76.                 }  
  77.             }  
  78.             //这里相当于将web_app的值指向已经解压后的路径  
  79.             web_app= Resource.newResource(extractedWebAppDir.getCanonicalPath());  
  80.   
  81.         }  
  82.   
  83.         // Now do we have something usable?  
  84.         if (!web_app.exists() || !web_app.isDirectory())  
  85.         {  
  86.             Log.warn("Web application not found " + _war);  
  87.             throw new java.io.FileNotFoundException(_war);  
  88.         }  
  89.   
  90.         if (Log.isDebugEnabled())  
  91.             Log.debug("webapp=" + web_app);  
  92.   
  93.         // ResourcePath  
  94.         super.setBaseResource(web_app);  //设置部署的文件夹的路径  
  95.     }  
  96. }  

这个就是对当前的web程序的war包进行处理,进行解压,放到相应的文件夹下面等等。。。


好了,其实到这里,对整个webApp的启动和创建已经设计都有了基本的了解了。。。


看jetty的源码过程还算蛮顺利的。。。莫非源码看多了。。。以后读源码也越来越顺利了。。。

相关文章
相关标签/搜索