浏览 7000 次
锁定老帖子 主题:Java程序中的配置文件的存放和读取
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-07-26
/-----------其它包目录 | | -------edu.ec.database | |---------------ConnectionPool(数据库连接池类) | |---------------Dao(数据库访问对象类) | |---------------DaoFactory(Dao的工厂类) | |---------------database.properties(数据库配置属性文件) | |---------------RecordSet(记录集类) 在这种存储方案中,所有的与数据库相关的类和配置文件都在同一个包目录中;在开发过程中,配置文件和源文件也按采用这种方式进行组织,这样会使得程序的数据库访问维护变得相当清晰明了。 大部分开发工具在编译打包这样的源文件组织时,会自动将相关配置文件和类文件放到生成的目标文件夹中或JAR文件中。一般情况下,我们在发布自己的 Java程序时,都是以JAR或WAR形式将程序打包发布,而对应的配置文件也会按照上述的目录格式被放到了JAR或WAR文件中,这样,就实现了配置文件和程序文件打包在一起发布的目的。 现在的问题是,我们如何读取位于程序安装文件中的配置文件的信息?比如,在上面的图中, ConnectionPool是一个数据库连接池类,它需要在系统启动时自动读取存储在database.properties中的数据库连接和配置信息,以便设置相关的数据库连接。这样,我们 就需要在程序中测定目前程序安装或部署的位置,以便读取对应的属性文件。 在很多其他语言编写的程序中,我们可以利用一些系统提供的API或一些全局对象获取目前应用程序运行所在的目录。比如VB,我们可以使用Application对象测定当前程序的安装位置,在Java程序中如何完成类似的任务呢? Java程序并没有类似于VB那种全局对象,但如果我们观察位于上述目录结构中的database.properties文件,应该发现其处于应用程序的CLASSPATH中,这样,我们就可以使用Java中的类装载器中的相关的方法,读出这些配置文件的信息,该类名为ClassLoader。比如,在上例中,我们可以先得到ConnectinPool的类装载器,然后测定ConnectionPool类所在的包路径,然后利用 ConnectionPool所在的包目录读出database.properties文件的信息,对应的伪代码如下: ClassLoader loader=ConnectionPool.class.getClassLoader(); 得到ConnectionPool所在的包名; 将包名转换为对应的目录名,存入一个名为path的字符串变量中; 调用loader的getResourceAsStream(path+"database.properties"),得到输入流 下面是一个可实际运行的样例代码片段,它可自动测定传入的类所在的包目录,返回传入的属性文件所代表的输入流。它还有一个附加的功能:如果属性文件直接放到了当前类所在的根目录(比如位于JAR文件的根目录或WAR文件的WEB-INF/classes目录中)、系统的用户目录系统、系统其他的类路径中时,它也可以找到;当然,如果还是找不到,它将返回null。具体的代码如下: public class PropHelper{ /** *guessPropFile: *@param cls:和要寻找的属性文件处于相同的包中的任意的类 *@param propFile:要寻找的属性文件名 */ public static java.io.InputStream guessPropFile(Class cls,String propFile){ try{ //得到类的类装载器 ClassLoader loader=cls.getClassLoader(); //先从当前类所处路径的根目录中寻找属性文件 java.io.InputStream in=loader.getResourceAsStream(propFile); if(in!=null) return in; //没有找到,就从该类所处的包目录中查找属性文件 Package pack=cls.getPackage(); if(pack!=null){ String packName=pack.getName(); String path=""; if(packName.indexOf(".") < 0 ) path=packName+"/"; else{ int start=0,end=0; end=packName.indexOf("."); while(end!=-1){ path=path+packName.substring(start,end)+"/"; start=end+1; end=packName.indexOf(".",start); } path=path+packName.substring(start)+"/"; } in=loader.getResourceAsStream(path+propFile); if(in!=null) return in; } //如果没有找到,再从当前系统的用户目录中进行查找 java.io.File f=null; String curDir=System.getProperty("user.dir"); f=new java.io.File(curDir,propFile); if(f.exists()) return new java.io.FileInputStream(f); //如果还是没有找到,则从系统所有的类路径中查找 String classpath=System.getProperty("java.class.path"); String[] cps=classpath.split(System.getProperty("path.separator")); for(int i=0;i < cps.length; i++){ f=new java.io.File(cps[i],propFile); if(f.exists()) break; f=null; } if(f!=null) return new java.io.FileInputStream(f); return null; }catch(Exception e){throw new RuntimeException(e);} } } 使用举例:利用上述的方法,可在ConnectionPool中自动查找和ConnectionPool处于同一个包目录中的database.properties的输入流,并利用该输入流读入对应的属性值的代码如下: public class ConnectionPool{ //静态初始化器,将在ConnectionPools加载时自动执行 static{ java.util.Properties dbProp=new java.util.Properties(); java.io.InputStream in=PropHelper.guessPropFile(edu.ec.database.ConnectionPool.class,"database.properties"); if(in!=null) dbProp.load(in); //利用dbProp,为相应的数据源对象设置相关的属性,比如C3P0........ } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-07-26
现在,guessPropFile可以自动在如下位置中寻找属性文件:
其实,guessPropFile方法还可做的更加智能一些,比如在WAR文件的WEB-INF文件中寻找属性文件。如果要完成这个任务,ClassLoader是关键类,利用它的getResource方法,就可以获得相应程序中的资源的位置,我们可以在它的基础上稍加修改就可获得当前Java程序的运行位置信息,其伪代码如下: 获得Class参数的所在的类名 取得该类所在的包名 将包名转换为路径 利用getResource得到当前的类文件所在URL 利用URL解析出当前Java程序所在的路径 具体代码如下: public class PropHelper{ //其他方法的定义 //............. /** *getAppPath需要一个当前程序使用的Java类的class属性参数,它可以返回打包过的 *Java可执行文件(jar,war)所处的系统目录名或非打包Java程序所处的目录 *@param cls为Class类型 *@return 返回值为该类所在的Java程序运行的目录 */ public static String getAppPath(Class cls){ ClassLoader loader=cls.getClassLoader(); String clsName=cls.getName()+".class"; Package pack=cls.getPackage(); String path=""; if(pack!=null){ String packName=pack.getName(); clsName=clsName.substring(packName.length()+1); if(packName.indexOf(".")<0) path=packName+"/"; else{ int start=0,end=0; end=packName.indexOf("."); while(end!=-1){ path=path+packName.substring(start,end)+"/"; start=end+1; end=packName.indexOf(".",start); } path=path+packName.substring(start)+"/"; } } java.net.URL url =loader.getResource(path+clsName); String realPath=url.getPath(); int pos=realPath.indexOf("file:"); if(pos>-1) realPath=realPath.substring(pos+5); pos=realPath.indexOf(path+clsName); realPath=realPath.substring(0,pos-1); if(realPath.endsWith("!")) realPath=realPath.substring(0,realPath.lastIndexOf("/")); return realPath; }//getAppPath定义结束 }//PropHelper类定义结束 在getAppPath方法的帮助下,我们可以测定当前程序运行的路径是不是包含WEB-INF/classes路径信息,如果是,则当前程序就可能是运行在Web环境中,这样,就可以对guessPropFile中的代码进行增加,加入在WEB-INF文件夹寻找属性文件的方法。 |
|
返回顶楼 | |
发表时间:2007-08-14
这个道路是不是有些曲折?
要是程序被打包了,要改个配置还要重新打包? 配置文件多的话还是集中起来管理比较直观,而且很多可以在系统启动时先加载,一般也就一次. |
|
返回顶楼 | |
发表时间:2007-08-20
deadcode 写道 这个道路是不是有些曲折?
程序打包成Jar发布后,应该将配置文件放在jar的当前同级目录,访问调用直接访问,如
要是程序被打包了,要改个配置还要重新打包? 配置文件多的话还是集中起来管理比较直观,而且很多可以在系统启动时先加载,一般也就一次. java.util.Properties pro = new java.util.Properties(); InputStream inStream = new java.io.FileInputStream("database.properties");pro.load(inStream); 如果是打包成WAR发布,则放在适合LZ的方法 |
|
返回顶楼 | |