一般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();
}
}
以上会打包成一个jar并放在defaultlib里,并且在jar里还有一个名字是classLoader的文件,里面写着“defaultjar”,另外在defaultlib里还有一个classLoader文件未被打入jar里,写的是outofjar
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();
}
}
以上打成一个jar放在warlib里,同样在jar里还有个classLoader的配置文件,里面写着“warjar”
还有一个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();
}
}
在这个web项目里还有个初始化时就启动的servlet如下
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)