|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
资源
本章介绍Spring如何处理资源以及你如何在Spring中使用资源。它包括以下主题:
简介
Java 的标准 java.net.URL 类和针对各种 URL 前缀的标准处理程序,不幸的是,对于所有对底层资源的访问来说并不足够。例如,没有标准化的 URL 实现可用于从类路径或相对于 ServletContext 获取资源。虽然可以为特定的 URL 前缀注册新的处理程序(类似于 http: 等现有处理程序),但通常比较复杂,URL 接口仍然缺少一些有用的功能,例如检查所指向资源是否存在的方法。
这个 Resource 接口
Spring 的 Resource 接口位于 org.springframework.core.io. 包中,旨在为抽象访问底层资源提供更强大的接口。以下列表提供了 Resource 接口的概述。有关更多详细信息,请参阅
Resource 的 javadoc。
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(): 定位并打开资源,返回一个InputStream以从该资源读取。每次调用都应返回一个新的InputStream。调用者有责任关闭流。 -
exists(): 返回一个boolean,表示此资源是否实际以物理形式存在。 -
isOpen(): 返回一个boolean表示此资源是否表示具有打开流的句柄。如果为true,则InputStream不能多次读取,只能读取一次,然后关闭以避免资源泄漏。对于所有常规资源实现,返回false,除了InputStreamResource之外。 -
getDescription(): 返回此资源的描述,用于在处理资源时的错误输出。这通常是完全限定的文件名或资源的实际URL。
其他方法可以让您获得一个实际的 URL 或 File 对象,该对象表示资源(如果底层实现兼容并支持该功能)。
某些 Resource 接口的实现还实现了扩展的
WritableResource 接口
,用于支持写入它的资源。
Spring 本身广泛使用 Resource 抽象,作为许多方法签名中的参数类型,当需要资源时使用。某些 Spring API 中的其他方法(例如各种 ApplicationContext 实现的构造函数)接受一个 String,在未经修饰或简单形式下用于创建适合该上下文实现的 Resource,或者通过在 String 路径上的特殊前缀,让调用者指定必须创建并使用的特定 Resource 实现。
虽然 Resource 接口在 Spring 中被广泛使用,而且 Spring 本身也经常使用它,但将其作为通用工具类在您自己的代码中使用也非常方便,用于访问资源,即使您的代码不关心 Spring 的其他部分。虽然这会使您的代码与 Spring 耦合,但它实际上只与这一小组工具类耦合,这些工具类可以作为 URL 的更强大替代品,并可以视为与其他用于此目的的库相当。
The Resource 抽象不会替换功能。
它会在可能的情况下对其进行包装。例如,UrlResource 会包装一个 URL 并使用包装后的 URL 来完成其工作。 |
内置的Resource实现
Spring 包含多个内置 Resource 实现:
有关Spring中可用的<code>0</code>实现的完整列表,请参阅 <a t="C2"><code>1</code></a> javadoc中的 “所有已知实现类”部分。
UrlResource
UrlResource 包装一个 java.net.URL,可以用来访问通常可以通过 URL 访问的任何对象,例如文件、HTTPS 目标、FTP 目标等。所有 URL 都有标准化的 String 表示形式,以便使用适当的标准化前缀来区分不同的 URL 类型。这包括 file: 用于访问文件系统路径,https: 用于通过 HTTPS 协议访问资源,ftp: 用于通过 FTP 访问资源等。
一个 UrlResource 是通过 Java 代码显式使用 UrlResource 构造函数创建的,
但通常在调用一个以 String 为参数的 API 方法时会隐式创建。
对于后一种情况,JavaBeans PropertyEditor 最终决定创建哪种类型的 Resource。
如果路径字符串包含已知的(对属性编辑器而言)前缀(例如 classpath:),它会为该前缀创建适当的专用 Resource。
然而,如果它无法识别前缀,就会认为该字符串是一个标准的 URL 字符串,并创建一个 UrlResource。
ClassPathResource
这个类表示应从类路径获取的资源。它使用线程上下文类加载器、给定的类加载器或给定的类来加载资源。
此 Resource 实现如果类路径资源位于文件系统中,但不适用于位于 jar 中且未被 servlet 引擎或任何环境扩展到文件系统的类路径资源。为了解决这个问题,各种 Resource 实现始终支持作为 java.net.URL 的解析。
一个 ClassPathResource 是通过 Java 代码显式使用 ClassPathResource 构造函数创建的,但当你调用一个需要 String 参数的 API 方法来表示路径时,通常会隐式创建。在后一种情况下,JavaBeans PropertyEditor 会识别字符串路径上的特殊前缀 classpath:,并在这种情况下创建一个 ClassPathResource。
FileSystemResource
这是一个 Resource 实现,用于 java.io.File 处理。它还支持
java.nio.file.Path 处理,应用 Spring 的标准基于字符串的路径
转换,但所有操作均通过 java.nio.file.Files API 执行。对于纯
java.nio.path.Path 支持,请使用 PathResource。 FileSystemResource
可以作为 File 和 URL 进行解析。
PathResource
这是一个用于Resource的java.nio.file.Path实现,通过Path API执行所有操作和转换。它支持作为File和URL进行解析,并且还实现了扩展的WritableResource接口。PathResource实际上是FileSystemResource的一种基于java.nio.path.Path的纯替代方案,具有不同的createRelative行为。
ServletContextResource
这是对Resource资源的ServletContext实现,它解释了相关Web应用程序根目录内的相对路径。
它始终支持流访问和URL访问,但只有在Web应用程序存档已解压且资源在文件系统上时才允许java.io.File访问。
是否已解压并在文件系统上,或者直接从JAR或其他地方(如数据库)访问,实际上取决于Servlet容器。
这个 ResourceLoader 接口
ResourceLoader 接口旨在由可以返回(即加载)Resource 实例的对象实现。以下列表显示了 ResourceLoader 接口的定义:
public interface ResourceLoader {
Resource getResource(String location);
ClassLoader getClassLoader();
}
所有应用程序上下文都实现 ResourceLoader 接口。因此,所有应用程序上下文都可以用来获取 Resource 实例。
当您在特定的应用程序上下文上调用 getResource(),并且指定的位置路径没有特定的前缀时,您将返回一个与该特定应用程序上下文相适应的 Resource 类型。例如,假设以下代码片段是针对 ClassPathXmlApplicationContext 实例运行的:
-
Java
-
Kotlin
Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
val template = ctx.getResource("some/resource/path/myTemplate.txt")
相对于 ClassPathXmlApplicationContext,这段代码返回 ClassPathResource。如果同一方法针对 FileSystemXmlApplicationContext 实例运行,它将返回 FileSystemResource。对于 WebApplicationContext,它将返回 ServletContextResource。它会为每个上下文返回适当的对象。
因此,你可以以适合特定应用程序上下文的方式加载资源。
另一方面,您还可以通过指定特殊的 classpath: 前缀,强制使用 ClassPathResource,而不管应用程序上下文类型如何,如下例所示:
-
Java
-
Kotlin
Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
val template = ctx.getResource("classpath:some/resource/path/myTemplate.txt")
同样,您可以通过指定任何标准的 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: |
|
从类路径加载。 |
file: |
|
作为 |
https: |
|
作为 |
无 |
|
取决于基础 |
这个 ResourcePatternResolver 接口
ResourcePatternResolver 接口是对 ResourceLoader 接口的扩展,它定义了将位置模式(例如,Ant 风格的路径模式)解析为 Resource 对象的策略。
public interface ResourcePatternResolver extends ResourceLoader {
String CLASSPATH_ALL_URL_PREFIX = "classpath*:";
Resource[] getResources(String locationPattern) throws IOException;
}
如上所示,此接口还为类路径中的所有匹配资源定义了一个特殊的classpath*:资源前缀。请注意,在这种情况下,资源位置应为一个不带占位符的路径——例如,classpath*:/config/beans.xml。类路径中的JAR文件或不同目录可能包含具有相同路径和相同名称的多个文件。有关classpath*:资源前缀的通配符支持的更多细节,请参阅应用上下文构造函数资源路径中的通配符及其子主题。
传入的 ResourceLoader(例如通过
ResourceLoaderAware 语义提供的)可以检查
它是否也实现了这个扩展接口。
PathMatchingResourcePatternResolver 是一个独立的实现,可以在 ApplicationContext 之外使用,并且也被 ResourceArrayPropertyEditor 用于填充 Resource[] bean 属性。 PathMatchingResourcePatternResolver 能够将指定的资源路径解析为一个或多个匹配的 Resource 对象。源路径可能是一个简单的路径,该路径与目标 Resource 有一一对应的关系,或者可能包含特殊的 classpath*: 前缀和/或内部 Ant 风格的正则表达式(使用 Spring 的 org.springframework.util.AntPathMatcher 实用工具进行匹配)。后两者实际上是通配符。
|
默认的 |
这个 ResourceLoaderAware 接口
ResourceLoaderAware 接口是一个特殊的回调接口,用于标识那些期望获得 ResourceLoader 引用的组件。下面的代码展示了 ResourceLoaderAware 接口的定义:
public interface ResourceLoaderAware {
void setResourceLoader(ResourceLoader resourceLoader);
}
当一个类实现 ResourceLoaderAware 并部署到应用上下文中(作为Spring管理的Bean),应用上下文会将其识别为 ResourceLoaderAware。然后应用上下文会调用 setResourceLoader(ResourceLoader),并把自己作为参数传入(记住,Spring中的所有应用上下文都实现了 ResourceLoader 接口)。
由于 ApplicationContext 是 ResourceLoader,该 bean 也可以实现 ApplicationContextAware 接口,并直接使用提供的应用上下文来加载资源。然而,通常情况下,如果只需要该功能,最好使用专门的 ResourceLoader 接口。这样代码只会与资源加载接口(可以视为一个工具接口)耦合,而不会与整个 Spring ApplicationContext 接口耦合。
在应用程序组件中,您还可以依赖ResourceLoader的自动连接,作为实现ResourceLoaderAware接口的替代方法。传统的constructor和byType自动连接模式(如自动连接协作对象中所述)可以分别为构造函数参数或setter方法参数提供ResourceLoader。为了获得更大的灵活性(包括自动连接字段和多个参数的方法),可以考虑使用基于注解的自动连接功能。在这种情况下,只要相关字段、构造函数或方法带有@Autowired注解,ResourceLoader就会被自动连接到期望ResourceLoader类型的字段、构造函数参数或方法参数上。有关更多信息,请参见使用@Autowired。
要加载一个或多个 Resource 对象,以用于包含通配符或使用特殊 classpath*: 资源前缀的资源路径,建议将 ResourcePatternResolver 的实例注入到您的应用程序组件中,而不是 ResourceLoader。 |
作为依赖项的资源配置
如果该bean本身将通过某种动态过程确定并提供资源路径,那么该bean使用ResourceLoader或ResourcePatternResolver接口来加载资源可能是有意义的。例如,考虑加载某种模板的情况,其中所需的特定资源取决于用户的角色。如果资源是静态的,那么完全消除使用ResourceLoader接口(或ResourcePatternResolver接口)是有意义的,让bean公开它需要的Resource属性,并期望它们被注入到其中。
然后注入这些属性之所以简单,是因为所有应用上下文都注册并使用一个特殊的JavaBeans PropertyEditor,它可以将 String 路径转换为 Resource 对象。例如,以下 MyBean 类有一个类型为 Resource 的 template 属性。
-
Java
-
Kotlin
public class MyBean {
private Resource template;
public setTemplate(Resource template) {
this.template = template;
}
// ...
}
class MyBean(var template: Resource)
在XML配置文件中,可以使用一个简单字符串来配置该资源的 template 属性,如下例所示:
<bean id="myBean" class="example.MyBean">
<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>
请注意,资源路径没有前缀。因此,由于应用程序上下文本身将被用作 ResourceLoader,资源将通过 ClassPathResource、FileSystemResource 或 ServletContextResource 加载,具体取决于应用程序上下文的确切类型。
如果您需要强制使用特定的 Resource 类型,可以使用前缀。以下两个示例展示了如何强制使用 ClassPathResource 和 UrlResource(后者用于访问文件系统中的文件):
<property name="template" value="classpath:some/resource/path/myTemplate.txt">
<property name="template" value="file:///some/resource/path/myTemplate.txt"/>
如果 MyBean 类被重构以用于注解驱动的配置,那么 myTemplate.txt 的路径可以存储在一个名为 template.path 的键下 — 例如,在一个对 Spring Environment 可用的属性文件中(参见 环境抽象)。然后可以通过 @Value 注解使用属性占位符来引用模板路径(参见 使用 @Value)。Spring 会将模板路径的值作为字符串检索,一个特殊的 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)
如果我们想支持在类路径下多个位置发现的相同路径的多个模板 — 例如,在类路径中的多个jar文件中 — 可以使用特殊的classpath*:前缀和通配符来定义一个templates.path键为classpath*:/config/templates/*.txt。如果重新定义MyBean类如下,Spring会将模板路径模式转换为一个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定义是从类路径加载的,因为使用了ClassPathResource。但是,请考虑以下示例,它创建了一个FileSystemXmlApplicationContext:
-
Java
-
Kotlin
ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/appContext.xml");
val ctx = FileSystemXmlApplicationContext("conf/appContext.xml")
现在,bean 定义从文件系统位置加载(在本例中,相对于当前工作目录)。
请注意,在位置路径上使用特殊的 classpath 前缀或标准 URL 前缀会覆盖默认的 Resource 类型,该类型用于加载 bean 定义。考虑以下示例:
-
Java
-
Kotlin
ApplicationContext ctx =
new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
val ctx = FileSystemXmlApplicationContext("classpath:conf/appContext.xml")
使用 FileSystemXmlApplicationContext 会从类路径加载 bean 定义。但是,它仍然是一个 FileSystemXmlApplicationContext。如果之后作为 ResourceLoader 使用,任何未加前缀的路径仍然被视为文件系统路径。
构造 ClassPathXmlApplicationContext 实例 — 快捷方式
ClassPathXmlApplicationContext 暴露了许多构造函数,以实现方便的实例化。基本思路是,您只需提供一个仅包含 XML 文件名(不包括前导路径信息)的字符串数组,同时提供一个Class。然后ClassPathXmlApplicationContext会从提供的类中推断出路径信息。
考虑以下目录结构:
com/
example/
services.xml
repositories.xml
MessengerService.class
以下示例显示了如何实例化一个由文件名为services.xml和repositories.xml(位于类路径上)中定义的 beans 组成的ClassPathXmlApplicationContext实例:
-
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以了解有关各种构造函数的详细信息。
应用上下文构造器资源路径中的通配符
应用程序上下文构造器值中的资源路径可以是简单路径(如前所示),每个路径都与目标 Resource 一一对应,或者包含特殊的 classpath*: 前缀或内部 Ant 风格模式(通过使用 Spring 的 PathMatcher 实用工具进行匹配)。后两者实际上是通配符。
此机制的一个用途是当您需要执行组件风格的应用程序组装时。所有组件都可以将上下文定义片段发布到一个已知的路径位置,并且当使用以classpath*:开头的相同路径创建最终的应用程序上下文时,所有组件片段都会被自动拾取。
请注意,这种通配符用法仅适用于应用程序上下文构造函数中的资源路径(或当你直接使用 PathMatcher 工具类层次结构时),并在构造时进行解析。它与 Resource 类型本身无关。
你不能使用 classpath*: 前缀来构造一个实际的 Resource,因为资源一次只能指向一个资源。
Ant风格模式
路径位置可以包含 Ant 风格的模式,如下例所示:
/WEB-INF/*-context.xml com/mycompany/**/applicationContext.xml file:C:/some/path/*-context.xml classpath:com/mycompany/**/applicationContext.xml
当路径位置包含Ant风格的模式时,解析器会遵循更复杂的程序来尝试解析通配符。它会为到最后一个非通配符段的路径生成一个Resource,并从中获取一个URL。如果此URL不是jar: URL或特定于容器的变体(例如WebLogic中的zip:,WebSphere中的wsjar等),则会从该URL中获取一个java.io.File,并通过遍历文件系统来解析通配符。对于jar URL的情况,解析器会从其中获取一个java.net.JarURLConnection,或者手动解析jar URL,然后遍历jar文件的内容来解析通配符。
对可移植性的影响
如果指定的路径已经是 file URL(无论是因为基础 ResourceLoader 是文件系统路径还是显式指定),则通配符功能可以完全可移植地工作。
如果指定的路径是一个 classpath 位置,解析器必须通过进行 Classloader.getResource() 调用来获取最后一个非通配符路径段的URL。由于这只是路径中的一个节点(不是结尾的文件),在 ClassLoader 的javadoc中,确切返回哪种类型的URL实际上是未定义的。实际上,它始终是一个表示目录的 java.io.File(当类路径资源解析为文件系统位置时)或某种jar URL(当类路径资源解析为jar位置时)。尽管如此,此操作仍存在可移植性问题。
如果为最后一个非通配符段获取了jar URL,解析器必须能够从中获取java.net.JarURLConnection或手动解析jar URL,以便遍历jar的内容并解析通配符。这在大多数环境中有效,但在其他环境中会失败,因此我们强烈建议在依赖它之前,在您的特定环境中对来自jar的资源的通配符解析进行彻底测试。
前缀 classpath*:
在构建基于XML的应用程序上下文时,位置字符串可以使用特殊的classpath*:前缀,如下例所示:
-
Java
-
Kotlin
ApplicationContext ctx =
new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
val ctx = ClassPathXmlApplicationContext("classpath*:conf/appContext.xml")
此特定前缀指定所有与给定名称匹配的类路径资源必须被获取(内部上,这实际上是通过调用ClassLoader.getResources(…)来完成的),然后合并以形成最终的应用程序上下文定义。
通配符类路径依赖于底层
getResources()
的 ClassLoader 方法。由于大多数应用服务器现在都提供自己的 ClassLoader
实现,行为可能会有所不同,尤其是在处理 JAR 文件时。要检查 classpath* 是否有效,可以使用 ClassLoader 从类路径中的 JAR 文件中加载一个文件:
getClass().getClassLoader().getResources("<someFileInsideTheJar>")。用在类路径中不同位置的同名文件进行此测试——例如,同名且路径相同的文件但位于不同的 JAR 文件中。如果返回了不正确的结果,请查看应用服务器文档中可能影响 ClassLoader 行为的设置。 |
您还可以将 classpath*: 前缀与位置路径其余部分中的 PathMatcher 模式结合使用(例如,classpath*:META-INF/*-beans.xml)。在这种情况下,解析策略相当简单:对最后一个非通配符路径段调用 ClassLoader.getResources() 以获取类加载器层次结构中的所有匹配资源,然后,对每个资源,使用之前描述的相同的 PathMatcher 解析策略来处理通配符子路径。
与通配符相关的其他注意事项
请注意,当与Ant风格的模式结合使用时,classpath*:仅在模式开始前至少有一个根目录时才能可靠工作,除非实际的目标文件位于文件系统中。这意味着像classpath*:*.xml这样的模式可能无法从jar文件的根目录检索文件,而只能从展开的目录的根目录检索文件。
Spring 从 JDK 的
ClassLoader.getResources() 方法中获取类路径条目,该方法仅对空字符串(表示可能的搜索根目录)返回文件系统位置。Spring 还会评估
URLClassLoader 运行时配置和 jar 文件中的 java.class.path 清单,但这不一定能保证可移植的行为。
|
类路径包的扫描要求类路径中存在相应的目录条目。在使用Ant构建JAR时,请勿激活JAR任务的 在 JDK 9 的模块路径(Jigsaw)上,Spring 的类路径扫描通常按预期工作。 在这里,将资源放入专用目录也是非常推荐的,这可以避免在 JAR 文件根级别搜索时出现的上述可移植性问题。 |
带有 classpath: 个资源的 Ant 风格模式,如果要搜索的根包在多个类路径位置中可用,则不能保证找到匹配的资源。
考虑以下资源位置示例:
com/mycompany/package1/service-context.xml
现在考虑一个类似 Ant 风格的路径,某人可能会用来尝试找到该文件:
classpath:com/mycompany/**/service-context.xml
这样的资源在类路径中可能只存在于一个位置,但当使用如前面示例中的路径来尝试解析它时,解析器会基于getResource("com/mycompany");返回的第一个URL进行操作。如果这个基础包节点存在于多个ClassLoader位置,所需的资源可能不存在于找到的第一个位置。因此,在这种情况下,应该优先使用classpath*:并带有相同的Ant风格模式,这会搜索包含com.mycompany基础包的所有类路径位置:classpath*:com/mycompany/**/service-context.xml。
FileSystemResource 注意事项
一个未连接到 FileSystemApplicationContext 的 FileSystemResource(即当 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")
以下示例也是等价的(尽管它们应该有所不同,因为一个情况是相对的,另一个是绝对的):
-
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")
在实际应用中,如果您需要真正的绝对文件系统路径,应避免使用带有 FileSystemResource 或 FileSystemXmlApplicationContext 的绝对路径,并通过使用 file: URL 前缀强制使用 UrlResource。以下示例显示了如何操作:
-
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")