介绍

Java 的标准类和各种 URL 前缀的标准处理程序, 不幸的是,它们还不足以满足所有对低级资源的访问。为 例如,没有可用于访问 需要从类路径或相对于 类路径获取的资源。虽然可以为专用前缀注册新的处理程序(类似于前缀的现有处理程序,例如 ),但这通常是 相当复杂,界面仍然缺乏一些理想的功能, 例如检查所指向的资源是否存在的方法。java.net.URLURLServletContextURLhttp:URL

界面Resource

Spring的接口位于软件包中 旨在成为一个功能更强大的接口,用于抽象对低级资源的访问。这 以下列表提供了接口的概述。有关更多详细信息,请参阅资源 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():返回指示此资源是否表示句柄 使用开放流。如果 ,则不能多次读取,并且 必须只读取一次,然后关闭以避免资源泄漏。返回 所有常用的资源实现,但 .booleantrueInputStreamfalseInputStreamResource

  • getDescription():返回此资源的说明,用于错误 使用资源时的输出。这通常是完全限定的文件名或 资源的实际 URL。

其他方法允许您获得表示 资源(如果基础实现兼容并支持该实现 功能)。URLFile

该接口的某些实现还实现了扩展的 WritableResource 接口 用于支持写入的资源。Resource

Spring 本身广泛使用抽象,作为 需要资源时的许多方法签名。某些 Spring API 中的其他方法 (例如各种实现的构造函数)采用一种以朴素或简单的形式用于创建适当的 该上下文实现,或者通过路径上的特殊前缀,让 调用方指定必须创建和使用特定的实现。ResourceApplicationContextStringResourceStringResource

虽然该接口在 Spring 和 Spring 中被大量使用,但它实际上是 非常方便地在自己的代码中单独用作通用实用程序类,以便访问 资源,即使你的代码不知道或不关心 Spring 的任何其他部分。 虽然这会将您的代码耦合到 Spring,但它实际上只将其耦合到这一小集合 实用程序类,它可以作为更有能力的替代品,并且可以 被认为等同于您将用于此目的的任何其他库。ResourceURL

抽象不会取代功能。它把它包裹在什么地方 可能。例如,a 包装一个 URL 并使用包装的 URL 来执行其 工作。ResourceUrlResourceURL

内置实现Resource

Spring 包含几个内置实现:Resource

有关 Spring 中可用实现的完整列表,请参阅 资源 javadoc 的“所有已知实现类”部分。Resource

UrlResource

UrlResource包装一个,可用于访问任何对象 通常可通过 URL(例如文件、HTTPS 目标、FTP 目标和 别人。所有 URL 都具有标准化的表示形式,因此适当的 标准化前缀用于指示一种 URL 类型与另一种 URL 类型。这包括访问文件系统路径,通过 HTTPS协议,用于通过FTP访问资源等。java.net.URLStringfile:https:ftp:

A 是由 Java 代码通过显式使用构造函数创建的 但通常是在调用 API 方法时隐式创建的,该方法采用旨在表示路径的参数。对于后一种情况,JavaBeans 最终决定创建哪种类型。如果路径字符串包含 众所周知的(对属性编辑器来说,即)前缀(例如),它创建一个 适用于该前缀。但是,如果它无法识别 前缀,它假定该字符串是标准 URL 字符串,并创建一个 .UrlResourceUrlResourceStringPropertyEditorResourceclasspath:ResourceUrlResource

ClassPathResource

此类表示应从类路径获取的资源。它使用 线程上下文类加载器、给定类加载器或给定的类 加载资源。

此实现支持将类路径解析为 if 资源驻留在文件系统中,但不驻留在 jar 并且尚未扩展(通过 servlet 引擎或任何环境) 到文件系统。为了解决这个问题,各种实现始终支持 分辨率为 .Resourcejava.io.FileResourcejava.net.URL

A 是由 Java 代码通过显式使用构造函数创建的,但通常是在调用 API 方法时隐式创建的,该方法采用用于表示路径的参数。对于后一种情况,JavaBeans 会识别字符串路径上的特殊前缀 ,并且 在这种情况下创建一个。ClassPathResourceClassPathResourceStringPropertyEditorclasspath:ClassPathResource

FileSystemResource

这是句柄的实现。它还支持句柄,应用 Spring 的标准基于字符串的路径 转换,但通过 API 执行所有操作。对于纯基础支持,请改用 。 支持解析为 a 和 .Resourcejava.io.Filejava.nio.file.Pathjava.nio.file.Filesjava.nio.path.PathPathResourceFileSystemResourceFileURL

PathResource

这是句柄的实现,执行所有 通过 API 进行操作和转换。它支持分辨率为 和 作为 和 还实现了扩展接口。 实际上是 with 的纯基替代品 不同的行为。Resourcejava.nio.file.PathPathFileURLWritableResourcePathResourcejava.nio.path.PathFileSystemResourcecreateRelative

ServletContextResource

这是解释 相关 Web 应用程序根目录中的相对路径。ResourceServletContext

它始终支持流访问和 URL 访问,但仅允许访问 当 Web 应用程序存档展开并且资源物理位于 文件系统。无论它是否被扩展并在文件系统上或被访问 直接来自 JAR 或其他地方,如数据库(可以想象)实际上是 依赖于 Servlet 容器。java.io.File

InputStreamResource

an 是给定 的实现。它 仅当没有特定的实现适用时,才应使用。在 particular、preferred 或任何基于文件的实现(如果可能)。InputStreamResourceResourceInputStreamResourceByteArrayResourceResource

与其他实现相比,这是一个描述符 已打开的资源。因此,它从 返回。如果出现以下情况,请勿使用它 您需要将资源描述符保留在某个位置,或者如果您需要读取流 多次。ResourcetrueisOpen()

ByteArrayResource

这是给定字节数组的实现。它为给定的字节数组创建一个。ResourceByteArrayInputStream

它对于从任何给定的字节数组加载内容很有用,而不必求助于 一次性使用。InputStreamResource

界面ResourceLoader

该接口旨在由可以返回的对象实现 (即加载)实例。以下列表显示了接口定义:ResourceLoaderResourceResourceLoader

public interface ResourceLoader {

	Resource getResource(String location);

	ClassLoader getClassLoader();
}

所有应用程序上下文都实现该接口。因此,所有 应用程序上下文可用于获取实例。ResourceLoaderResource

调用特定应用程序上下文和位置路径时 指定没有特定的前缀,则返回的类型是 适用于该特定应用程序上下文。例如,假设如下 针对实例运行代码片段:getResource()ResourceClassPathXmlApplicationContext

  • Java

  • Kotlin

Resource template = ctx.getResource("some/resource/path/myTemplate.txt");
val template = ctx.getResource("some/resource/path/myTemplate.txt")

针对 ,该代码返回 。如果 对实例运行相同的方法,它将 返回一个 .对于 ,它将返回 a 。同样,它将为每个上下文返回适当的对象。ClassPathXmlApplicationContextClassPathResourceFileSystemXmlApplicationContextFileSystemResourceWebApplicationContextServletContextResource

因此,您可以以适合特定应用程序的方式加载资源 上下文。

另一方面,你也可以强制使用,不管 应用程序上下文类型,通过指定特殊前缀,如下所示 示例显示:ClassPathResourceclasspath:

  • Java

  • Kotlin

Resource template = ctx.getResource("classpath:some/resource/path/myTemplate.txt");
val template = ctx.getResource("classpath:some/resource/path/myTemplate.txt")

同样,您可以通过指定任何标准前缀来强制使用 a。以下示例使用 and 前缀: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

表 1.资源字符串
前缀 解释

类路径:

classpath:com/myapp/config.xml

从类路径加载。

文件:

file:///data/config.xml

从文件系统加载为。另请参阅 FileSystemResource 注意事项URL

https:

https://myserver/logo.png

加载为 .URL

(无)

/data/config.xml

取决于基础 .ApplicationContext

界面ResourcePatternResolver

该接口是接口的扩展 它定义了用于解析位置模式的策略(例如,Ant 样式的路径 pattern) 到对象中。ResourcePatternResolverResourceLoaderResource

public interface ResourcePatternResolver extends ResourceLoader {

	String CLASSPATH_ALL_URL_PREFIX = "classpath*:";

	Resource[] getResources(String locationPattern) throws IOException;
}

从上面可以看出,这个接口还定义了一个特殊的资源前缀 对于类路径中的所有匹配资源。请注意,资源位置是 在本例中,应为不带占位符的路径,例如 .JAR 文件或类路径中的不同目录可以 包含具有相同路径和相同名称的多个文件。有关更多详细信息,请参阅应用程序上下文构造函数资源路径中的通配符及其子部分 在带有资源前缀的通配符支持上。classpath*:classpath*:/config/beans.xmlclasspath*:

可以检查传入(例如,通过 ResourceLoaderAware 语义提供的传入)是否 它也实现了这个扩展接口。ResourceLoader

PathMatchingResourcePatternResolver是可用的独立实现 在 an 之外,也用于 for 填充 Bean 属性。 能够 将指定的资源位置路径解析为一个或多个匹配对象。 源路径可以是具有到目标的一对一映射的简单路径,也可以包含特殊前缀和/或内部 蚂蚁风格的正则表达式(使用 Spring 的实用程序进行匹配)。后者都是有效的 通配符。ApplicationContextResourceArrayPropertyEditorResource[]PathMatchingResourcePatternResolverResourceResourceclasspath*:org.springframework.util.AntPathMatcher

任何标准中的默认值实际上是一个实例 其中实现接口。实例本身也是如此,它也 实现接口并委托给默认值。ResourceLoaderApplicationContextPathMatchingResourcePatternResolverResourcePatternResolverApplicationContextResourcePatternResolverPathMatchingResourcePatternResolver

界面ResourceLoaderAware

该接口是一个特殊的回调接口,用于识别 希望提供参考的组件。以下列表 显示接口的定义:ResourceLoaderAwareResourceLoaderResourceLoaderAware

public interface ResourceLoaderAware {

	void setResourceLoader(ResourceLoader resourceLoader);
}

当类实现并部署到应用程序上下文中时 (作为 Spring 管理的 bean),它被应用程序识别为 上下文。然后,应用程序上下文调用 , 提供自身作为参数(请记住,Spring 中的所有应用程序上下文都实现了 接口)。ResourceLoaderAwareResourceLoaderAwaresetResourceLoader(ResourceLoader)ResourceLoader

由于 an 是 ,因此 bean 也可以实现接口,并直接使用提供的应用程序上下文来 加载资源。但是,一般来说,如果这就是您所需要的,最好使用专用界面。代码将仅与资源加载耦合 接口(可以被认为是一个实用程序接口),而不是整个Spring接口。ApplicationContextResourceLoaderApplicationContextAwareResourceLoaderApplicationContext

在应用程序组件中,您还可以依赖 as 的自动接线 实现接口的替代方法。传统模式和自动接线模式(如自动接线协作者中所述) 能够为 构造函数参数或 setter 方法参数。为了获得更大的灵活性(包括能够 autowire 字段和多参数方法),考虑使用基于注释的 自动接线功能。在这种情况下,自动连接到一个字段, 构造函数参数,或要求类型为 long 的方法参数 因为所讨论的字段、构造函数或方法带有注释。 有关详细信息,请参阅使用 @AutowiredResourceLoaderResourceLoaderAwareconstructorbyTypeResourceLoaderResourceLoaderResourceLoader@Autowired

为包含通配符的资源路径加载一个或多个对象 或者使用特殊的资源前缀,请考虑将 ResourcePatternResolver 的实例自动连接到 应用程序组件,而不是 .Resourceclasspath*:ResourceLoader

作为依赖关系的资源

如果 Bean 本身要通过某种方式确定和提供资源路径 在动态过程中,Bean 使用 OR 接口来加载资源可能是有意义的。例如,考虑加载 某种模板,其中所需的特定资源取决于 用户的角色。如果资源是静态的,则完全消除接口(或接口)的使用是有意义的,将 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 配置文件中,可以使用简单的 该资源的字符串,如以下示例所示:template

<bean id="myBean" class="example.MyBean">
	<property name="template" value="some/resource/path/myTemplate.txt"/>
</bean>

请注意,资源路径没有前缀。因此,由于应用程序上下文 本身将用作 ,资源通过 、 a 或 a 加载 ,具体取决于 应用程序上下文的确切类型。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)。春天会 以字符串形式检索模板路径的值,并带有特殊遗嘱 将字符串转换为要注入到构造函数中的对象。 下面的示例演示了如何实现此目的。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)

如果我们想支持在同一路径下发现的多个模板 类路径中的位置(例如,类路径中的多个 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 定义是从类路径加载的,因为 使用。但是,请考虑以下示例,该示例将创建一个:ClassPathResourceFileSystemXmlApplicationContext

  • Java

  • Kotlin

ApplicationContext ctx =
	new FileSystemXmlApplicationContext("conf/appContext.xml");
val ctx = FileSystemXmlApplicationContext("conf/appContext.xml")

现在,Bean 定义是从文件系统位置加载的(在本例中,相对于 当前工作目录)。

请注意,在 位置路径覆盖为加载 Bean 而创建的缺省类型 定义。请看以下示例:classpathResource

  • Java

  • Kotlin

ApplicationContext ctx =
	new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
val ctx = FileSystemXmlApplicationContext("classpath:conf/appContext.xml")

using 从类路径加载 Bean 定义。 但是,它仍然是一个.如果它随后被用作 ,则任何不带前缀的路径仍被视为文件系统路径。FileSystemXmlApplicationContextFileSystemXmlApplicationContextResourceLoader

构造实例 — 快捷方式ClassPathXmlApplicationContext

公开了许多构造函数,以启用 方便的实例化。其基本思想是,您可以只提供一个字符串数组 仅包含 XML 文件本身的文件名(不带前导路径) 信息),并提供 .然后派生 所提供类中的路径信息。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。

应用程序上下文构造函数资源路径中的通配符

应用程序上下文构造函数值中的资源路径可以是简单路径(如 如前所示),其中每个都具有与目标的一对一映射,或者, 或者,可以包含特殊前缀或内部 Ant 样式的模式 (使用 Spring 的实用程序进行匹配)。后者都是有效的 通配符。Resourceclasspath*:PathMatcher

此机制的一个用途是当您需要执行组件样式的应用程序组装时。都 组件可以上下文定义片段发布到已知位置路径,并且 当使用以 为前缀的相同路径创建最终应用程序上下文时,将自动拾取所有组件片段。classpath*:

请注意,此通配符特定于应用程序上下文中资源路径的使用 构造函数(或者直接使用实用程序类层次结构时)和 is 在施工时解决。它与类型本身无关。 不能使用前缀构造实际的 ,因为 一个资源一次只指向一个资源。PathMatcherResourceclasspath*:Resource

蚂蚁风格的图案

路径位置可以包含 Ant 样式的模式,如以下示例所示:

/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml

当路径位置包含 Ant 样式模式时,解析器将遵循更复杂的模式 尝试解析通配符的过程。它为路径生成一个 最后一个非通配符段,并从中获取 URL。如果此 URL 不是 URL,或者 特定于容器的变体(例如在 WebLogic、WebSphere 等中), a 是从中获取的,用于通过遍历 文件系统。对于 jar URL,解析器要么从中获取 a,要么手动解析 jar URL,然后遍历 用于解析通配符的 JAR 文件的内容。Resourcejar:zip:wsjarjava.io.Filejava.net.JarURLConnection

对可移植性的影响

如果指定的路径已经是 URL(隐式地,因为基是文件系统 URL 或显式),则保证通配符 以完全便携的方式工作。fileResourceLoader

如果指定的路径是位置,则解析器必须获取最后一个 通过拨打非通配符路径段 URL。由于这个 只是路径的一个节点(不是末尾的文件),实际上(在 javadoc 中)在这种情况下返回什么样的 URL 是未定义的。在实践中, 它始终是一个表示目录(其中类路径资源 解析为文件系统位置)或某种 jar URL(其中类路径资源 解析为 jar 位置)。尽管如此,此操作仍存在可移植性问题。classpathClassloader.getResource()ClassLoaderjava.io.File

如果获取了最后一个非通配符段的 jar URL,则解析器必须能够 从中获取或手动解析 jar URL,以便能够 遍历 jar 的内容并解析通配符。这在大多数环境中都有效 但在其他情况下失败,我们强烈建议对资源进行通配符解析 来自罐子 在你依赖它之前,要在你的特定环境中进行彻底的测试。java.net.JarURLConnection

前缀classpath*:

在构造基于 XML 的应用程序上下文时,位置字符串可以使用 特殊前缀,如以下示例所示:classpath*:

  • Java

  • Kotlin

ApplicationContext ctx =
	new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
val ctx = ClassPathXmlApplicationContext("classpath*:conf/appContext.xml")

此特殊前缀指定与给定名称匹配的所有类路径资源 必须获得(在内部,这基本上是通过调用 )然后合并以形成最终应用程序 上下文定义。ClassLoader.getResources(…​)

通配符类路径依赖于基础 .由于现在大多数应用程序服务器都提供自己的实现,因此行为可能会有所不同,尤其是在处理 jar 文件时。一个 检查是否有效的简单测试是使用 从 在类路径上的 jar 中:.尝试此测试 具有相同名称但位于两个不同位置的文件(例如,文件) 具有相同的名称和相同的路径,但在类路径上的不同 jar 中。如果 返回不适当的结果,请查看应用程序服务器文档的设置 这可能会影响行为。getResources()ClassLoaderClassLoaderclasspath*ClassLoadergetClass().getClassLoader().getResources("<someFileInsideTheJar>")ClassLoader

您还可以将前缀与 位置路径的其余部分(例如,)。在这个 案例,解决策略相当简单:调用是 用于最后一个非通配符路径段,以获取 类加载器层次结构,然后,关闭每个资源,相同的分辨率 前面描述的策略用于通配符子路径。classpath*:PathMatcherclasspath*:META-INF/*-beans.xmlClassLoader.getResources()PathMatcher

与通配符有关的其他说明

请注意,当与 Ant 样式模式结合使用时,仅有效 在模式开始之前,至少有一个根目录,除非实际 目标文件驻留在文件系统中。这意味着 这样的模式可能不会从 jar 文件的根目录中检索文件,而只能从 jar 文件的根目录中检索文件 从扩展目录的根目录。classpath*:classpath*:*.xml

Spring 检索类路径条目的能力源于 JDK 的方法,该方法仅返回 空字符串(指示要搜索的潜在根)。Spring 评估 jar 文件中的运行时配置和清单 也是如此,但这并不能保证会导致可移植行为。ClassLoader.getResources()URLClassLoaderjava.class.path

类路径包的扫描需要存在相应的目录 类路径中的条目。使用 Ant 构建 JAR 时,不要激活 JAR 任务的 Switch。此外,基于安全性,类路径目录可能不会公开 某些环境中的策略 — 例如,JDK 1.7.0_45 上的独立应用程序 及更高版本(这需要在清单中设置“Trusted-Library”。见 stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources)。files-only

在 JDK 9 的模块路径 (Jigsaw) 上,Spring 的类路径扫描通常按预期工作。 在这里,也强烈建议将资源放入专用目录中, 通过搜索 JAR 文件根级别避免了上述可移植性问题。

带有资源的蚂蚁式模式不保证找到匹配项 资源(如果要搜索的根包在多个类路径位置可用)。 请考虑以下资源位置示例:classpath:

com/mycompany/package1/service-context.xml

现在考虑一个 Ant 样式的路径,有人可能会用它来尝试查找该文件:

classpath:com/mycompany/**/service-context.xml

这样的资源可能只存在于类路径中的一个位置,但是当路径如 前面的示例用于尝试解决它,解析器将 (第一个) 返回的 URL。如果此基础包节点存在于 多个位置,所需的资源可能不存在第一个位置 找到位置。因此,在这种情况下,您应该更愿意使用 相同的 Ant 样式模式,它搜索包含基本包的所有类路径位置: .getResource("com/mycompany");ClassLoaderclasspath*:com.mycompanyclasspath*:com/mycompany/**/service-context.xml

FileSystemResource警告

未附加到 a 的 A (that 是,当 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")

以下示例也是等效的(即使它们不同是有意义的,作为一个 大小写是相对的,另一个是绝对的):

  • 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")

在实践中,如果您需要真正的绝对文件系统路径,则应避免使用 具有 或 和 的绝对路径 使用 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")