In the spring configuration file, we often see a configuration path similar to this:
Java code
Classpath:/com/module/**/* SQL. xml
The system automatically loads xml files that comply with the path rules according to the configuration path.
Let us assume that you have implemented the following functions:
What do you do if you load a compliant xml file based on a wildcard path?
Let's take a look at a small example:
Java code
Import java. io. IOException;
Import org. springframework. core. io. Resource;
Import org. springframework. core. io. support. PathMatchingResourcePatternResolver;
Import org. springframework. core. io. support. ResourcePatternResolver;
Public class XMLManager {
Private String location = "classpath: *. xml ";
Public void readFile () throws IOException {
ResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver ();
Resource [] source = resourceLoader. getResources (location );
For (int I = 0; I <source. length; I ++ ){
Resource resource = source [I];
System. out. println (resource. getFilename ());
}
}
Public static void main (String [] args ){
XMLManager m = new XMLManager ();
Try {
M. readFile ();
} Catch (IOException e ){
E. printStackTrace ();
}
}
}
Output result:
Java code
ApplicationContext. xml
Logback. xml
Menu_my.xml
Is it easy?
You only need to call the getResources method of PathMatchingResourcePatternResolver to implement the desired function.
Next, let's take a closer look at spring's source code PathMatchingResourcePatternResolver:
1. getResources Method
Java code
Public Resource [] getResources (String locationPattern) throws IOException {
Assert. notNull (locationPattern, "Location pattern must not be null ");
If (locationPattern. startsWith (CLASSPATH_ALL_URL_PREFIX )){
// A class path resource (multiple resources for same name possible)
If (getPathMatcher (). isPattern (locationPattern. substring (CLASSPATH_ALL_URL_PREFIX.length ()))){
// A class path resource pattern
Return findPathMatchingResources (locationPattern );
}
Else {
// All class path resources with the given name
Return findAllClassPathResources (locationPattern. substring (CLASSPATH_ALL_URL_PREFIX.length ()));
}
}
Else {
// Only look for a pattern after a prefix here
// (To not get fooled by a pattern symbol in a strange prefix ).
Int prefixEnd = locationPattern. indexOf (":") + 1;
If (getPathMatcher (). isPattern (locationPattern. substring (prefixEnd ))){
// A file pattern
Return findPathMatchingResources (locationPattern );
}
Else {
// A single resource with the given name
Return new Resource [] {getResourceLoader (). getResource (locationPattern )};
}
}
}
This method is mainly used to determine whether locationPattern contains wildcards. If it contains wildcards, The findPathMatchingResources method is called. If it does not contain wildcards, it does not need to be parsed.
2. findPathMatchingResources Method
Java code
Protected Resource [] findPathMatchingResources (String locationPattern) throws IOException {
String rootDirPath = determineRootDir (locationPattern );
String subPattern = locationPattern. substring (rootDirPath. length ());
Resource [] rootDirResources = getResources (rootDirPath );
Set <Resource> result = new LinkedHashSet <Resource> (16 );
For (Resource rootDirResource: rootDirResources ){
RootDirResource = resolveRootDirResource (rootDirResource );
If (isJarResource (rootDirResource )){
Result. addAll (doFindPathMatchingJarResources (rootDirResource, subPattern ));
}
Else if (rootDirResource. getURL (). getProtocol (). startsWith (ResourceUtils. URL_PROTOCOL_VFS )){
Result. addAll (VfsResourceMatchingDelegate. findMatchingResources (rootDirResource, subPattern, getPathMatcher ()));
}
Else {
Result. addAll (doFindPathMatchingFileResources (rootDirResource, subPattern ));
}
}
If (logger. isDebugEnabled ()){
Logger. debug ("Resolved location pattern [" + locationPattern + "] to resources" + result );
}
Return result. toArray (new Resource [result. size ()]);
}
Split locationPattern into two parts: rootDirPath and subPattern.
RootDirPath is the root directory path.
SubPattern is a sub-directory path matching rule string.
View All subdirectories in the root directory and obtain all subdirectories.
In the doFindPathMatchingFileResources (rootDirResource, subPattern) method
Then match the subPattern one by one based on the subdirectories.
3. doFindPathMatchingFileResources
Java code
Protected Set <Resource> doFindPathMatchingFileResources (Resource rootDirResource, String subPattern)
Throws IOException {
File rootDir;
Try {
RootDir = rootDirResource. getFile (). getAbsoluteFile ();
}
Catch (IOException ex ){
If (logger. isWarnEnabled ()){
Logger. warn ("Cannot search for matching files underneath" + rootDirResource +
"Because it does not correspond to a directory in the file system", ex );
}
Return Collections. emptySet ();
}
Return doFindMatchingFileSystemResources (rootDir, subPattern );
}
Jump to another method doFindMatchingFileSystemResources:
Java code
Protected Set <Resource> doFindMatchingFileSystemResources (File rootDir, String subPattern) throws IOException {
If (logger. isDebugEnabled ()){
Logger. debug ("Looking for matching resources in directory tree [" + rootDir. getPath () + "]");
}
Set <File> matchingFiles = retrieveMatchingFiles (rootDir, subPattern );
Set <Resource> result = new LinkedHashSet <Resource> (matchingFiles. size ());
For (File file: matchingFiles ){
Result. add (new FileSystemResource (file ));
}
Return result;
}
RetrieveMatchingFiles
Java code
Protected Set <File> retrieveMatchingFiles (File rootDir, String pattern) throws IOException {
If (! RootDir. exists ()){
// Silently skip non-existing directories.
If (logger. isDebugEnabled ()){
Logger. debug ("Skipping [" + rootDir. getAbsolutePath () + "] because it does not exist ");
}
Return Collections. emptySet ();
}
If (! RootDir. isDirectory ()){
// Complain louder if it exists but is no directory.
If (logger. isWarnEnabled ()){
Logger. warn ("Skipping [" + rootDir. getAbsolutePath () + "] because it does not denote a directory ");
}
Return Collections. emptySet ();
}
If (! RootDir. canRead ()){
If (logger. isWarnEnabled ()){
Logger. warn ("Cannot search for matching files underneath directory [" + rootDir. getAbsolutePath () +
"] Because the application is not allowed to read the directory ");
}
Return Collections. emptySet ();
}
String fullPattern = StringUtils. replace (rootDir. getAbsolutePath (), File. separator ,"/");
If (! Pattern. startsWith ("/")){
FullPattern + = "/";
}
FullPattern = fullPattern + StringUtils. replace (pattern, File. separator ,"/");
Set <File> result = new LinkedHashSet <File> (8 );
DoRetrieveMatchingFiles (fullPattern, rootDir, result );
Return result;
}
Call the recursive method:
DoRetrieveMatchingFiles
Java code
Protected void doRetrieveMatchingFiles (String fullPattern, File dir, Set <File> result) throws IOException {
If (logger. isDebugEnabled ()){
Logger. debug ("Searching directory [" + dir. getAbsolutePath () +
"] For files matching pattern [" + fullPattern + "]");
}
File [] dirContents = dir. listFiles ();
If (dirContents = null ){
If (logger. isWarnEnabled ()){
Logger. warn ("cocould not retrieve contents of directory [" + dir. getAbsolutePath () + "]");
}
Return;
}
For (File content: dirContents ){
String currPath = StringUtils. replace (content. getAbsolutePath (), File. separator ,"/");
If (content. isDirectory () & getPathMatcher (). matchStart (fullPattern, currPath + "/")){
If (! Content. canRead ()){
If (logger. isDebugEnabled ()){
Logger. debug ("Skipping subdirectory [" + dir. getAbsolutePath () +
"] Because the application is not allowed to read the directory ");
}
}
Else {
DoRetrieveMatchingFiles (fullPattern, content, result );
}
}
If (getPathMatcher (). match (fullPattern, currPath )){
Result. add (content );
}
}
}
This article is from goodscript"