Class PathMatchingResourcePatternResolver

java.lang.Object
org.springframework.core.io.support.PathMatchingResourcePatternResolver
All Implemented Interfaces:
ResourceLoader, ResourcePatternResolver
Direct Known Subclasses:
ServletContextResourcePatternResolver

public class PathMatchingResourcePatternResolver extends Object implements ResourcePatternResolver
A ResourcePatternResolver implementation that is able to resolve a specified resource location path into one or more matching Resources.

The source path may be a simple path which has a one-to-one mapping to a target Resource, or alternatively may contain the special "classpath*:" prefix and/or internal Ant-style path patterns (matched using Spring's AntPathMatcher utility). Both of the latter are effectively wildcards.

No Wildcards

In the simple case, if the specified location path does not start with the "classpath*:" prefix and does not contain a PathMatcher pattern, this resolver will simply return a single resource via a getResource() call on the underlying ResourceLoader. Examples are real URLs such as "file:C:/context.xml", pseudo-URLs such as "classpath:/context.xml", and simple unprefixed paths such as "/WEB-INF/context.xml". The latter will resolve in a fashion specific to the underlying ResourceLoader (e.g. ServletContextResource for a WebApplicationContext).

Ant-style Patterns

When the path location contains an Ant-style pattern, for example:

 /WEB-INF/*-context.xml
 com/example/**/applicationContext.xml
 file:C:/some/path/*-context.xml
 classpath:com/example/**/applicationContext.xml
the resolver follows a more complex but defined procedure to try to resolve the wildcard. It produces a Resource for the path up to the last non-wildcard segment and obtains a URL from it. If this URL is not a "jar:" URL or container-specific variant (e.g. "zip:" in WebLogic, "wsjar" in WebSphere", etc.), then the root directory of the filesystem associated with the URL is obtained and used to resolve the wildcards by walking the filesystem. In the case of a jar URL, the resolver either gets a java.net.JarURLConnection from it, or manually parses the jar URL, and then traverses the contents of the jar file, to resolve the wildcards.

Implications on Portability

If the specified path is already a file URL (either explicitly, or implicitly because the base ResourceLoader is a filesystem one), then wildcarding is guaranteed to work in a completely portable fashion.

If the specified path is a class path location, then the resolver must obtain the last non-wildcard path segment URL via a Classloader.getResource() call. Since this is just a node of the path (not the file at the end) it is actually undefined (in the ClassLoader Javadocs) exactly what sort of URL is returned in this case. In practice, it is usually a java.io.File representing the directory, where the class path resource resolves to a filesystem location, or a jar URL of some sort, where the class path resource resolves to a jar location. Still, there is a portability concern on this operation.

If a jar URL is obtained for the last non-wildcard segment, the resolver must be able to get a java.net.JarURLConnection from it, or manually parse the jar URL, to be able to walk the contents of the jar and resolve the wildcard. This will work in most environments but will fail in others, and it is strongly recommended that the wildcard resolution of resources coming from jars be thoroughly tested in your specific environment before you rely on it.

classpath*: Prefix

There is special support for retrieving multiple class path resources with the same name, via the "classpath*:" prefix. For example, "classpath*:META-INF/beans.xml" will find all "META-INF/beans.xml" files in the class path, be it in "classes" directories or in JAR files. This is particularly useful for autodetecting config files of the same name at the same location within each jar file. Internally, this happens via a ClassLoader.getResources() call, and is completely portable.

The "classpath*:" prefix can also be combined with a PathMatcher pattern in the rest of the location path — for example, "classpath*:META-INF/*-beans.xml". In this case, the resolution strategy is fairly simple: a ClassLoader.getResources() call is used on the last non-wildcard path segment to get all the matching resources in the class loader hierarchy, and then off each resource the same PathMatcher resolution strategy described above is used for the wildcard sub pattern.

Other Notes

As of Spring Framework 6.0, if getResources(String) is invoked with a location pattern using the "classpath*:" prefix it will first search all modules in the boot layer, excluding system modules. It will then search the class path using ClassLoader APIs as described previously and return the combined results. Consequently, some of the limitations of class path searches may not apply when applications are deployed as modules.

WARNING: Note that "classpath*:" when combined with Ant-style patterns will only work reliably with at least one root directory before the pattern starts, unless the actual target files reside in the file system. This means that a pattern like "classpath*:*.xml" will not retrieve files from the root of jar files but rather only from the root of expanded directories. This originates from a limitation in the JDK's ClassLoader.getResources() method which only returns file system locations for a passed-in empty String (indicating potential roots to search). This ResourcePatternResolver implementation tries to mitigate the jar root lookup limitation through URLClassLoader introspection and "java.class.path" manifest evaluation; however, without portability guarantees.

WARNING: Ant-style patterns with "classpath:" resources are not guaranteed to find matching resources if the base package to search is available in multiple class path locations. This is because a resource such as

   com/example/package1/service-context.xml
may exist in only one class path location, but when a location pattern such as
   classpath:com/example/**/service-context.xml
is used to try to resolve it, the resolver will work off the (first) URL returned by getResource("com/example"). If the com/example base package node exists in multiple class path locations, the actual desired resource may not be present under the com/example base package in the first URL. Therefore, preferably, use "classpath*:" with the same Ant-style pattern in such a case, which will search all class path locations that contain the base package.
Since:
1.0.2
Author:
Juergen Hoeller, Colin Sampaleanu, Marius Bogoevici, Costin Leau, Phillip Webb, Sam Brannen, Sebastien Deleuze, Dave Syer
See Also: