本章介绍了 Spring 如何处理资源以及如何使用 Spring。它包括以下主题:
介绍
Java 的标准类和各种 URL 前缀的标准处理程序,
不幸的是,对于所有对低级资源的访问来说,这还不够。为
示例中,没有可用于访问
需要从 Classpath 获取的资源或相对于 .虽然可以为专用前缀注册新的处理程序(类似于前缀的现有处理程序,例如 ),这通常是
相当复杂,并且界面仍然缺乏一些理想的功能,
例如,用于检查所指向的资源是否存在的方法。java.net.URLURLServletContextURLhttp:URL
界面Resource
Spring 的接口位于包中
旨在成为对低级资源的抽象访问的更强大的接口。这
下面的清单提供了该界面的概述。有关更多详细信息,请参阅 Resource javadoc。Resourceorg.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();
}
如接口的定义所示,它扩展了接口。下面的清单显示了接口的定义:ResourceInputStreamSourceInputStreamSource
public interface InputStreamSource {
	InputStream getInputStream() throws IOException;
}
界面中一些最重要的方法是:Resource
- 
getInputStream():查找并打开资源,返回 for 从资源中读取。预计每次调用都会返回一个新的 .调用方负责关闭流。InputStreamInputStream - 
exists():返回一个 物理形式。boolean - 
isOpen():返回一个 tag,指示此资源是否表示句柄 与开放的流。如果 ,则不能多次读取 ,并且 必须只读取一次,然后关闭以避免资源泄漏。的返回 所有常用的资源实现,除了 .booleantrueInputStreamfalseInputStreamResource - 
getDescription():返回此资源的说明,用于错误 output 来执行。这通常是完全限定的文件名或 资源的实际 URL。 
其他方法允许您获取表示
资源(如果底层实现兼容并支持
功能)。URLFile
该接口的某些实现还实现了扩展的 WritableResource 接口
对于支持写入它的资源。Resource
Spring 本身广泛使用抽象,作为
需要资源时有许多方法签名。某些 Spring API 中的其他方法
(例如各种实现的构造函数)采用一个 THAT,它以朴素或简单的形式用于创建适当的
该上下文实现,或者通过路径上的特殊前缀,让
caller 指定必须创建和使用特定实现。ResourceApplicationContextStringResourceStringResource
虽然该接口与 Spring 和 Spring 一起使用很多,但它实际上是
非常方便,可以在您自己的代码中单独用作通用工具类,以便访问
添加到资源中,即使您的代码不知道或不关心 Spring 的任何其他部分。
虽然这会将您的代码耦合到 Spring,但它实际上只将其耦合到这一小群
Utility 类,它可以作为
被认为等同于您用于此目的的任何其他库。ResourceURL
抽象不会取代功能。它将其包装在
可能。例如,a 包装一个 URL 并使用包装的 URL 来执行其
工作。ResourceUrlResourceURL | 
抽象不会取代功能。它将其包装在
可能。例如,a 包装一个 URL 并使用包装的 URL 来执行其
工作。ResourceUrlResourceURL | 
内置实现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.URLStringfile:https:ftp:
A 由 Java 代码显式使用构造函数创建
但通常在调用采用用于表示路径的参数的 API 方法时隐式创建。对于后一种情况,JavaBeans 最终决定创建哪种类型。如果路径字符串包含
众所周知的(对于属性编辑器来说,即)前缀(例如 ),它会创建一个
适当的 专门用于该前缀。但是,如果它无法识别
前缀,则假定该字符串是标准 URL 字符串,并创建一个 .UrlResourceUrlResourceStringPropertyEditorResourceclasspath:ResourceUrlResource
ClassPathResource
此类表示应从 Classpath 获取的资源。它使用 线程上下文类加载器、给定类加载器或 loading resources.
此实现支持将 Expression 解析为 Bean 的 class path
资源驻留在文件系统中,但不适用于驻留在
jar 中,并且尚未扩展(通过 servlet 引擎或任何环境)
添加到文件系统中。为了解决这个问题,各种 implementations 始终支持
分辨率设置为 .Resourcejava.io.FileResourcejava.net.URL
A 是由 Java 代码通过显式使用构造函数创建的,但通常是在调用采用用于表示路径的参数的 API 方法时隐式创建的。对于后一种情况,JavaBeans 识别字符串路径上的特殊前缀 , 和
在这种情况下创建一个。ClassPathResourceClassPathResourceStringPropertyEditorclasspath:ClassPathResource
FileSystemResource
这是 handles 的实现。它还支持句柄,应用 Spring 的标准基于 String 的 path
转换,但通过 API 执行所有操作。对于纯基础支持,请改用 a。 支持分辨率为 A 和 .Resourcejava.io.Filejava.nio.file.Pathjava.nio.file.Filesjava.nio.path.PathPathResourceFileSystemResourceFileURL
PathResource
这是一个用于 handles 的实现,执行所有
操作和转换。它支持将分辨率解析为 和
作为 A 进行,并且还实现了扩展接口。 实际上是 with 的纯基替代品
不同的行为。Resourcejava.nio.file.PathPathFileURLWritableResourcePathResourcejava.nio.path.PathFileSystemResourcecreateRelative
ServletContextResource
这是解释
相关 Web 应用程序根目录中的相对路径。ResourceServletContext
它始终支持流访问和 URL 访问,但仅允许访问
当 Web 应用程序存档扩展并且资源物理位于
文件系统。无论它是否被扩展、在文件系统上或被访问
直接从 JAR 或其他位置(如数据库)实际上是
依赖于 Servlet 容器。java.io.File
界面ResourceLoader
该接口旨在由可以返回
(即 load)实例。下面的清单显示了接口定义:ResourceLoaderResourceResourceLoader
public interface ResourceLoader {
	Resource getResource(String location);
	ClassLoader getClassLoader();
}
所有应用程序上下文都实现该接口。因此,所有
应用程序上下文可用于获取实例。ResourceLoaderResource
当您调用特定的应用程序上下文时,位置路径
specified 没有特定的前缀,则返回一个
适合该特定应用程序上下文。例如,假设以下内容
针对实例运行的代码片段:getResource()ResourceClassPathXmlApplicationContext
- 
Java
 - 
Kotlin
 
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
val template = ctx.getResource("some/resource/path/myTemplate.txt")
对于 ,该代码返回一个 .如果
相同的方法对实例运行,它将
返回一个 .对于 a ,它将返回一个 .它同样会为每个上下文返回适当的对象。ClassPathXmlApplicationContextClassPathResourceFileSystemXmlApplicationContextFileSystemResourceWebApplicationContextServletContextResource
因此,您可以以适合特定应用程序的方式加载资源 上下文。
另一方面,您也可以强制使用
application context 类型,通过指定特殊前缀,如下所示
示例显示:ClassPathResourceclasspath:
- 
Java
 - 
Kotlin
 
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
val template = ctx.getResource("classpath:some/resource/path/myTemplate.txt")
同样,您可以通过指定任何标准前缀来强制使用 a。以下示例使用 和 前缀:UrlResourcejava.net.URLfilehttps
- 
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")
下表总结了将对象转换为对象的策略:StringResource
| 前缀 | 例 | 解释 | 
|---|---|---|
类路径:  | 
  | 
从 Classpath 加载。  | 
文件:  | 
  | 
作为 从文件系统加载。另请参阅   | 
https 的 URL 中:  | 
  | 
加载为 .  | 
(无)  | 
  | 
取决于底层 .  | 
| 前缀 | 例 | 解释 | 
|---|---|---|
类路径:  | 
  | 
从 Classpath 加载。  | 
文件:  | 
  | 
作为 从文件系统加载。另请参阅   | 
https 的 URL 中:  | 
  | 
加载为 .  | 
(无)  | 
  | 
取决于底层 .  | 
界面ResourcePatternResolver
interface 是 interface 的扩展
,它定义了解析位置模式(例如,Ant 样式路径
pattern) 转换为对象。ResourcePatternResolverResourceLoaderResource
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.xmlclasspath*:
可以检查传入的 (例如,通过 ResourceLoaderAware 语义提供的)
它也实现了这个扩展接口。ResourceLoader
PathMatchingResourcePatternResolver是可用的独立实现
在 an 和 之外也被用于
填充 bean 属性。 能够
将指定的资源位置路径解析为一个或多个匹配对象。
源路径可以是与 target 进行一对一映射的简单路径,也可以包含特殊前缀和/或 internal
Ant 样式的正则表达式(使用 Spring 的实用程序进行匹配)。后者两者都是有效的
通配符。ApplicationContextResourceArrayPropertyEditorResource[]PathMatchingResourcePatternResolverResourceResourceclasspath*:org.springframework.util.AntPathMatcher
| 
 任何标准中的默认值实际上都是一个实例
其中实现接口。实例本身也是如此,它也
实现接口并委托给默认的 .  | 
| 
 任何标准中的默认值实际上都是一个实例
其中实现接口。实例本身也是如此,它也
实现接口并委托给默认的 .  | 
界面ResourceLoaderAware
该接口是一个特殊的回调接口,用于标识
组件。以下清单
显示了接口的定义:ResourceLoaderAwareResourceLoaderResourceLoaderAware
public interface ResourceLoaderAware {
	void setResourceLoader(ResourceLoader resourceLoader);
}
当类实现并部署到应用程序上下文中时
(作为 Spring 管理的 bean)中,它被应用程序识别为
上下文。然后,应用程序上下文调用 ,
将自身作为参数提供(请记住,Spring 中的所有应用程序上下文都实现了
界面)。ResourceLoaderAwareResourceLoaderAwaresetResourceLoader(ResourceLoader)ResourceLoader
由于 an 是 ,因此 bean 还可以实现接口并使用提供的应用程序上下文直接
load 资源。但是,一般来说,如果这就是您所需要的,最好使用专用界面。该代码将仅与资源加载耦合
接口(可以被认为是一个 Util 接口),而不是整个 Spring 接口。ApplicationContextResourceLoaderApplicationContextAwareResourceLoaderApplicationContext
在应用程序组件中,您还可以依赖 as 的自动装配
实现接口的替代方法。传统模式和自动装配模式(如 自动装配协作者中所述)
能够为 constructor 参数或
setter 方法参数。为了获得更大的灵活性(包括
autowire fields 和多个参数方法),请考虑使用基于注释的
自动装配功能。在这种情况下,它被自动连接到一个字段
constructor 参数或期望类型为 long 的方法参数
因为有问题的 field、constructor 或 method 带有 Annotation。
有关更多信息,请参阅使用 @Autowired。ResourceLoaderResourceLoaderAwareconstructorbyTypeResourceLoaderResourceLoaderResourceLoader@Autowired
为包含通配符的资源路径加载一个或多个对象
或使用特殊的资源前缀,请考虑将 ResourcePatternResolver 的实例自动连接到您的
application 组件而不是 .Resourceclasspath*:ResourceLoader | 
为包含通配符的资源路径加载一个或多个对象
或使用特殊的资源前缀,请考虑将 ResourcePatternResolver 的实例自动连接到您的
application 组件而不是 .Resourceclasspath*:ResourceLoader | 
作为依赖项的资源
如果 Bean 本身将通过某种排序来确定和提供资源路径
动态进程中,bean 使用 or 接口来加载资源可能是有意义的。例如,考虑 loading
中,所需的特定资源取决于
用户的角色。如果资源是静态的,那么完全消除接口(或接口)的使用是有意义的,让
bean 公开了它需要的属性,并期望将它们注入其中。ResourceLoaderResourcePatternResolverResourceLoaderResourcePatternResolverResource
然后注入这些属性变得微不足道的是,所有应用程序上下文
注册并使用一个特殊的 JavaBeans ,它可以转换路径
到对象。例如,以下类具有 .PropertyEditorStringResourceMyBeantemplateResource
- 
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>
请注意,资源路径没有前缀。因此,由于应用程序上下文
本身将用作 ,资源通过 、 、 或 、 加载,具体取决于
应用程序上下文的确切类型。ResourceLoaderClassPathResourceFileSystemResourceServletContextResource
如果需要强制使用特定类型,可以使用前缀。这
以下两个示例展示了如何强制 A 和 A (
后者用于访问文件系统中的文件):ResourceClassPathResourceUrlResource
<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会
将模板路径的值检索为字符串,并且会有一个特殊的
将字符串转换为要注入构造函数的对象。
以下示例演示了如何实现此目的。MyBeanmyTemplate.txttemplate.pathEnvironment@ValuePropertyEditorResourceMyBean
- 
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.pathclasspath*:/config/templates/*.txtMyBeanResourceMyBean
- 
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 定义的路径取决于 并且适合于
特定的应用程序上下文。例如,请考虑以下示例,该示例创建一个 :ResourceClassPathXmlApplicationContext
- 
Java
 - 
Kotlin
 
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
val ctx = ClassPathXmlApplicationContext("conf/appContext.xml")
Bean 定义是从 Classpath 加载的,因为
使用。但是,请考虑以下示例,该示例创建一个 :ClassPathResourceFileSystemXmlApplicationContext
- 
Java
 - 
Kotlin
 
ApplicationContext ctx =
	new FileSystemXmlApplicationContext("conf/appContext.xml");
val ctx = FileSystemXmlApplicationContext("conf/appContext.xml")
现在,bean 定义是从文件系统位置加载的(在本例中,相对于 当前工作目录)。
请注意,在
location path 覆盖 created 的默认类型以加载 bean
定义。请考虑以下示例:classpathResource
- 
Java
 - 
Kotlin
 
ApplicationContext ctx =
	new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
val ctx = FileSystemXmlApplicationContext("classpath:conf/appContext.xml")
Using 从 Classpath 中加载 bean 定义。
但是,它仍然是 .如果随后将其用作 a ,则任何未带前缀的路径仍被视为文件系统路径。FileSystemXmlApplicationContextFileSystemXmlApplicationContextResourceLoader
构造实例 — 快捷方式ClassPathXmlApplicationContext
这公开了许多构造函数以启用
方便的实例化。基本思想是,您可以只提供一个字符串数组
,仅包含 XML 文件本身的文件名(没有前导路径
信息),并提供 .then 派生
来自提供的类的路径信息。ClassPathXmlApplicationContextClassClassPathXmlApplicationContext
请考虑以下目录布局:
com/
  example/
    services.xml
    repositories.xml
    MessengerService.class
以下示例显示了由
在名为 和 (位于
classpath) 可以实例化:ClassPathXmlApplicationContextservices.xmlrepositories.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 进行匹配)。后者两者都是有效的
通配符。Resourceclasspath*:PathMatcher
此机制的一个用途是当您需要执行组件样式的应用程序组装时。都
组件可以将上下文定义片段发布到已知的位置路径,并且
当使用前缀为 的相同路径创建最终应用程序上下文时,会自动选取所有组件片段。classpath*:
请注意,此通配符特定于应用程序上下文中资源路径的使用
构造函数(或者直接使用实用程序类层次结构时),并且是
在构建时解决。它与类型本身无关。
您不能使用前缀来构造实际的 ,因为
一个资源一次只指向一个资源。PathMatcherResourceclasspath*: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,然后遍历
内容解析通配符。Resourcejar:zip:wsjarjava.io.Filejava.net.JarURLConnection
对可移植性的影响
如果指定的路径已经是一个 URL(无论是隐式的,因为基是文件系统的 URL,还是显式的),则通配符保证为
以完全便携的方式工作。fileResourceLoader
如果指定的路径是一个位置,则解析程序必须获取最后一个
非通配符路径段 URL。由于这个
只是路径的一个节点(而不是末尾的文件),实际上它未定义(在 javadoc 中)在这种情况下返回的 URL 类型。在实践中,
它始终表示目录(其中 Classpath 资源
解析为文件系统位置)或某种类型的 jar URL(其中 Classpath 资源
解析为 jar 位置)。尽管如此,此操作仍然存在可移植性问题。classpathClassloader.getResource()ClassLoaderjava.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()ClassLoaderClassLoaderclasspath*ClassLoadergetClass().getClassLoader().getResources("<someFileInsideTheJar>")ClassLoader | 
您还可以将前缀与
位置路径的其余部分(例如 )。在这个
的情况下,解析策略相当简单:调用
用于获取
类加载器层次结构,然后从每个资源中使用相同的分辨率
前面描述的策略用于通配符子路径。classpath*:PathMatcherclasspath*:META-INF/*-beans.xmlClassLoader.getResources()PathMatcher
与通配符相关的其他说明
请注意,当与 Ant 样式模式结合使用时,仅
可靠地使用至少一个根目录,除非实际的
目标文件驻留在文件系统中。这意味着诸如 jar 文件的根目录之类的模式可能不会从 jar 文件的根目录中检索文件,而只会从
从扩展目录的根目录。classpath*:classpath*:*.xml
Spring 检索 Classpath 条目的能力源自 JDK 的方法,该方法仅返回
空字符串(指示要搜索的潜在根)。Spring 评估运行时配置和 jar 文件中的清单
,但不能保证这会导致可移植行为。ClassLoader.getResources()URLClassLoaderjava.class.path
| 
 扫描 classpath 包需要存在相应的目录
条目。使用 Ant 构建 JAR 时,请勿激活 JAR 任务的开关。此外,Classpath 目录可能不会根据安全性公开
某些环境中的策略 — 例如,JDK 1.7.0_45 上的独立应用程序
和更高级别(这需要在您的清单中设置 'Trusted-Library')。请参阅 stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources)。 在 JDK 9 的模块路径(拼图)上, Spring 的 Classpath 扫描通常按预期工作。 在这里,强烈建议将资源放入专用目录, 避免了上述搜索 jar 文件根级别的可移植性问题。  | 
不保证包含资源的 ant 样式模式能够找到匹配项
resources(如果要搜索的根包在多个 Classpath 位置中可用)。
请考虑以下资源位置示例:classpath:
com/mycompany/package1/service-context.xml
现在考虑一个 Ant 样式的路径,有人可能会使用它来尝试查找该文件:
classpath:com/mycompany/**/service-context.xml
这样的资源可能只存在于 Classpath 中的一个位置,但是当
前面的示例用于尝试解决它,解析器在(第一个)
由 返回的 URL。如果此基础包节点存在于
多个位置,则所需的资源可能不存在于第一个
找到位置。因此,在这种情况下,您应该更喜欢与
相同的 Ant 样式模式,它搜索包含基本包的所有类路径位置: .getResource("com/mycompany");ClassLoaderclasspath*:com.mycompanyclasspath*:com/mycompany/**/service-context.xml
FileSystemResource警告
A 未附加到 (该
is,当 a 不是实际的 ) 处理
绝对路径和相对路径。相对路径是相对于
当前工作目录,而绝对路径是相对于
文件系统。FileSystemResourceFileSystemApplicationContextFileSystemApplicationContextResourceLoader
但是,出于向后兼容性(历史)原因,当 为 .强制所有附加的实例
将所有位置路径视为相对路径,无论它们是否以前导斜杠开头。
在实践中,这意味着以下示例是等效的:FileSystemApplicationContextResourceLoaderFileSystemApplicationContextFileSystemResource
- 
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。以下示例
演示如何执行此操作:FileSystemResourceFileSystemXmlApplicationContextUrlResourcefile:
- 
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()ClassLoaderClassLoaderclasspath*ClassLoadergetClass().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)。 在 JDK 9 的模块路径(拼图)上, Spring 的 Classpath 扫描通常按预期工作。 在这里,强烈建议将资源放入专用目录, 避免了上述搜索 jar 文件根级别的可移植性问题。  |