此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring Framework 6.1.13! |
此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring Framework 6.1.13! |
本章介绍了 Spring 如何处理资源以及如何使用 Spring。它包括以下主题:
介绍
Java 的标准类和各种 URL 前缀的标准处理程序,
不幸的是,对于所有对低级资源的访问来说,这还不够。为
示例中,没有可用于访问
需要从 Classpath 获取的资源或相对于 .虽然可以为专用前缀注册新的处理程序(类似于前缀的现有处理程序,例如 ),这通常是
相当复杂,并且界面仍然缺乏一些理想的功能,
例如,用于检查所指向的资源是否存在的方法。java.net.URL
URL
ServletContext
URL
http:
URL
界面Resource
Spring 的接口位于包中
旨在成为对低级资源的抽象访问的更强大的接口。这
下面的清单提供了该界面的概述。有关更多详细信息,请参阅 Resource
javadoc。Resource
org.springframework.core.io.
Resource
public interface Resource extends InputStreamSource {
boolean exists();
boolean isReadable();
boolean isOpen();
boolean isFile();
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
ReadableByteChannel readableChannel() throws IOException;
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
如接口的定义所示,它扩展了接口。下面的清单显示了接口的定义:Resource
InputStreamSource
InputStreamSource
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
界面中一些最重要的方法是:Resource
-
getInputStream()
:查找并打开资源,返回 for 从资源中读取。预计每次调用都会返回一个新的 .调用方负责关闭流。InputStream
InputStream
-
exists()
:返回一个 物理形式。boolean
-
isOpen()
:返回一个 tag,指示此资源是否表示句柄 与开放的流。如果 ,则不能多次读取 ,并且 必须只读取一次,然后关闭以避免资源泄漏。的返回 所有常用的资源实现,除了 .boolean
true
InputStream
false
InputStreamResource
-
getDescription()
:返回此资源的说明,用于错误 output 来执行。这通常是完全限定的文件名或 资源的实际 URL。
其他方法允许您获取表示
资源(如果底层实现兼容并支持
功能)。URL
File
该接口的某些实现还实现了扩展的 WritableResource
接口
对于支持写入它的资源。Resource
Spring 本身广泛使用抽象,作为
需要资源时有许多方法签名。某些 Spring API 中的其他方法
(例如各种实现的构造函数)采用一个 THAT,它以朴素或简单的形式用于创建适当的
该上下文实现,或者通过路径上的特殊前缀,让
caller 指定必须创建和使用特定实现。Resource
ApplicationContext
String
Resource
String
Resource
虽然该接口与 Spring 和 Spring 一起使用很多,但它实际上是
非常方便,可以在您自己的代码中单独用作通用工具类,以便访问
添加到资源中,即使您的代码不知道或不关心 Spring 的任何其他部分。
虽然这会将您的代码耦合到 Spring,但它实际上只将其耦合到这一小群
Utility 类,它可以作为
被认为等同于您用于此目的的任何其他库。Resource
URL
抽象不会取代功能。它将其包装在
可能。例如,a 包装一个 URL 并使用包装的 URL 来执行其
工作。Resource UrlResource URL |
抽象不会取代功能。它将其包装在
可能。例如,a 包装一个 URL 并使用包装的 URL 来执行其
工作。Resource UrlResource URL |
内置实现Resource
Spring 包括几个内置的实现:Resource
有关 Spring 中可用的实现的完整列表,请查阅
Resource
javadoc 的 “All Known Implementing Classes” 部分。Resource
UrlResource
UrlResource
包装 a 并可用于访问任何
通常可通过 URL(例如文件、HTTPS 目标、FTP 目标)以及 URL 访问
别人。所有 URL 都有一个标准化的表示形式,以便适当的
标准化前缀用于指示一种 URL 类型与另一种 URL 类型。这包括用于访问文件系统路径,用于通过
HTTPS 协议,用于通过 FTP 访问资源等。java.net.URL
String
file:
https:
ftp:
A 由 Java 代码显式使用构造函数创建
但通常在调用采用用于表示路径的参数的 API 方法时隐式创建。对于后一种情况,JavaBeans 最终决定创建哪种类型。如果路径字符串包含
众所周知的(对于属性编辑器来说,即)前缀(例如 ),它会创建一个
适当的 专门用于该前缀。但是,如果它无法识别
前缀,则假定该字符串是标准 URL 字符串,并创建一个 .UrlResource
UrlResource
String
PropertyEditor
Resource
classpath:
Resource
UrlResource
ClassPathResource
此类表示应从 Classpath 获取的资源。它使用 线程上下文类加载器、给定类加载器或 loading resources.
此实现支持将 Expression 解析为 Bean 的 class path
资源驻留在文件系统中,但不适用于驻留在
jar 中,并且尚未扩展(通过 servlet 引擎或任何环境)
添加到文件系统中。为了解决这个问题,各种 implementations 始终支持
分辨率设置为 .Resource
java.io.File
Resource
java.net.URL
A 是由 Java 代码通过显式使用构造函数创建的,但通常是在调用采用用于表示路径的参数的 API 方法时隐式创建的。对于后一种情况,JavaBeans 识别字符串路径上的特殊前缀 , 和
在这种情况下创建一个。ClassPathResource
ClassPathResource
String
PropertyEditor
classpath:
ClassPathResource
FileSystemResource
这是 handles 的实现。它还支持句柄,应用 Spring 的标准基于 String 的 path
转换,但通过 API 执行所有操作。对于纯基础支持,请改用 a。 支持分辨率为 A 和 .Resource
java.io.File
java.nio.file.Path
java.nio.file.Files
java.nio.path.Path
PathResource
FileSystemResource
File
URL
PathResource
这是一个用于 handles 的实现,执行所有
操作和转换。它支持将分辨率解析为 和
作为 A 进行,并且还实现了扩展接口。 实际上是 with 的纯基替代品
不同的行为。Resource
java.nio.file.Path
Path
File
URL
WritableResource
PathResource
java.nio.path.Path
FileSystemResource
createRelative
ServletContextResource
这是解释
相关 Web 应用程序根目录中的相对路径。Resource
ServletContext
它始终支持流访问和 URL 访问,但仅允许访问
当 Web 应用程序存档扩展并且资源物理位于
文件系统。无论它是否被扩展、在文件系统上或被访问
直接从 JAR 或其他位置(如数据库)实际上是
依赖于 Servlet 容器。java.io.File
界面ResourceLoader
该接口旨在由可以返回
(即 load)实例。下面的清单显示了接口定义:ResourceLoader
Resource
ResourceLoader
public interface ResourceLoader {
Resource getResource(String location);
ClassLoader getClassLoader();
}
所有应用程序上下文都实现该接口。因此,所有
应用程序上下文可用于获取实例。ResourceLoader
Resource
当您调用特定的应用程序上下文时,位置路径
specified 没有特定的前缀,则返回一个
适合该特定应用程序上下文。例如,假设以下内容
针对实例运行的代码片段:getResource()
Resource
ClassPathXmlApplicationContext
-
Java
-
Kotlin
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
val template = ctx.getResource("some/resource/path/myTemplate.txt")
对于 ,该代码返回一个 .如果
相同的方法对实例运行,它将
返回一个 .对于 a ,它将返回一个 .它同样会为每个上下文返回适当的对象。ClassPathXmlApplicationContext
ClassPathResource
FileSystemXmlApplicationContext
FileSystemResource
WebApplicationContext
ServletContextResource
因此,您可以以适合特定应用程序的方式加载资源 上下文。
另一方面,您也可以强制使用
application context 类型,通过指定特殊前缀,如下所示
示例显示:ClassPathResource
classpath:
-
Java
-
Kotlin
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
val template = ctx.getResource("classpath:some/resource/path/myTemplate.txt")
同样,您可以通过指定任何标准前缀来强制使用 a。以下示例使用 和 前缀:UrlResource
java.net.URL
file
https
-
Java
-
Kotlin
Resource template = ctx.getResource("file:///some/resource/path/myTemplate.txt");
val template = ctx.getResource("file:///some/resource/path/myTemplate.txt")
-
Java
-
Kotlin
Resource template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt");
val template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt")
下表总结了将对象转换为对象的策略:String
Resource
前缀 | 例 | 解释 |
---|---|---|
类路径: |
|
从 Classpath 加载。 |
文件: |
|
作为 从文件系统加载。另请参阅 |
https 的 URL 中: |
|
加载为 . |
(无) |
|
取决于底层 . |
前缀 | 例 | 解释 |
---|---|---|
类路径: |
|
从 Classpath 加载。 |
文件: |
|
作为 从文件系统加载。另请参阅 |
https 的 URL 中: |
|
加载为 . |
(无) |
|
取决于底层 . |
界面ResourcePatternResolver
interface 是 interface 的扩展
,它定义了解析位置模式(例如,Ant 样式路径
pattern) 转换为对象。ResourcePatternResolver
ResourceLoader
Resource
public interface ResourcePatternResolver extends ResourceLoader {
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
Resource[] getResources(String locationPattern) throws IOException;
}
从上面可以看出,这个接口还定义了一个特殊的资源前缀
对于类路径中的所有匹配资源。请注意,资源位置为
在本例中,应为不带占位符的路径 — 例如,.JAR 文件或类路径中的不同目录可以
包含多个具有相同路径和名称的文件。有关更多详细信息,请参阅 Application Context Constructor Resource Paths 及其子部分中的通配符
On 通配符支持,并带有 Resource 前缀。classpath*:
classpath*:/config/beans.xml
classpath*:
可以检查传入的 (例如,通过 ResourceLoaderAware
语义提供的)
它也实现了这个扩展接口。ResourceLoader
PathMatchingResourcePatternResolver
是可用的独立实现
在 an 和 之外也被用于
填充 bean 属性。 能够
将指定的资源位置路径解析为一个或多个匹配对象。
源路径可以是与 target 进行一对一映射的简单路径,也可以包含特殊前缀和/或 internal
Ant 样式的正则表达式(使用 Spring 的实用程序进行匹配)。后者两者都是有效的
通配符。ApplicationContext
ResourceArrayPropertyEditor
Resource[]
PathMatchingResourcePatternResolver
Resource
Resource
classpath*:
org.springframework.util.AntPathMatcher
任何标准中的默认值实际上都是一个实例
其中实现接口。实例本身也是如此,它也
实现接口并委托给默认的 . |
任何标准中的默认值实际上都是一个实例
其中实现接口。实例本身也是如此,它也
实现接口并委托给默认的 . |
界面ResourceLoaderAware
该接口是一个特殊的回调接口,用于标识
组件。以下清单
显示了接口的定义:ResourceLoaderAware
ResourceLoader
ResourceLoaderAware
public interface ResourceLoaderAware {
void setResourceLoader(ResourceLoader resourceLoader);
}
当类实现并部署到应用程序上下文中时
(作为 Spring 管理的 bean)中,它被应用程序识别为
上下文。然后,应用程序上下文调用 ,
将自身作为参数提供(请记住,Spring 中的所有应用程序上下文都实现了
界面)。ResourceLoaderAware
ResourceLoaderAware
setResourceLoader(ResourceLoader)
ResourceLoader
由于 an 是 ,因此 bean 还可以实现接口并使用提供的应用程序上下文直接
load 资源。但是,一般来说,如果这就是您所需要的,最好使用专用界面。该代码将仅与资源加载耦合
接口(可以被认为是一个 Util 接口),而不是整个 Spring 接口。ApplicationContext
ResourceLoader
ApplicationContextAware
ResourceLoader
ApplicationContext
在应用程序组件中,您还可以依赖 as 的自动装配
实现接口的替代方法。传统模式和自动装配模式(如 自动装配协作者中所述)
能够为 constructor 参数或
setter 方法参数。为了获得更大的灵活性(包括
autowire fields 和多个参数方法),请考虑使用基于注释的
自动装配功能。在这种情况下,它被自动连接到一个字段
constructor 参数或期望类型为 long 的方法参数
因为有问题的 field、constructor 或 method 带有 Annotation。
有关更多信息,请参阅使用 @Autowired
。ResourceLoader
ResourceLoaderAware
constructor
byType
ResourceLoader
ResourceLoader
ResourceLoader
@Autowired
为包含通配符的资源路径加载一个或多个对象
或使用特殊的资源前缀,请考虑将 ResourcePatternResolver 的实例自动连接到您的
application 组件而不是 .Resource classpath*: ResourceLoader |
为包含通配符的资源路径加载一个或多个对象
或使用特殊的资源前缀,请考虑将 ResourcePatternResolver 的实例自动连接到您的
application 组件而不是 .Resource classpath*: ResourceLoader |
作为依赖项的资源
如果 Bean 本身将通过某种排序来确定和提供资源路径
动态进程中,bean 使用 or 接口来加载资源可能是有意义的。例如,考虑 loading
中,所需的特定资源取决于
用户的角色。如果资源是静态的,那么完全消除接口(或接口)的使用是有意义的,让
bean 公开了它需要的属性,并期望将它们注入其中。ResourceLoader
ResourcePatternResolver
ResourceLoader
ResourcePatternResolver
Resource
然后注入这些属性变得微不足道的是,所有应用程序上下文
注册并使用一个特殊的 JavaBeans ,它可以转换路径
到对象。例如,以下类具有 .PropertyEditor
String
Resource
MyBean
template
Resource
-
Java
-
Kotlin
public class MyBean {
private Resource template;
public setTemplate(Resource template) {
this.template = template;
}
// ...
}
class MyBean(var template: Resource)
在 XML 配置文件中,可以使用简单的
string 的 String,如下例所示:template
<bean id="myBean" class="example.MyBean">
<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>
请注意,资源路径没有前缀。因此,由于应用程序上下文
本身将用作 ,资源通过 、 、 或 、 加载,具体取决于
应用程序上下文的确切类型。ResourceLoader
ClassPathResource
FileSystemResource
ServletContextResource
如果需要强制使用特定类型,可以使用前缀。这
以下两个示例展示了如何强制 A 和 A (
后者用于访问文件系统中的文件):Resource
ClassPathResource
UrlResource
<property name="template" value="classpath:some/resource/path/myTemplate.txt">
<property name="template" value="file:///some/resource/path/myTemplate.txt"/>
如果重构该类以用于注解驱动的配置,则
path to 可以存储在名为 — 例如
在 Spring 可用的属性文件中(参见Environment Abstraction)。然后,可以使用属性占位符通过注释引用模板路径(请参阅使用 @Value
)。Spring会
将模板路径的值检索为字符串,并且会有一个特殊的
将字符串转换为要注入构造函数的对象。
以下示例演示了如何实现此目的。MyBean
myTemplate.txt
template.path
Environment
@Value
PropertyEditor
Resource
MyBean
-
Java
-
Kotlin
@Component
public class MyBean {
private final Resource template;
public MyBean(@Value("${template.path}") Resource template) {
this.template = template;
}
// ...
}
@Component
class MyBean(@Value("\${template.path}") private val template: Resource)
如果我们想支持在多个
位置 — 例如,在 Classpath 的多个 jar 中 — 我们可以
使用特殊前缀和通配符将键定义为 。如果我们按如下方式重新定义类,
Spring 会将模板路径模式转换为对象数组,这些对象
可以注入到构造函数中。classpath*:
templates.path
classpath*:/config/templates/*.txt
MyBean
Resource
MyBean
-
Java
-
Kotlin
@Component
public class MyBean {
private final Resource[] templates;
public MyBean(@Value("${templates.path}") Resource[] templates) {
this.templates = templates;
}
// ...
}
@Component
class MyBean(@Value("\${templates.path}") private val templates: Resource[])
应用程序上下文和资源路径
本节介绍如何使用资源(包括快捷方式)创建应用程序上下文 ,以及如何使用 XML、如何使用通配符和其他详细信息。
构造应用程序上下文
应用程序上下文构造函数(针对特定的应用程序上下文类型) 将字符串或字符串数组作为资源的位置路径,例如 构成上下文定义的 XML 文件。
当此类位置路径没有前缀时,从
该路径 和 用于加载 bean 定义的路径取决于 并且适合于
特定的应用程序上下文。例如,请考虑以下示例,该示例创建一个 :Resource
ClassPathXmlApplicationContext
-
Java
-
Kotlin
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
val ctx = ClassPathXmlApplicationContext("conf/appContext.xml")
Bean 定义是从 Classpath 加载的,因为
使用。但是,请考虑以下示例,该示例创建一个 :ClassPathResource
FileSystemXmlApplicationContext
-
Java
-
Kotlin
ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/appContext.xml");
val ctx = FileSystemXmlApplicationContext("conf/appContext.xml")
现在,bean 定义是从文件系统位置加载的(在本例中,相对于 当前工作目录)。
请注意,在
location path 覆盖 created 的默认类型以加载 bean
定义。请考虑以下示例:classpath
Resource
-
Java
-
Kotlin
ApplicationContext ctx =
new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
val ctx = FileSystemXmlApplicationContext("classpath:conf/appContext.xml")
Using 从 Classpath 中加载 bean 定义。
但是,它仍然是 .如果随后将其用作 a ,则任何未带前缀的路径仍被视为文件系统路径。FileSystemXmlApplicationContext
FileSystemXmlApplicationContext
ResourceLoader
构造实例 — 快捷方式ClassPathXmlApplicationContext
这公开了许多构造函数以启用
方便的实例化。基本思想是,您可以只提供一个字符串数组
,仅包含 XML 文件本身的文件名(没有前导路径
信息),并提供 .then 派生
来自提供的类的路径信息。ClassPathXmlApplicationContext
Class
ClassPathXmlApplicationContext
请考虑以下目录布局:
com/ example/ services.xml repositories.xml MessengerService.class
以下示例显示了由
在名为 和 (位于
classpath) 可以实例化:ClassPathXmlApplicationContext
services.xml
repositories.xml
-
Java
-
Kotlin
ApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {"services.xml", "repositories.xml"}, MessengerService.class);
val ctx = ClassPathXmlApplicationContext(arrayOf("services.xml", "repositories.xml"), MessengerService::class.java)
有关各种构造函数的详细信息,请参见ClassPathXmlApplicationContext
javadoc。
应用程序上下文构造函数资源路径中的通配符
应用程序上下文构造函数值中的资源路径可以是简单路径(如
前面所示),每个 Target(目标)都有一个一对一的映射,或者
或者,可以包含特殊前缀或内部 Ant 样式模式
(通过使用 Spring 的 Util 进行匹配)。后者两者都是有效的
通配符。Resource
classpath*:
PathMatcher
此机制的一个用途是当您需要执行组件样式的应用程序组装时。都
组件可以将上下文定义片段发布到已知的位置路径,并且
当使用前缀为 的相同路径创建最终应用程序上下文时,会自动选取所有组件片段。classpath*:
请注意,此通配符特定于应用程序上下文中资源路径的使用
构造函数(或者直接使用实用程序类层次结构时),并且是
在构建时解决。它与类型本身无关。
您不能使用前缀来构造实际的 ,因为
一个资源一次只指向一个资源。PathMatcher
Resource
classpath*:
Resource
Ant-style 模式
路径位置可以包含 Ant 样式模式,如下例所示:
/WEB-INF/*-context.xml com/mycompany/**/applicationContext.xml file:C:/some/path/*-context.xml classpath:com/mycompany/**/applicationContext.xml
当路径位置包含 Ant 样式模式时,解析程序遵循更复杂的
过程以尝试解析通配符。它为 path 生成一个
last 非通配符段并从中获取 URL。如果此 URL 不是 URL 或
特定于容器的变体(例如在 WebLogic、WebSphere 中等),
a 从中获取,并用于通过遍历
文件系统。对于 jar URL,解析器要么从中获取 a,要么手动解析 jar URL,然后遍历
内容解析通配符。Resource
jar:
zip:
wsjar
java.io.File
java.net.JarURLConnection
对可移植性的影响
如果指定的路径已经是一个 URL(无论是隐式的,因为基是文件系统的 URL,还是显式的),则通配符保证为
以完全便携的方式工作。file
ResourceLoader
如果指定的路径是一个位置,则解析程序必须获取最后一个
非通配符路径段 URL。由于这个
只是路径的一个节点(而不是末尾的文件),实际上它未定义(在 javadoc 中)在这种情况下返回的 URL 类型。在实践中,
它始终表示目录(其中 Classpath 资源
解析为文件系统位置)或某种类型的 jar URL(其中 Classpath 资源
解析为 jar 位置)。尽管如此,此操作仍然存在可移植性问题。classpath
Classloader.getResource()
ClassLoader
java.io.File
如果获取了最后一个非通配符段的 jar URL,则解析程序必须能够
从中获取 a 或手动解析 jar URL,以便能够
遍历 jar 的内容并解析通配符。这在大多数环境中都有效
但在其他 API 中失败,我们强烈建议 resources 的通配符解析
来自 jars 在您依赖它之前,请在您的特定环境中对其进行全面测试。java.net.JarURLConnection
前缀classpath*:
在构建基于 XML 的应用程序上下文时,位置字符串可以使用
特殊前缀,如下例所示:classpath*:
-
Java
-
Kotlin
ApplicationContext ctx =
new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
val ctx = ClassPathXmlApplicationContext("classpath*:conf/appContext.xml")
此特殊前缀指定与给定名称匹配的所有 Classpath 资源
必须获取(在内部,这基本上是通过调用 发生 ),然后合并以形成最终应用程序
context 定义。ClassLoader.getResources(…)
通配符类路径依赖于底层 .由于现在大多数应用程序服务器都提供自己的实现,因此行为可能会有所不同,尤其是在处理 jar 文件时。一个
检查是否有效的简单测试是使用 加载文件
在 Classpath 上的 jar 中: .尝试此测试
具有相同名称但位于两个不同位置的文件 — 例如,文件
具有相同的名称和相同的路径,但在 Classpath 上的不同 jar 中。如果
返回不适当的结果,请查看 Application Server 文档了解设置
这可能会影响行为。getResources() ClassLoader ClassLoader classpath* ClassLoader getClass().getClassLoader().getResources("<someFileInsideTheJar>") ClassLoader |
您还可以将前缀与
位置路径的其余部分(例如 )。在这个
的情况下,解析策略相当简单:调用
用于获取
类加载器层次结构,然后从每个资源中使用相同的分辨率
前面描述的策略用于通配符子路径。classpath*:
PathMatcher
classpath*:META-INF/*-beans.xml
ClassLoader.getResources()
PathMatcher
与通配符相关的其他说明
请注意,当与 Ant 样式模式结合使用时,仅
可靠地使用至少一个根目录,除非实际的
目标文件驻留在文件系统中。这意味着诸如 jar 文件的根目录之类的模式可能不会从 jar 文件的根目录中检索文件,而只会从
从扩展目录的根目录。classpath*:
classpath*:*.xml
Spring 检索 Classpath 条目的能力源自 JDK 的方法,该方法仅返回
空字符串(指示要搜索的潜在根)。Spring 评估运行时配置和 jar 文件中的清单
,但不能保证这会导致可移植行为。ClassLoader.getResources()
URLClassLoader
java.class.path
扫描 classpath 包需要存在相应的目录
条目。使用 Ant 构建 JAR 时,请勿激活 JAR 任务的开关。此外,Classpath 目录可能不会根据安全性公开
某些环境中的策略 — 例如,JDK 1.7.0_45 上的独立应用程序
和更高级别(这需要在您的清单中设置 'Trusted-Library')。请参阅 stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources)。 在模块路径(Java Module System)上,Spring 的类路径扫描通常工作为 预期。在这里,强烈建议将资源放入专用目录, 避免了上述搜索 jar 文件根级别的可移植性问题。 |
不保证包含资源的 ant 样式模式能够找到匹配项
resources(如果要搜索的根包在多个 Classpath 位置中可用)。
请考虑以下资源位置示例:classpath:
com/mycompany/package1/service-context.xml
现在考虑一个 Ant 样式的路径,有人可能会使用它来尝试查找该文件:
classpath:com/mycompany/**/service-context.xml
这样的资源可能只存在于 Classpath 中的一个位置,但是当
前面的示例用于尝试解决它,解析器在(第一个)
由 返回的 URL。如果此基础包节点存在于
多个位置,则所需的资源可能不存在于第一个
找到位置。因此,在这种情况下,您应该更喜欢与
相同的 Ant 样式模式,它搜索包含基本包的所有类路径位置: .getResource("com/mycompany");
ClassLoader
classpath*:
com.mycompany
classpath*:com/mycompany/**/service-context.xml
FileSystemResource
警告
A 未附加到 (该
is,当 a 不是实际的 ) 处理
绝对路径和相对路径。相对路径是相对于
当前工作目录,而绝对路径是相对于
文件系统。FileSystemResource
FileSystemApplicationContext
FileSystemApplicationContext
ResourceLoader
但是,出于向后兼容性(历史)原因,当 为 .强制所有附加的实例
将所有位置路径视为相对路径,无论它们是否以前导斜杠开头。
在实践中,这意味着以下示例是等效的:FileSystemApplicationContext
ResourceLoader
FileSystemApplicationContext
FileSystemResource
-
Java
-
Kotlin
ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/context.xml");
val ctx = FileSystemXmlApplicationContext("conf/context.xml")
-
Java
-
Kotlin
ApplicationContext ctx =
new FileSystemXmlApplicationContext("/conf/context.xml");
val ctx = FileSystemXmlApplicationContext("/conf/context.xml")
以下示例也是等效的(即使它们不同是有意义的,但作为一个 case 是相对的,另一个是绝对的):
-
Java
-
Kotlin
FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("some/resource/path/myTemplate.txt");
val ctx: FileSystemXmlApplicationContext = ...
ctx.getResource("some/resource/path/myTemplate.txt")
-
Java
-
Kotlin
FileSystemXmlApplicationContext ctx = ...;
ctx.getResource("/some/resource/path/myTemplate.txt");
val ctx: FileSystemXmlApplicationContext = ...
ctx.getResource("/some/resource/path/myTemplate.txt")
在实践中,如果你需要真正的绝对文件系统路径,你应该避免使用
带有 OR 和
通过使用 URL 前缀强制使用 a。以下示例
演示如何执行此操作:FileSystemResource
FileSystemXmlApplicationContext
UrlResource
file:
-
Java
-
Kotlin
// actual context type doesn't matter, the Resource will always be UrlResource
ctx.getResource("file:///some/resource/path/myTemplate.txt");
// actual context type doesn't matter, the Resource will always be UrlResource
ctx.getResource("file:///some/resource/path/myTemplate.txt")
-
Java
-
Kotlin
// force this FileSystemXmlApplicationContext to load its definition via a UrlResource
ApplicationContext ctx =
new FileSystemXmlApplicationContext("file:///conf/context.xml");
// force this FileSystemXmlApplicationContext to load its definition via a UrlResource
val ctx = FileSystemXmlApplicationContext("file:///conf/context.xml")
通配符类路径依赖于底层 .由于现在大多数应用程序服务器都提供自己的实现,因此行为可能会有所不同,尤其是在处理 jar 文件时。一个
检查是否有效的简单测试是使用 加载文件
在 Classpath 上的 jar 中: .尝试此测试
具有相同名称但位于两个不同位置的文件 — 例如,文件
具有相同的名称和相同的路径,但在 Classpath 上的不同 jar 中。如果
返回不适当的结果,请查看 Application Server 文档了解设置
这可能会影响行为。getResources() ClassLoader ClassLoader classpath* ClassLoader getClass().getClassLoader().getResources("<someFileInsideTheJar>") ClassLoader |
扫描 classpath 包需要存在相应的目录
条目。使用 Ant 构建 JAR 时,请勿激活 JAR 任务的开关。此外,Classpath 目录可能不会根据安全性公开
某些环境中的策略 — 例如,JDK 1.7.0_45 上的独立应用程序
和更高级别(这需要在您的清单中设置 'Trusted-Library')。请参阅 stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources)。 在模块路径(Java Module System)上,Spring 的类路径扫描通常工作为 预期。在这里,强烈建议将资源放入专用目录, 避免了上述搜索 jar 文件根级别的可移植性问题。 |