Browse Source

Polish Resources section of the reference manual

See gh-26447
pull/26556/head
Sam Brannen 4 years ago
parent
commit
ff43731347
  1. 146
      src/docs/asciidoc/core/core-resources.adoc

146
src/docs/asciidoc/core/core-resources.adoc

@ -127,15 +127,15 @@ that context implementation or, via special prefixes on the `String` path, let t
caller specify that a specific `Resource` implementation must be created and used. caller specify that a specific `Resource` implementation must be created and used.
While the `Resource` interface is used a lot with Spring and by Spring, it is actually While the `Resource` interface is used a lot with Spring and by Spring, it is actually
very useful to use as a general utility class by itself in your own code, for access to very convenient to use as a general utility class by itself in your own code, for access
resources, even when your code does not know or care about any other parts of Spring. to resources, even when your code does not know or care about any other parts of Spring.
While this couples your code to Spring, it really only couples it to this small set of While this couples your code to Spring, it really only couples it to this small set of
utility classes, which serve as a more capable replacement for `URL` and can be utility classes, which serves as a more capable replacement for `URL` and can be
considered equivalent to any other library you would use for this purpose. considered equivalent to any other library you would use for this purpose.
NOTE: The `Resource` abstraction does not replace functionality. NOTE: The `Resource` abstraction does not replace functionality. It wraps it where
It wraps it where possible. For example, a `UrlResource` wraps a URL and uses the possible. For example, a `UrlResource` wraps a URL and uses the wrapped `URL` to do its
wrapped `URL` to do its work. work.
@ -158,20 +158,19 @@ Spring includes the following `Resource` implementations:
=== `UrlResource` === `UrlResource`
`UrlResource` wraps a `java.net.URL` and can be used to access any object that is `UrlResource` wraps a `java.net.URL` and can be used to access any object that is
normally accessible with a URL, such as files, an HTTP target, an FTP target, and others. All normally accessible with a URL, such as files, an HTTPS target, an FTP target, and
URLs have a standardized `String` representation, such that appropriate standardized others. All URLs have a standardized `String` representation, such that appropriate
prefixes are used to indicate one URL type from another. This includes `file:` for standardized prefixes are used to indicate one URL type from another. This includes
accessing filesystem paths, `http:` for accessing resources through the HTTP protocol, `file:` for accessing filesystem paths, `https:` for accessing resources through the
`ftp:` for accessing resources through FTP, and others. HTTPS protocol, `ftp:` for accessing resources through FTP, and others.
A `UrlResource` is created by Java code by explicitly using the `UrlResource` constructor A `UrlResource` is created by Java code by explicitly using the `UrlResource` constructor
but is often created implicitly when you call an API method that takes a `String` but is often created implicitly when you call an API method that takes a `String`
argument meant to represent a path. For the latter case, a JavaBeans argument meant to represent a path. For the latter case, a JavaBeans `PropertyEditor`
`PropertyEditor` ultimately decides which type of `Resource` to create. If the path ultimately decides which type of `Resource` to create. If the path string contains a
string contains well-known (to it, that is) prefix (such as `classpath:`), it well-known (to property editor, that is) prefix (such as `classpath:`), it creates an
creates an appropriate specialized `Resource` for that prefix. However, if it does not appropriate specialized `Resource` for that prefix. However, if it does not recognize the
recognize the prefix, it assume the string is a standard URL string and prefix, it assumes the string is a standard URL string and creates a `UrlResource`.
creates a `UrlResource`.
@ -182,7 +181,7 @@ This class represents a resource that should be obtained from the classpath. It
either the thread context class loader, a given class loader, or a given class for either the thread context class loader, a given class loader, or a given class for
loading resources. loading resources.
This `Resource` implementation supports resolution as `java.io.File` if the class path This `Resource` implementation supports resolution as a `java.io.File` if the class path
resource resides in the file system but not for classpath resources that reside in a resource resides in the file system but not for classpath resources that reside in a
jar and have not been expanded (by the servlet engine or whatever the environment is) jar and have not been expanded (by the servlet engine or whatever the environment is)
to the filesystem. To address this, the various `Resource` implementations always support to the filesystem. To address this, the various `Resource` implementations always support
@ -221,14 +220,15 @@ dependent on the Servlet container.
[[resources-implementations-inputstreamresource]] [[resources-implementations-inputstreamresource]]
=== `InputStreamResource` === `InputStreamResource`
An `InputStreamResource` is a `Resource` implementation for a given `InputStream`. It should be used only if no An `InputStreamResource` is a `Resource` implementation for a given `InputStream`. It
specific `Resource` implementation is applicable. In particular, prefer should be used only if no specific `Resource` implementation is applicable. In
`ByteArrayResource` or any of the file-based `Resource` implementations where possible. particular, prefer `ByteArrayResource` or any of the file-based `Resource`
implementations where possible.
In contrast to other `Resource` implementations, this is a descriptor for an already-opened In contrast to other `Resource` implementations, this is a descriptor for an
resource. Therefore, it returns `true` from `isOpen()`. Do not use it if you need already-opened resource. Therefore, it returns `true` from `isOpen()`. Do not use it if
to keep the resource descriptor somewhere or if you need to read a stream multiple you need to keep the resource descriptor somewhere or if you need to read a stream
times. multiple times.
@ -256,15 +256,19 @@ interface definition:
public interface ResourceLoader { public interface ResourceLoader {
Resource getResource(String location); Resource getResource(String location);
ClassLoader getClassLoader();
} }
---- ----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
interface ResourceLoader { interface ResourceLoader {
fun getResource(location: String): Resource
fun getResource(location: String): Resource fun getClassLoader(): ClassLoader
} }
---- ----
All application contexts implement the `ResourceLoader` interface. Therefore, all All application contexts implement the `ResourceLoader` interface. Therefore, all
@ -286,9 +290,9 @@ snippet of code was run against a `ClassPathXmlApplicationContext` instance:
val template = ctx.getResource("some/resource/path/myTemplate.txt") val template = ctx.getResource("some/resource/path/myTemplate.txt")
---- ----
Against a `ClassPathXmlApplicationContext`, that code returns a `ClassPathResource`. If the same method were run Against a `ClassPathXmlApplicationContext`, that code returns a `ClassPathResource`. If
against a `FileSystemXmlApplicationContext` instance, it would return a the same method were run against a `FileSystemXmlApplicationContext` instance, it would
`FileSystemResource`. For a `WebApplicationContext`, it would return a return a `FileSystemResource`. For a `WebApplicationContext`, it would return a
`ServletContextResource`. It would similarly return appropriate objects for each context. `ServletContextResource`. It would similarly return appropriate objects for each context.
As a result, you can load resources in a fashion appropriate to the particular application As a result, you can load resources in a fashion appropriate to the particular application
@ -310,8 +314,7 @@ example shows:
---- ----
Similarly, you can force a `UrlResource` to be used by specifying any of the standard Similarly, you can force a `UrlResource` to be used by specifying any of the standard
`java.net.URL` prefixes. The following pair of examples use the `file` and `http` `java.net.URL` prefixes. The following examples use the `file` and `https` prefixes:
prefixes:
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java .Java
@ -335,7 +338,8 @@ prefixes:
val template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt") val template = ctx.getResource("https://myhost.com/resource/path/myTemplate.txt")
---- ----
The following table summarizes the strategy for converting `String` objects to `Resource` objects: The following table summarizes the strategy for converting `String` objects to `Resource`
objects:
[[resources-resource-strings]] [[resources-resource-strings]]
.Resource strings .Resource strings
@ -350,7 +354,7 @@ The following table summarizes the strategy for converting `String` objects to `
| `file:///data/config.xml` | `file:///data/config.xml`
| Loaded as a `URL` from the filesystem. See also <<resources-filesystemresource-caveats>>. | Loaded as a `URL` from the filesystem. See also <<resources-filesystemresource-caveats>>.
| http: | https:
| `https://myserver/logo.png` | `https://myserver/logo.png`
| Loaded as a `URL`. | Loaded as a `URL`.
@ -366,8 +370,8 @@ The following table summarizes the strategy for converting `String` objects to `
== The `ResourceLoaderAware` interface == The `ResourceLoaderAware` interface
The `ResourceLoaderAware` interface is a special callback interface which identifies The `ResourceLoaderAware` interface is a special callback interface which identifies
components that expect to be provided with a `ResourceLoader` reference. The following components that expect to be provided a `ResourceLoader` reference. The following listing
listing shows the definition of the `ResourceLoaderAware` interface: shows the definition of the `ResourceLoaderAware` interface:
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java .Java
@ -400,7 +404,7 @@ interface (which can be considered a utility interface) and not to the whole Spr
`ApplicationContext` interface. `ApplicationContext` interface.
In application components, you may also rely upon autowiring of the `ResourceLoader` as In application components, you may also rely upon autowiring of the `ResourceLoader` as
an alternative to implementing the `ResourceLoaderAware` interface. The "`traditional`" an alternative to implementing the `ResourceLoaderAware` interface. The _traditional_
`constructor` and `byType` autowiring modes (as described in <<beans-factory-autowire>>) `constructor` and `byType` autowiring modes (as described in <<beans-factory-autowire>>)
are capable of providing a `ResourceLoader` for either a constructor argument or a are capable of providing a `ResourceLoader` for either a constructor argument or a
setter method parameter, respectively. For more flexibility (including the ability to setter method parameter, respectively. For more flexibility (including the ability to
@ -507,9 +511,9 @@ used. However, consider the following example, which creates a `FileSystemXmlApp
Now the bean definition is loaded from a filesystem location (in this case, relative to Now the bean definition is loaded from a filesystem location (in this case, relative to
the current working directory). the current working directory).
Note that the use of the special classpath prefix or a standard URL prefix on the 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 location path overrides the default type of `Resource` created to load the definition.
definition. Consider the following example: Consider the following example:
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java .Java
@ -523,9 +527,9 @@ definition. Consider the following example:
val ctx = 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 Using `FileSystemXmlApplicationContext` loads the bean definitions from the classpath.
`FileSystemXmlApplicationContext`. If it is subsequently used as a `ResourceLoader`, any However, it is still a `FileSystemXmlApplicationContext`. If it is subsequently used as a
unprefixed paths are still treated as filesystem paths. `ResourceLoader`, any unprefixed paths are still treated as filesystem paths.
[[resources-app-ctx-classpathxml]] [[resources-app-ctx-classpathxml]]
@ -534,33 +538,34 @@ unprefixed paths are still treated as filesystem paths.
The `ClassPathXmlApplicationContext` exposes a number of constructors to enable The `ClassPathXmlApplicationContext` exposes a number of constructors to enable
convenient instantiation. The basic idea is that you can supply merely a string array 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 that contains only the filenames of the XML files themselves (without the leading path
information) and also supplies a `Class`. The `ClassPathXmlApplicationContext` information) and also supply a `Class`. The `ClassPathXmlApplicationContext` then derives
then derives the path information from the supplied class. the path information from the supplied class.
Consider the following directory layout: Consider the following directory layout:
[literal,subs="verbatim,quotes"] [literal,subs="verbatim,quotes"]
---- ----
com/ com/
foo/ example/
services.xml services.xml
daos.xml repositories.xml
MessengerService.class MessengerService.class
---- ----
The following example shows how a `ClassPathXmlApplicationContext` instance composed of the beans defined in The following example shows how a `ClassPathXmlApplicationContext` instance composed of
files named `services.xml` and `daos.xml` (which are on the classpath) can be instantiated: the beans defined in files named `services.xml` and `repositories.xml` (which are on the
classpath) can be instantiated:
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java .Java
---- ----
ApplicationContext ctx = new ClassPathXmlApplicationContext( ApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {"services.xml", "daos.xml"}, MessengerService.class); new String[] {"services.xml", "repositories.xml"}, MessengerService.class);
---- ----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
---- ----
val ctx = ClassPathXmlApplicationContext(arrayOf("services.xml", "daos.xml"), MessengerService::class.java) val ctx = ClassPathXmlApplicationContext(arrayOf("services.xml", "repositories.xml"), MessengerService::class.java)
---- ----
See the {api-spring-framework}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`] See the {api-spring-framework}/context/support/ClassPathXmlApplicationContext.html[`ClassPathXmlApplicationContext`]
@ -572,13 +577,13 @@ javadoc for details on the various constructors.
=== Wildcards in Application Context Constructor Resource Paths === Wildcards in Application Context Constructor Resource Paths
The resource paths in application context constructor values may be simple paths (as The resource paths in application context constructor values may be simple paths (as
shown earlier), each of which has a one-to-one mapping to a target `Resource` or, alternately, may shown earlier), each of which has a one-to-one mapping to a target `Resource` or,
contain the special "classpath*:" prefix or internal Ant-style regular expressions alternately, may contain the special "classpath*:" prefix or internal Ant-style patterns
(matched by using Spring's `PathMatcher` utility). Both of the latter are effectively (matched by using Spring's `PathMatcher` utility). Both of the latter are effectively
wildcards. wildcards.
One use for this mechanism is when you need to do component-style application assembly. All One use for this mechanism is when you need to do component-style application assembly. All
components can 'publish' context definition fragments to a well-known location path, and, components can _publish_ context definition fragments to a well-known location path, and,
when the final application context is created using the same path prefixed with when the final application context is created using the same path prefixed with
`classpath*:`, all component fragments are automatically picked up. `classpath*:`, all component fragments are automatically picked up.
@ -602,14 +607,14 @@ file:C:/some/path/\*-context.xml
classpath:com/mycompany/**/applicationContext.xml classpath:com/mycompany/**/applicationContext.xml
---- ----
When the path location contains an Ant-style pattern, the resolver follows a more complex procedure to try to resolve the When the path location contains an Ant-style pattern, the resolver follows a more complex
wildcard. It produces a `Resource` for the path up to the last non-wildcard segment and procedure to try to resolve the wildcard. It produces a `Resource` for the path up to the
obtains a URL from it. If this URL is not a `jar:` URL or container-specific variant last non-wildcard segment and obtains a URL from it. If this URL is not a `jar:` URL or
(such as `zip:` in WebLogic, `wsjar` in WebSphere, and so on), a `java.io.File` is container-specific variant (such as `zip:` in WebLogic, `wsjar` in WebSphere, and so on),
obtained from it and used to resolve the wildcard by traversing the filesystem. In the a `java.io.File` is obtained from it and used to resolve the wildcard by traversing the
case of a jar URL, the resolver either gets a `java.net.JarURLConnection` from it or filesystem. In the case of a jar URL, the resolver either gets a
manually parses the jar URL and then traverses the contents of the jar file to resolve `java.net.JarURLConnection` from it or manually parses the jar URL and then traverses the
the wildcards. contents of the jar file to resolve the wildcards.
[[resources-app-ctx-portability]] [[resources-app-ctx-portability]]
===== Implications on Portability ===== Implications on Portability
@ -657,14 +662,15 @@ must be obtained (internally, this essentially happens through a call to
context definition. context definition.
NOTE: The wildcard classpath relies on the `getResources()` method of the underlying NOTE: The wildcard classpath relies on the `getResources()` method of the underlying
classloader. As most application servers nowadays supply their own classloader `ClassLoader`. As most application servers nowadays supply their own `ClassLoader`
implementation, the behavior might differ, especially when dealing with jar files. A implementation, the behavior might differ, especially when dealing with jar files. A
simple test to check if `classpath*` works is to use the classloader to load a file from simple test to check if `classpath*` works is to use the `ClassLoader` to load a file from
within a jar on the classpath: within a jar on the classpath:
`getClass().getClassLoader().getResources("<someFileInsideTheJar>")`. Try this test with `getClass().getClassLoader().getResources("<someFileInsideTheJar>")`. Try this test with
files that have the same name but are placed inside two different locations. In case an files that have the same name but reside in two different locations -- for example, files
inappropriate result is returned, check the application server documentation for with the same name and same path but in different jars on the classpath. In case an
settings that might affect the classloader behavior. inappropriate result is returned, check the application server documentation for settings
that might affect the `ClassLoader` behavior.
You can also combine the `classpath*:` prefix with a `PathMatcher` pattern in the You can also combine the `classpath*:` prefix with a `PathMatcher` pattern in the
rest of the location path (for example, `classpath*:META-INF/*-beans.xml`). In this rest of the location path (for example, `classpath*:META-INF/*-beans.xml`). In this
@ -692,7 +698,7 @@ as well, but this is not guaranteed to lead to portable behavior.
[NOTE] [NOTE]
==== ====
The scanning of classpath packages requires the presence of corresponding directory The scanning of classpath packages requires the presence of corresponding directory
entries in the classpath. When you build JARs with Ant, do not activate the files-only entries in the classpath. When you build JARs with Ant, do not activate the `files-only`
switch of the JAR task. Also, classpath directories may not get exposed based on security switch of the JAR task. Also, classpath directories may not get exposed based on security
policies in some environments -- for example, stand-alone applications on JDK 1.7.0_45 policies in some environments -- for example, stand-alone applications on JDK 1.7.0_45
and higher (which requires 'Trusted-Library' to be set up in your manifests. See and higher (which requires 'Trusted-Library' to be set up in your manifests. See
@ -722,7 +728,7 @@ classpath:com/mycompany/**/service-context.xml
Such a resource may be in only one location, but when a path such as the preceding example Such a resource may be in only one location, but when a path such as the preceding example
is used to try to resolve it, the resolver works off the (first) URL returned by is used to try to resolve it, the resolver works off the (first) URL returned by
`getResource("com/mycompany");`. If this base package node exists in multiple `getResource("com/mycompany");`. If this base package node exists in multiple
classloader locations, the actual end resource may not be there. Therefore, in such a case `ClassLoader` locations, the actual end resource may not be there. Therefore, in such a case
you should prefer using `classpath*:` with the same Ant-style pattern, which you should prefer using `classpath*:` with the same Ant-style pattern, which
searches all class path locations that contain the root package. searches all class path locations that contain the root package.

Loading…
Cancel
Save