likes
comments
collection
share

spring中的资源加载器DefaultResourceLoader以及classpath,classpath*理解

作者站长头像
站长
· 阅读数 5

什么是资源加载器

资源加载器是java类中访问项目中其他文件的的一种工具,例如在maven项目中的com.example包下有一个ResourceTest类,在Resources目录下有一个helloword.txt文件,我想在ResourceTest类中访问到helloword.txt文件中的内容,就需要使用资源类加载器。 spring中的资源加载器DefaultResourceLoader以及classpath,classpath*理解

什么是类路径

在资源加载器加载时会有一个类路径的概念(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/javasrc)下,它们在编译后不会被复制到class目录下。但是,你可以配置你的构建工具(比如Maven、Gradle等)或IDE(比如IntelliJ IDEA、Eclipse等)来把这些资源文件也复制到class目录下。例如,在Maven项目中,你应该把这些资源文件放在src/main/resources目录下,Maven在编译项目时会自动把这个目录下的所有文件复制到target/classes目录下。

以上项目编译后的结果如下图 spring中的资源加载器DefaultResourceLoader以及classpath,classpath*理解

那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)进行搜索
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:

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文件

new PathMatchingResourcePatternResolver(classLoader)
  .getResources("classpath*:application.properties");