资源

本章介绍了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。

其他方法允许您获取表示资源的实际URLFile对象(如果底层实现兼容并支持该功能)。

Resource接口的一些实现还实现了扩展的WritableResource接口,用于支持向其写入的资源。

Spring自身广泛使用Resource抽象,作为许多方法签名中需要资源的参数类型。在一些Spring API中的其他方法(例如各种ApplicationContext实现的构造函数)接受一个String,在未经修饰或简单形式下用于创建适用于该上下文实现的Resource,或者通过String路径上的特殊前缀,让调用者指定必须创建和使用特定Resource实现。

虽然Resource接口在Spring中被广泛使用,但实际上作为您自己代码中的通用实用类使用非常方便,用于访问资源,即使您的代码不知道或不关心Spring的其他部分。虽然这将您的代码与Spring耦合,但实际上只将其与这一小组实用类耦合,这些类作为URL的更有能力的替代品,并且可以被视为用于此目的的任何其他库的等效物。

资源抽象并不替换功能。它在可能的情况下对其进行包装。例如,UrlResource包装了一个URL并使用包装的URL执行其工作。

内置Resource实现

Spring包含几个内置的Resource实现:

要查看Spring中可用的所有Resource实现的完整列表,请参阅Resource javadoc中的"All Known Implementing Classes"部分。

UrlResource

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

通过显式使用UrlResource构造函数,可以创建一个UrlResource,但通常在调用接受String参数表示路径的API方法时会隐式创建一个UrlResource。对于后一种情况,JavaBeans PropertyEditor最终决定创建哪种类型的Resource。如果路径字符串包含一个众所周知的(对于属性编辑器而言)前缀(例如classpath:),它会为该前缀创建一个适当的专门的Resource。但是,如果它不识别前缀,则假定该字符串是一个标准的URL字符串,并创建一个UrlResource

ClassPathResource

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

如果类路径资源位于文件系统中,此Resource实现支持将其解析为java.io.File,但对于位于jar中且未被展开(由servlet引擎或环境处理)到文件系统中的类路径资源不支持。为了解决这个问题,各种Resource实现始终支持将其解析为java.net.URL

通过显式使用ClassPathResource构造函数,可以创建一个ClassPathResource,但通常在调用接受String参数表示路径的API方法时会隐式创建一个ClassPathResource。对于后一种情况,JavaBeans PropertyEditor识别字符串路径上的特殊前缀classpath:,并在这种情况下创建一个ClassPathResource

FileSystemResource

这是一个用于java.io.File句柄的Resource实现。它还支持java.nio.file.Path句柄,应用Spring的标准基于字符串的路径转换,但通过java.nio.file.Files API执行所有操作。对于纯java.nio.path.Path支持,请改用PathResourceFileSystemResource支持将其解析为FileURL

PathResource

这是一个用于java.nio.file.Path句柄的Resource实现,通过Path API执行所有操作和转换。它支持将其解析为FileURL,还实现了扩展的WritableResource接口。 PathResource实际上是FileSystemResource的纯java.nio.path.Path替代方案,具有不同的createRelative行为。

ServletContextResource

这是一个用于解释相关Web应用程序根目录内部相对路径的ServletContext资源的Resource实现。

它始终支持流访问和URL访问,但仅当Web应用程序归档已展开且资源实际上位于文件系统上时才允许java.io.File访问。它是否已展开并位于文件系统上,或者直接从JAR文件或其他位置(如数据库)访问,实际上取决于Servlet容器。

InputStreamResource

InputStreamResource是给定InputStreamResource实现。仅当没有适用的特定Resource实现时才应使用它。特别是,在可能的情况下,应优先考虑ByteArrayResource或任何基于文件的Resource实现。

与其他Resource实现相反,这是一个已打开资源的描述符。因此,它从isOpen()返回true。如果需要将资源描述符保存在某处,或者需要多次读取流,则不要使用它。

ByteArrayResource

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

它可用于从任何给定的字节数组加载内容,而无需求助于一次性使用的InputStreamResource

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

类似地,您可以通过指定任何标准的java.net.URL前缀来强制使用UrlResource。以下示例使用了filehttps前缀:

  • 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对象的策略:

表1. 资源字符串
前缀 示例 说明

classpath:

classpath:com/myapp/config.xml

从类路径加载。

file:

file:///data/config.xml

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

https:

https://myserver/logo.png

作为URL加载。

(无)

/data/config.xml

取决于底层ApplicationContext

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实用程序进行匹配)。后两者实际上是通配符。

在任何标准ApplicationContext中,默认的ResourceLoader实际上是PathMatchingResourcePatternResolver的一个实例,它实现了ResourcePatternResolver接口。对于ApplicationContext实例本身也是如此,它还实现了ResourcePatternResolver接口,并委托给默认的PathMatchingResourcePatternResolver

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接口的替代方法。传统的constructorbyType自动装配模式(如自动装配协作者中所述)能够为构造函数参数或setter方法参数提供ResourceLoader。要获得更多灵活性(包括能够自动装配字段和多参数方法的能力),请考虑使用基于注解的自动装配功能。在这种情况下,只要字段、构造函数或方法带有@Autowired注解,ResourceLoader就会自动装配到期望ResourceLoader类型的字段、构造函数参数或方法参数中。有关更多信息,请参见使用@Autowired

要加载包含通配符或使用特殊classpath*:资源前缀的资源路径的一个或多个Resource对象,请考虑将一个ResourcePatternResolver实例自动装配到您的应用组件中,而不是ResourceLoader

资源作为依赖

如果bean本身将通过某种动态过程确定并提供资源路径,那么bean可能最好使用ResourceLoaderResourcePatternResolver接口来加载资源。例如,考虑加载某种模板,其中所需的特定资源取决于用户的角色。如果资源是静态的,最好完全消除ResourceLoader接口(或ResourcePatternResolver接口)的使用,让bean公开它需要的Resource属性,并期望将它们注入其中。

使得注入这些属性变得简单的是,所有应用程序上下文都注册并使用一个特殊的JavaBeansPropertyEditor,它可以将String路径转换为Resource对象。例如,以下MyBean类具有一个类型为Resourcetemplate属性。

  • 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,资源将通过ClassPathResourceFileSystemResourceServletContextResource之一加载,具体取决于应用程序上下文的确切类型。

如果需要强制使用特定的Resource类型,可以使用前缀。以下两个示例展示了如何强制使用ClassPathResourceUrlResource(后者用于访问文件系统中的文件):

<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将把字符串转换为要注入到MyBean构造函数中的Resource对象。以下示例演示了如何实现这一点。

  • 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将把模板路径模式转换为可以注入到MyBean构造函数中的Resource对象数组。

  • 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[])

应用上下文和资源路径

This section covers how to create application contexts with resources, including shortcuts that work with XML, how to use wildcards, and other details.

Constructing Application Contexts

An application context constructor (for a specific application context type) generally takes a string or array of strings as the location paths of the resources, such as XML files that make up the definition of the context.

When such a location path does not have a prefix, the specific Resource type built from that path and used to load the bean definitions depends on and is appropriate to the specific application context. For example, consider the following example, which creates a ClassPathXmlApplicationContext:

  • Java

  • Kotlin

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

The bean definitions are loaded from the classpath, because a ClassPathResource is used. However, consider the following example, which creates a FileSystemXmlApplicationContext:

  • Java

  • Kotlin

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

Now the bean definitions are loaded from a filesystem location (in this case, relative to the current working directory).

Note that the use of the special classpath prefix or a standard URL prefix on the location path overrides the default type of Resource created to load the bean definitions. Consider the following example:

  • Java

  • Kotlin

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

Using FileSystemXmlApplicationContext loads the bean definitions from the classpath. However, it is still a FileSystemXmlApplicationContext. If it is subsequently used as a ResourceLoader, any unprefixed paths are still treated as filesystem paths.

Constructing ClassPathXmlApplicationContext Instances — Shortcuts

The ClassPathXmlApplicationContext exposes a number of constructors to enable convenient instantiation. The basic idea is that you can supply merely a string array that contains only the filenames of the XML files themselves (without the leading path information) and also supply a Class. The ClassPathXmlApplicationContext then derives the path information from the supplied class.

Consider the following directory layout:

com/
  example/
    services.xml
    repositories.xml
    MessengerService.class

The following example shows how a ClassPathXmlApplicationContext instance composed of the beans defined in files named services.xml and repositories.xml (which are on the classpath) can be instantiated:

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

See the ClassPathXmlApplicationContext javadoc for details on the various constructors.

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

应用程序上下文构造函数值中的资源路径可以是简单路径(如前面所示),每个路径都与目标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等),则从中获取一个java.io.File并用于通过遍历文件系统来解析通配符。在jar URL的情况下,解析器要么从中获取一个java.net.JarURLConnection,要么手动解析jar URL,然后遍历jar文件的内容以解析通配符。

对可移植性的影响

如果指定的路径已经是file URL(隐式地因为基本ResourceLoader是文件系统的一个或显式地),则通配符保证以完全可移植的方式工作。

如果指定的路径是classpath位置,则解析器必须通过进行Classloader.getResource()调用来获取最后一个非通配符路径段的URL。由于这只是路径的一个节点(而不是最终的文件),在这种情况下返回的URL实际上是未定义的(在ClassLoader javadoc中)。实际上,它始终是代表目录的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(…​)来实现),然后合并以形成最终的应用程序上下文定义。

通配符类路径依赖于底层ClassLoadergetResources()方法。由于大多数应用服务器现在提供自己的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任务的files-only开关。此外,基于某些环境中的安全策略,类路径目录可能不会暴露出来,例如,JDK 1.7.0_45及更高版本的独立应用程序(需要在清单中设置“Trusted-Library”)。请参阅stackoverflow.com/questions/19394570/java-jre-7u45-breaks-classloader-getresources

在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位置中,则所需的资源可能不在找到的第一个位置中。因此,在这种情况下,您应该更喜欢使用具有相同Ant风格模式的classpath*:,该模式搜索包含com.mycompany基本包的所有类路径位置:classpath*:com/mycompany/**/service-context.xml

FileSystemResource 注意事项

一个未附加到FileSystemApplicationContext(也就是说,当FileSystemApplicationContext不是实际的ResourceLoader)的FileSystemResource会按照您的预期处理绝对路径和相对路径。相对路径是相对于当前工作目录,而绝对路径是相对于文件系统的根目录。

然而,出于向后兼容(历史)原因,当FileSystemApplicationContextResourceLoader时,情况会有所改变。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")

实际上,如果您需要真正的绝对文件系统路径,应避免在FileSystemResourceFileSystemXmlApplicationContext中使用绝对路径,并通过使用file: URL前缀强制使用UrlResource。以下示例展示了如何实现:

  • Java

  • Kotlin

// 实际上上下文类型无关紧要,资源将始终是UrlResource
ctx.getResource("file:///some/resource/path/myTemplate.txt");
// 实际上上下文类型无关紧要,资源将始终是UrlResource
ctx.getResource("file:///some/resource/path/myTemplate.txt")
  • Java

  • Kotlin

// 强制此FileSystemXmlApplicationContext通过UrlResource加载其定义
ApplicationContext ctx =
	new FileSystemXmlApplicationContext("file:///conf/context.xml");
// 强制此FileSystemXmlApplicationContext通过UrlResource加载其定义
val ctx = FileSystemXmlApplicationContext("file:///conf/context.xml")