Java项目读取resources资源文件路径那点事

Wesley13
• 阅读 901

  今天在Java程序中读取resources资源下的文件,由于对Java结构了解不透彻,遇到很多坑。正常在Java工程中读取某路径下的文件时,可以采用绝对路径和相对路径,绝对路径没什么好说的,相对路径,即相对于当前类的路径。在本地工程和服务器中读取文件的方式有所不同,以下图配置文件为例:

 Java项目读取resources资源文件路径那点事

(1)本地读取资源文件

  Java类中需要读取properties中的配置文件,可以采用文件(File)方式进行读取:

File file = new File("src/main/resources/properties/test.properties");
InputStream in = new FileInputStream(file);

  注意:当在IDEA中运行(不部署在服务器上),可以读取到该文件;

  原因:JavaWeb项目部署服务器中,会将项目打包成Jar包或者war包,此时就不会存在 src/main/resources 目录,JVM会在编译项目时,主动将 java文件编译成 class文件 和 resources 下的静态文件放在 target/classes目录下;

  理解:Java文件只有编译成 class文件才会被JVM执行,本地执行时会,当前项目即为Java进程的工作空间,虽然class文件在target/classes目录下,但是target/classes不是class文件运行的目录,只是存放的目录,运行目录还是在IDEA的模块下,所以运行时会找到 src/main/resources 资源文件!

(2)服务器(Tomcat)读取资源文件

  当工程部署到Tomcat中时,按照上边方式,则会抛出异常:FileNotFoundException。原因:Java工程打包部署到Tomcat中时,properties的路径变到顶层(classes下),这是由Maven工程结构决定的。由Maven构建的web工程,主代码放在src/main/java路径下,资源放在src/main/resources路径下,当构建jar包 或 war包时,JVM虚拟机会自动编译java文件为class文件存放在 target/classes目录下,resource资源下的文件会原封不动的拷贝一份到 target/classes 目录下:

  Java项目读取resources资源文件路径那点事

  方式一:此时读取资源文件时,采用流(Stream)的方式读取,并通过JDK中Properties类加载,可以方便的获取到配置文件中的信息:

InputStream in = this.getClass().getResourceAsStream("/properties/test.properties");
Properties properties = new Properties();
properties.load(in);
properties.getProperty("name");

重点理解:class.getResourceAStream() 与 class.getClassLoader().getResorceAsStream() 的区别

  Java项目读取resources资源文件路径那点事

1) InputStream inStream = PropertiesTest.class.getResourceAsStream("test.properties"); 

​2) inStream = PropertiesTest.class.getResourceAsStream("/com/test/demo/test.properties") 

3) inStream = PropertiesTest.class.getClassLoader().getResourceAsStream("com/test/demo/test.properties");

 1)第一种和第二种方式采用 Class 对象去加载,第三种方式采用 ClassLoader 对象去加载资源文件,之所以 Class 可以加载资源文件,是因为 Class 类封装的 ClassLoader 的 getResourceAsStream() 方法,从 Class 类中的源码可以看出:

public InputStream getResourceAsStream(String name) {
        name = resolveName(name);
        ClassLoader cl = getClassLoader0();
        if (cl==null) {
            // A system class.
            return ClassLoader.getSystemResourceAsStream(name);
        }
        return cl.getResourceAsStream(name);
 }

 理由:​​之所以这样做无疑还是方便客户端的调用,省的每次获取ClassLoader才能加载资源文件的麻烦!

 2).class 是获取当前类的 class 对象,getClassLoader()是获取当前的类加载器,什么是类加载器?简单点说,就是用来加载java类的,类加载器就是负责把class文件加载进内存中,并创建一个java.lang.Class类的一个实例,也就是class对象,并且每个类的类加载器都不相同,getResourceAsStream(path)是用来获取资源的,因为这是ClassLoader(类加载器)获取资源,而类加载器默认是从 classPath 下获取资源的,因为这下面有class文件。所以这段代码总的意思是通过类加载器在 classPath 目录下获取资源,并且是以流的形式。我们知道在Java中所有的类都是通过加载器加载到虚拟机中的,而且类加载器之间存在父子关系,就是子知道父,父不知道子,这样不同的子加载的类型之间是无法访问的(虽然它们都被放在方法区中),所以在这里通过当前类的加载器来加载资源也就是保证是和类类型是同一个加载器加载的。 

(3)class.getClassLoader().getResourceAsStream() 和 class.getResouceAsStream() 的区别

  a)class.getClassLoader().getResourceAsStream(String name)  默认从classpath中找文件(文件放在resources目录下),name不能带"/",否则会抛空指针。采用相对路径, "/"就相当于当前进程的根目录,即项目根目录;

inStream = PropertiesTest.class.getClassLoader().getResourceAsStream("com/test/demo/test.properties");

b)class.getResourceAsStream(String name) 是采用绝对路径,绝对路径是相对于 classpath 根目录的路径,"/" 就代表着 classpath,所以 name 属性需要前面加上 "/";

inStream = PropertiesTest.class.getResourceAsStream("/com/test/demo/test.properties")

方式二:采用Spring注解

  如果工程中使用Spring,可以通过注解的方式获取配置信息,但需要将配置文件放到Spring配置文件中扫描后,才能将配置信息放入上下文。

<context:component-scan base-package="com.xxxx.service"/>
 <context:property-placeholder location="classpath:properties/xxx.properties" ignore-unresolvable="true"/>

  然后在程序中可以使用 @Value进行获取properties文件中的属性值,如下:

@Value("${xxxt.server}")
 private static String serverUrl;

方式三:采用Spring配置

  也可以在Spring配置文件中读取属性值,赋予类成员变量

<?xml version="1.0" encoding="UTF-8"?>
  <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
      
      <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          <property name="location" value="classpath:properties/xxx.properties"/>
      </bean>
     
     <bean id="service" class="com.xxxx.service.ServiceImpl">         <property name="serverUrl" value="${xxxt.server}" />
     </bean>
 
 </beans>

  每天进步一点点,继续前进......

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java读取properties文件总结
一、java读取properties文件总结在java项目中,操作properties文件是经常要做的,因为很多的配置信息都会写在properties文件中,这里主要是总结使用getResourceAsStream方法和InputStream流去读取properties文件,使用getRe
Wesley13 Wesley13
3年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Wesley13 Wesley13
3年前
Java基础学习总结(15)——java读取properties文件总结
一、java读取properties文件总结  在java项目中,操作properties文件是经常要做的,因为很多的配置信息都会写在properties文件中,这里主要是总结使用getResourceAsStream方法和InputStream流去读取properties文件,使用get
Wesley13 Wesley13
3年前
Java 读取Properties文件时应注意的路径问题
1\.使用Class的getResourceAsStream()方法读取Properties文件(资源文件)的路径问题:      InputStreaminthis.getClass().getResourceAsStream("资源Name");    注意:    (1)这种方式要求Properties资源文件必须与当
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
JavaSE IO流
1.文件操作:在Java中如何操作磁盘中文件,java中把文件作为一个对象进行操作   File类进行表示磁盘中的文件:   路径:     绝对路径:从磁盘的根目录进行表示如:E:\\vedio\\20170713\\JavaSE\\T\_day01\\question\\常见面试题\_01.t
Wesley13 Wesley13
3年前
Java相对路径读取文件
Java相对路径读取文件不管你是新手还是老鸟,在程序中读取资源文件总会遇到一些找不到文件的问题,这与Java底层的实现有关,不能算bug,只要方法得当,问题还是可以解决的。项目的文件夹结构:repathtest ├─src │    └─com │            └─lavasoft │          
Stella981 Stella981
3年前
Linux文件路径、cd命令、mkdir、rmdir、rm命令
第二章文件、目录管理2.6相对路径和绝对路径相对路径相对路径就是相对当前目录来说的,比如我当前在/root下,那么要表示/root/213/可以直接ls213/绝对路径绝对路径是从/(也被称为根目录)开始的,比如/usr、/etc