什么是资源加载器
资源加载器是java类中访问项目中其他文件的的一种工具,例如在maven项目中的com.example包下有一个ResourceTest类,在Resources目录下有一个helloword.txt文件,我想在ResourceTest类中访问到helloword.txt文件中的内容,就需要使用资源类加载器。
什么是类路径
在资源加载器加载时会有一个类路径的概念(classpath),什么是类路径呢? 类路径(Classpath)是Java用来查找类文件的环境变量
,当Java运行时环境需要加载类时,它会在类路径中搜索这个类。
常见的类路路径有哪些
类路径可以包含目录或者JAR文件。如果类路径包含了一个目录,Java运行时环境会在这个目录下搜索类文件;如果类路径包含了一个JAR文件,Java运行时环境会在这个JAR文件中搜索类文件。虽然JAR文件本身没有类路径,但是JAR文件可以包含一个名为MANIFEST.MF的清单文件,这个文件可以包含一些元数据,包括"Class-Path"属性。这个"Class-Path"属性可以指定一些相对于这个JAR文件的路径,这些路径会被添加到运行这个JAR文件的应用的类路径中。这种机制允许一个JAR文件指定它的依赖,这些依赖在运行这个JAR文件时会被自动添加到类路径中。需要注意的是,这个"Class-Path"属性只在运行JAR文件时有效,对于其他使用这个JAR文件作为库的应用,它们需要自己管理类路径,包括添加必要的依赖
在maven项目中/target/classs
就是一种类路径目录。源代码在编译后,.java
文件会被编译成.class
文件并放在target/classes
(如果是Maven项目)。默认情况下,只有.java
文件会被编译成.class
文件并放在class目录下。如果你把其他类型的文件(比如.xml
、.txt
、.properties
等)放在源代码目录(src/main/java
或src
)下,它们在编译后不会被复制到class目录下。但是,你可以配置你的构建工具(比如Maven、Gradle等)或IDE(比如IntelliJ IDEA、Eclipse等)来把这些资源文件也复制到class目录下。例如,在Maven项目中,你应该把这些资源文件放在src/main/resources
目录下,Maven在编译项目时会自动把这个目录下的所有文件复制到target/classes
目录下。
以上项目编译后的结果如下图
那maven如何如何将项目依赖的jar包放到类路径下
Maven是一个项目管理和构建工具,它会自动处理项目的依赖关系和构建过程。在项目的pom.xml文件中,开发者会声明项目的依赖关系,这些依赖关系通常是一些第三方的库,这些库的代码会被打包成JAR文件并发布到Maven的仓库中。当你构建项目时,Maven会解析pom.xml文件,找出项目的所有依赖,并下载这些依赖的JAR文件。这些JAR文件被下载到本地的Maven仓库中(默认在用户的home目录下的.m2/repository目录中)。
当Maven运行Java编译器来编译项目的代码时,它会把所有的依赖的JAR文件都添加到编译器的类路径中。这样,编译器在编译项目的代码时,就可以找到所有需要的类的定义
。
在Maven项目中,你不需要手动管理类路径,所有的类路径管理工作都由Maven自动完成,比如target/classes
。
Java原生的资源加载器
java原生的加载资源资源文件的方式有一下四种情况,他们有什么区别呢?从图中可以看出方式1与方式2为一组,我们暂且叫A组,方式3与方式4为一组,叫B组,A组与B组的区别是A组是以ResourceTest
的类对象来加载资源,而B组则是使用加载ResourceTest
类的类加载
器来加载资源。
- A组加不加
/
的区别:不加/
是在target/classes/org/example/ResourceTest.class相对位置进行搜索,如果想在类路径classpath(即target/classes
)路径上进行查找则需要加上/
- B组加不加`/没有区别,因为都是相当于类路径classpath(即target/classes)进行搜索
ini
URL resource = ResourceTest.class.getResource("helloword.txt"); //方式1
URL resource2 = ResourceTest.class.getResource("/helloword.txt"); //方式2
URL resource2 = ResourceTest.class.getClassLoader().getResource("helloword.text"); //方式3
URL resource3 = ResourceTest.class.getClassLoader().getResource("/helloword.text"); //方式4
Spring中的资源加载器
DefaultResourceLoader
Spring中提供了DefaultResourceLoader
类来进行资源的加载,该类支持字符串中包含classpath:
表示在类路径下进行加载。而原生的java是支持classpath:
的
ini
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource resource2 = loader.getResource("helloword.txt"); //方式1
Resource resource3 = loader.getResource("/helloword.txt");//方式2
Resource resource4 = loader.getResource("classpath:helloword.txt");//方式3
方式2与方式3加载路径是一致的都是在类路径下加载,方式1是在相对当前的相对路径下进行加载,如果你在 com.example.myproject
包下调用此方法,那么它会在 com/example/myproject/
目录下查找 helloword.text
文件。需要注意DefaultResourceLoader
对方式1进行处理,如果在相对目录下未找到 helloword.text
,那么会继续在类路径下继续进行加载
PathMatchingResourcePatternResolver
PathMatchingResourcePatternResolver
是Spring的资源加载器,它可以解析一种特殊的资源路径模式,比如classpath*:
、classpath:
、file:
、http:
等。其中,classpath*:
是一种特殊的前缀,它表示要加载类路径下的所有匹配的资源。例如,classpath*:com/example/**/*.xml
表示加载所有类路径下的com/example/
目录(包括其子目录)中的.xml
文件。PathMatchingResourcePatternResolver
会遍历所有的类路径,对每一个类路径应用给定的路径模式,然后把所有匹配的资源都加载出来。这使得我们可以方便地加载分布在多个类路径下的资源(比如多个jar包
中的类路径)。
需要注意的是,classpath*:
只能加载那些可以通过类路径来访问的资源。如果资源不在类路径下,那么它就无法被加载。
比如,下图是加载所有类路径下的application.properties
文件,包含各个依赖模块中的application.properties
文件
scss
new PathMatchingResourcePatternResolver(classLoader)
.getResources("classpath*:application.properties");