IT序号网

java 获取当前类的路径知识解答

developer 2021年05月24日 编程语言 176 0

最近在做项目的时候,自己写了一些配置参数的读取,将配置文件放到具体的位置,然后让程序根据当前类的路径寻找配置文件的路径,但是,发现eclipse的开发坏境下是可以顺利读取到指定路径下的配置文件中的配置参数的,

但是当将项目放到Tomcat下  或者 将项目打包成可执行jar包之后,编译后的class文件却读取不到了开发环境下寻找的配置文件了。

如果在 .java 文件中直接写// public static  String Config = "config.properties";  则该路径指向的就是项目的 src 的同级目录(直接将配置文件放到项目的根目录下)

经过查找资料和进行验证,现将读取class文件相对路径下配置文件的方法汇总如下:

方法一:使用System获取路径

方法二:使用当前类的ProtectionDomain或者ClassLoader获取路径

方法三:使用Thread获取路径

方法一:

示例:

 public static  final String URLConfig = System.getProperty("user.dir").replace("bin", "webapps")+"/URLConfig.properties";//这种是将配置文件放到Tomcat的webapps的目录下

其中的 System.getProperty("user.dir")  为获取用户当前工作目录

java的System.getProperty()方法可以获取的值

获取的代码示例:

public   class  SystemProperty {   
    public   static   void  main(String args[]) {      
    System.out.println("java_vendor:"  + System.getProperty( "java.vendor" ));      
    System.out.println("java_vendor_url:"       
             + System.getProperty("java.vendor.url" ));      
    System.out.println("java_home:"  + System.getProperty( "java.home" ));      
    System.out.println("java_class_version:"       
             + System.getProperty("java.class.version" ));      
    System.out.println("java_class_path:"       
            + System.getProperty("java.class.path" ));      
    System.out.println("os_name:"  + System.getProperty( "os.name" ));      
    System.out.println("os_arch:"  + System.getProperty( "os.arch" ));      
    System.out.println("os_version:"  + System.getProperty( "os.version" ));      
    System.out.println("user_name:"  + System.getProperty( "user.name" ));      
    System.out.println("user_home:"  + System.getProperty( "user.home" ));      
    System.out.println("user_dir:"  + System.getProperty( "user.dir" ));      
    System.out.println("java_vm_specification_version:"       
            + System.getProperty("java.vm.specification.version" ));      
    System.out.println("java_vm_specification_vendor:"       
            + System.getProperty("java.vm.specification.vendor" ));      
    System.out.println("java_vm_specification_name:"       
            + System.getProperty("java.vm.specification.name" ));      
    System.out.println("java_vm_version:"       
            + System.getProperty("java.vm.version" ));      
    System.out.println("java_vm_vendor:"       
            + System.getProperty("java.vm.vendor" ));      
    System.out      
            .println("java_vm_name:"  + System.getProperty( "java.vm.name" ));      
    System.out.println("java_ext_dirs:"       
            + System.getProperty("java.ext.dirs" ));      
    System.out.println("file_separator:"       
            + System.getProperty("file.separator" ));      
    System.out.println("path_separator:"       
            + System.getProperty("path.separator" ));      
    System.out.println("line_separator:"       
            + System.getProperty("line.separator" ));      
}     

上面示例引用的博客地址:https://blog.csdn.net/capmiachael/article/details/51895823

方法二:

示例1:

public static String getMyDIR(){//获取当前类文件的绝对路径 
String jarWholePath = ConfigerPraram.class.getProtectionDomain().getCodeSource().getLocation().getFile();  
try {  
//保险起见,将路径进行decode转码 
jarWholePath = java.net.URLDecoder.decode(jarWholePath, "UTF-8");  
} catch (UnsupportedEncodingException e) { System.out.println(e.toString()); }  
//获取jar包的上级目录 
String jarPath = new File(jarWholePath).getParentFile().getAbsolutePath();  
return jarPath; 
}

示例2:

/** 
     * 获取项目所在路径 
     *  
     * @return 
     */ 
    public static String getRealPath() {
     //通过类加载器获取jar包的绝对路径 String realPath
= MyPath.class.getClassLoader().getResource("") .getFile(); java.io.File file = new java.io.File(realPath); realPath = file.getParentFile().getAbsolutePath(); //获取jar包的上级目录
try {
       //路径decode转码 realPath
= java.net.URLDecoder.decode(realPath, "utf-8"); } catch (Exception e) { e.printStackTrace(); }  
    return realPath ; 
  }

方法三:(该方法还未做验证,引用博客:https://blog.csdn.net/z69183787/article/details/22774537)

Thread.currentThread().getContextClassLoader().getResource("")来得到当前的classpath的绝对路径的URI表示法

Application可以通过new FileInputStream("xx.properties");直接在classes一级获取。关键是有时我们需要通过web修改配置文件,我们不 能将路径写死了。经过测试觉得有以下心得:

1.servlet中读写。如果运用Struts 或者Servlet可以直接在初始化参数中配置,调用时根据servlet的getRealPath("/")获取真实路径,再根据String file = this.servlet.getInitParameter("abc");获取相对的WEB-INF的相对路径。
例:
InputStream input =Thread.currentThread().getContextClassLoader().getResourceAsStream("abc.properties"); 
Properties prop = new Properties();
prop.load(input);
input.close();

prop.setProperty("abc", “test");
prop.store(new FileOutputStream(path), “–test–"); 
out.close(); 

2.直接在jsp中操作,通过jsp内置对象获取可操作的绝对地址。
例:
// jsp页面
String path = pageContext.getServletContext().getRealPath("/");
String realPath = path+"/WEB-INF/classes/abc.properties";

//java 程序
InputStream in = getClass().getClassLoader().getResourceAsStream("abc.properties"); // abc.properties放在webroot/WEB-INF/classes/目录下
prop.load(in);
in.close();

OutputStream out = new FileOutputStream(path); // path为通过页面传入的路径
prop.setProperty("abc", “abcccccc");
prop.store(out, “–test–");
out.close();

3.只通过Java程序操作资源文件
InputStream in = new FileInputStream("abc.properties"); // 相对路径,项目下的路径

OutputStream out = new FileOutputStream("abc.properties");

下面的参考解释引用于博客:https://www.cnblogs.com/gaoxing/p/4703412.html

打个简单的比方,你一个WEB程序,发布到Tomcat里面运行。
首先是执行Tomcat org.apache.catalina.startup.Bootstrap类,这时候的类加载器是ClassLoader.getSystemClassLoader()。
而我们后面的WEB程序,里面的jar、resources都是由Tomcat内部来加载的,所以你在代码中动态加载jar、资源文件的时候,首先应该是使用Thread.currentThread().getContextClassLoader()。如果你使用Test.class.getClassLoader(),可能会导致和当前线程所运行的类加载器不一致(因为Java天生的多线程)。
Test.class.getClassLoader()一般用在getResource,因为你想要获取某个资源文件的时候,这个资源文件的位置是相对固定的。

java的类加载机制(jvm规范)是委托模型,简单的说,如果一个类加载器想要加载一个类,首先它会委托给它的parent去加载,如果它的所有parent都没有成功的加载那么它才会自己亲自来,有点儿像儿子使唤老子的感觉。

 

如果你使用Test.class.getClassLoader(),可能会导致和当前线程所运行的类加载器不一致 :Class.getClassLoader() returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class was loaded by the bootstrap class loader.


发布评论

分享到:

IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

java抛出异常--后续代码是否还会执行知识解答
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。