Class.getResourceAsStream 和 ClassLoder.getResourceAsStream 的区别
问题描述
最近学习MyBaits时用到了 InputStream Resources.getResourceAsStream(String resource)来读取MyBatis配置文件,为了方便使用,封装了一个SqlSessionFactoryUtil,代码如下
并且将这个类放在了一个单独的jar包中,其他工程会引用这个jar包,当然其他工程的MyBatis配置文件名称均为Mybatis-Configuration.xml
问题就是,测试时报错,无法找到Mybatis-Configuration.xml文件,但工程中这个文件确实存在,如图
package canger.study.Utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; /** * Created by Administrator on 2018\2\12 0012. */ public class SqlSessionFactoryUtil { private static String resource = "Mybatis-Configuration.xml"; private static SqlSessionFactory sqlSessionFactory = null; public static void setResourcePath(String path){ resource = path; } private static void initSqlSessionFactory() throws IOException { if (sqlSessionFactory!=null){ return; } synchronized (SqlSessionFactoryUtil.class){ if(sqlSessionFactory==null){ InputStream resourceAsStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); } } } public static SqlSession openSqlSession() throws IOException { initSqlSessionFactory(); return sqlSessionFactory.openSession(); } }
问题排查
InputStream Resources.getResourceAsStream(String resource)底层采用ClassLoder.getResourceAsStream(String resource)方法,ClassLoder.getResourceAsStream(String resource)调用时返回了null,百度后知道ClassLoder.getResourceAsStream(String resource)只会检查当前jar包的路径,不用检查其他jar包,所以无法找到文件,具体可参考 https://stackoverflow.com/questions/16570523/getresourceasstream-returns-null ,
同时Class..getResourceAsStream(String resource)会检查其他jar包,所以能够找到配置文件
修改后的代码如下
package canger.study.Utils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; /** * Created by Administrator on 2018\2\12 0012. */ public class SqlSessionFactoryUtil { private static String resource = "/Mybatis-Configuration.xml"; private static SqlSessionFactory sqlSessionFactory = null; public static void setResourcePath(String path){ resource = path; } private static void initSqlSessionFactory(){ if (sqlSessionFactory!=null){ return; } synchronized (SqlSessionFactoryUtil.class){ if(sqlSessionFactory==null){ InputStream resourceAsStream = SqlSessionFactoryUtil.class.getClassLoader().getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); } } } public static SqlSession openSqlSession(){ initSqlSessionFactory(); return sqlSessionFactory.openSession(); } }
总结
Class.getResourceAsStream(String name) 和 ClassLoader.getResourceAsStream(String name)区别如下
-
ClassLoader.getResourceAsStream(String name) 无论name最前面是否为'/' 都会从classpath的根路径下查找
-
Class.getResourceAsStream(String name)如果 name不以'/'开头则在当前类所在包的路径查找 ,如果name是以 '/' 开头的,那么就会从classpath的根路径下开始查找
- ClassLoader.getResourceAsStream(String name)不会查看其他jar包,Class.getResourceAsStream(String name)会查看其他jar包