当前位置:编程学习 > JAVA >>

jetty对于包的加载顺序的处理

 
  1.问题
     今天在本地和测试环境用jetty跑应用发现本地环境跑起来有问题,而测试环境却没有问题,出现的是war包的WEB-INF的lib目录下有两个jar包a.jar和b.jar,但是这两个jar包邮两个包名和类目一样,但是功能却不一样的类,那么jetty启动加载这个类的时候用的是a.jar里面的类还是b.jar里面的类呢,出了问题只能查了。
  2.本地环境jetty加载目录里面是b.jar排在a.jar前面,而测试环境是a.jar排在b.jar前面,而记载a.jar里面的类是正确的。我们看看jetty怎么处理:
   首先jetty加载一个APP war的过程中WebInfConfiguration.java类里面加载类的顺序,优先加载的是WEB-INF/classes,然后再加载WEB-INF/lib里面的jar包,而jar的加载顺序又是怎么样的呢?
   
[java] 
@Override  
   public void configure(WebAppContext context) throws Exception  
   {  
       //cannot configure if the context is already started  
       if (context.isStarted())  
       {  
           if (Log.isDebugEnabled()){Log.debug("Cannot configure webapp "+context+" after it is started");}  
           return;  
       }  
  
       Resource web_inf = context.getWebInf();  
  
       // Add WEB-INF classes and lib classpaths  
       if (web_inf != null && web_inf.isDirectory() && context.getClassLoader() instanceof WebAppClassLoader)  
       {  
           // Look for classes directory  
           Resource classes= web_inf.addPath("classes/");  
           if (classes.exists())  
               ((WebAppClassLoader)context.getClassLoader()).addClassPath(classes);  
  
           // Look for jars  
           Resource lib= web_inf.addPath("lib/");  
           if (lib.exists() || lib.isDirectory())  
               ((WebAppClassLoader)context.getClassLoader()).addJars(lib);  
       }  
         
       // Look for extra resource  
       List<Resource> resources = (List<Resource>)context.getAttribute(RESOURCE_URLS);  
       if (resources!=null)  
       {  
           Resource[] collection=new Resource[resources.size()+1];  
           int i=0;  
           collection[i++]=context.getBaseResource();  
           for (Resource resource : resources)  
               collection[i++]=resource;  
           context.setBaseResource(new ResourceCollection(collection));  
       }  
   }  
((WebAppClassLoader)context.getClassLoader()).addClassPath(classes);   这是加载每个class类的过程
   addURL(url);调用jdk包的URLClassPath把每个class文件放到list的后续,每次加载类的时候从这个list第一个开始查找,找到则加载
 
  这里看完我们就可以再看加载lib下面的jar包的过程了
addJars是对lib下面所有jar包用jdk的list方法获取所有jar包,然后对每个jar进行处理。
   
[java]  
/* ------------------------------------------------------------ */  
/** Add elements to the class path for the context from the jar and zip files found 
 *  in the specified resource. 
 * @param lib the resource that contains the jar and/or zip files. 
 */  
public void addJars(Resource lib)  
{  
    if (lib.exists() && lib.isDirectory())  
    {  
        String[] files=lib.list();  
        for (int f=0;files!=null && f<files.length;f++)  
        {  
            try   
            {  
                Resource fn=lib.addPath(files[f]);  
                String fnlc=fn.getName().toLowerCase();  
                if (!fn.isDirectory() && isFileSupported(fnlc))  
                {  
                    String jar=fn.toString();  
                    jar=StringUtil.replace(jar, ",", "%2C");  
                    jar=StringUtil.replace(jar, ";", "%3B");  
                    addClassPath(jar);  
                }  
            }  
            catch (Exception ex)  
            {  
                Log.warn(Log.EXCEPTION,ex);  
            }  
        }  
    }  
}  
 
 String[] files=lib.list(); 这一行就是关系jar包的加载顺序关键点,这里列出来的顺序就是jar包的加载顺序,
[java] 
/* --------------------------------------------------------- */  
/** 
 * Returns a list of resources contained in the given resource 
 */  
@Override  
public String[] list()  
{  
    String[] list =_file.list();  
    if (list==null)  
        return null;  
    for (int i=list.length;i-->0;)  
    {  
        if (new File(_file,list[i]).isDirectory() &&  
            !list[i].endsWith("/"))  
            list[i]+="/";  
    }  
    return list;  
}  
 最终 String[] list =_file.list();就是java.io.File的list方法,而这个方法的顺序是怎么样,只能看jdk的代码了。我们写个程序简单
补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,