一般web项目部署在jboss的deploy目录下,其依赖的jar一般在web-inf\lib 里面(以下称warlib),但jboss还提供了一个lib文件即和deploy平行的目录(以下称defaultlib),这里面也可以放jar,按照网上的说法当war里需要的类在自身目录里找不到时就会去defaultlib里面去找(但实际项目中发现并非总是如此,例如涉及xml解析和spring的一些东西的时候)。
那么问题来了,当需要读取配置文件时到底读的哪儿的配置文件呢?总的来说配置文件有以下几个地方
在war的classes里
在war里lib文件夹里
在war的jar里
在defaultlib文件夹下
在defaultlib的jar里
对于上面涉及到jar的情况又分为在自己的jar里和在其他jar里两种情况,于是我写了下面的代码做测试
public class DefaultJar { public void print() throws IOException{ System.out.println("-----"+this.getClass().getName()+"-----"); ClassLoader parentLoader=null; ClassLoader threadLoader=Thread.currentThread().getContextClassLoader(); System.out.println("ThreadLoader:"+threadLoader); parentLoader=threadLoader; do{ parentLoader=parentLoader.getParent(); System.out.println("\tParentLoader:"+parentLoader); }while(null!=parentLoader); ClassLoader classLoader=this.getClass().getClassLoader(); System.out.println(" ClassLoader:"+this.getClass().getClassLoader()); parentLoader=classLoader; do{ parentLoader=parentLoader.getParent(); System.out.println("\tParentLoader:"+parentLoader); }while(null!=parentLoader); System.out.println(" isEqual:"+(threadLoader==classLoader)); InputStream is=null; byte[] data=null; is=threadLoader.getResourceAsStream("classLoader"); data=new byte[is.available()]; is.read(data); System.out.println("data from ThreadLoader:"+new String(data)); is.close(); is=classLoader.getResourceAsStream("classLoader"); data=new byte[is.available()]; is.read(data); System.out.println("data from ClassLoader:"+new String(data)); is.close(); System.out.println(); } }
public class WarJar { public void print() throws IOException{ System.out.println("-----"+this.getClass().getName()+"-----"); ClassLoader parentLoader=null; ClassLoader threadLoader=Thread.currentThread().getContextClassLoader(); System.out.println("ThreadLoader:"+threadLoader); parentLoader=threadLoader; do{ parentLoader=parentLoader.getParent(); System.out.println("\tParentLoader:"+parentLoader); }while(null!=parentLoader); ClassLoader classLoader=this.getClass().getClassLoader(); System.out.println(" ClassLoader:"+this.getClass().getClassLoader()); parentLoader=classLoader; do{ parentLoader=parentLoader.getParent(); System.out.println("\tParentLoader:"+parentLoader); }while(null!=parentLoader); System.out.println(" isEqual:"+(threadLoader==classLoader)); InputStream is=null; byte[] data=null; is=threadLoader.getResourceAsStream("classLoader"); data=new byte[is.available()]; is.read(data); System.out.println("data from ThreadLoader:"+new String(data)); is.close(); is=classLoader.getResourceAsStream("classLoader"); data=new byte[is.available()]; is.read(data); System.out.println("data from ClassLoader:"+new String(data)); is.close(); System.out.println(); } }
还有一个web项目
public class WarClass { public void print() throws IOException{ System.out.println("-----"+this.getClass().getName()+"-----"); ClassLoader parentLoader=null; ClassLoader threadLoader=Thread.currentThread().getContextClassLoader(); System.out.println("ThreadLoader:"+threadLoader); parentLoader=threadLoader; do{ parentLoader=parentLoader.getParent(); System.out.println("\tParentLoader:"+parentLoader); }while(null!=parentLoader); ClassLoader classLoader=this.getClass().getClassLoader(); System.out.println(" ClassLoader:"+this.getClass().getClassLoader()); parentLoader=classLoader; do{ parentLoader=parentLoader.getParent(); System.out.println("\tParentLoader:"+parentLoader); }while(null!=parentLoader); System.out.println(" isEqual:"+(threadLoader==classLoader)); InputStream is=null; byte[] data=null; is=threadLoader.getResourceAsStream("classLoader"); data=new byte[is.available()]; is.read(data); System.out.println("data from ThreadLoader:"+new String(data)); is.close(); is=classLoader.getResourceAsStream("classLoader"); data=new byte[is.available()]; is.read(data); System.out.println("data from ClassLoader:"+new String(data)); is.close(); System.out.println(); } }
public class InitServlet extends HttpServlet { @Override public void init() throws ServletException { super.init(); try { new WarClass().print(); new WarJar().print(); new DefaultJar().print(); } catch (Exception e) { e.printStackTrace(); } } }同样在war里也有配置文件,写的是“warclass”
注意以上三个不在同一个package里
放入jboss执行后运行结果:
2016-05-05 14:06:35,884 INFO [STDOUT] (main) -----com.warclass.WarClass-----
2016-05-05 14:06:35,884 INFO [STDOUT] (main) ThreadLoader:org.jboss.web.tomcat.service.WebCtxLoader$ENCLoader@171fe0d
2016-05-05 14:06:35,884 INFO [STDOUT] (main) ParentLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,884 INFO [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,884 INFO [STDOUT] (main) ClassLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,884 INFO [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,884 INFO [STDOUT] (main) isEqual:false
2016-05-05 14:06:35,899 INFO [STDOUT] (main) data from ThreadLoader:warclass
2016-05-05 14:06:35,899 INFO [STDOUT] (main) data from ClassLoader:warclass
2016-05-05 14:06:35,899 INFO [STDOUT] (main) -----qbit.warjar.WarJar-----
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ThreadLoader:org.jboss.web.tomcat.service.WebCtxLoader$ENCLoader@171fe0d
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ParentLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ClassLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,899 INFO [STDOUT] (main) isEqual:false
2016-05-05 14:06:35,899 INFO [STDOUT] (main) data from ThreadLoader:warclass
2016-05-05 14:06:35,899 INFO [STDOUT] (main) data from ClassLoader:warclass
2016-05-05 14:06:35,899 INFO [STDOUT] (main) -----qbit.defaultjar.DefaultJar-----
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ThreadLoader:org.jboss.web.tomcat.service.WebCtxLoader$ENCLoader@171fe0d
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ParentLoader:BaseClassLoader@1cf0283{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/deploy/WarClass.war/}
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ClassLoader:BaseClassLoader@34600d{vfsfile:/D:/PowerNT5Server/jboss-5.1.0.GA/server/default/conf/jboss-service.xml}
2016-05-05 14:06:35,899 INFO [STDOUT] (main) ParentLoader:null
2016-05-05 14:06:35,899 INFO [STDOUT] (main) isEqual:false
2016-05-05 14:06:35,899 INFO [STDOUT] (main) data from ThreadLoader:warclass
2016-05-05 14:06:35,899 INFO [STDOUT] (main) data from ClassLoader:defaultjar
从结果来看:
war和defaultlib里面的class用的是两个classLoader
thread都是同一个classLoader,这个容易想到,但是意外的发现他的classLoader居然是war里的classLoader
至于两个classLoader读取配置文件,war的读取的是classes下面,而defaultlib里面读取的是jar里面另外根据其他的实验表名读取配置名字是读取名字最小的jar里(那就说明未必和读取配置文件代码所在的jar是同一个jar)