为什么Spring的PathMatchingResourcePatternResolver没有匹配“ *”?

时间:2018-06-28 14:24:53

标签: spring

我正在尝试从zip文件中获取属性文件。我需要使用通配符,因为我要匹配“ my.properties”或“ my_en.properties”。我像这样创建ResourcePatternResolver

ClassLoader loader = MyClass.class.getClassLoader();
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(loader);

当我尝试不使用通配符来检索“ my.properties”文件时,我成功了:

resolver.getResource("file:C:/somePath/a.zip/META-INF/my.properties").exists()

返回true。但是,如果我在文件名中添加通配符,则失败,例如

resolver.getResource("file:C:/somePath/a.zip/META-INF/my*.properties").exists()

返回false。我该怎么做才能匹配并检索两个文件?我正在尝试在Tomcat的Web应用程序中执行此操作。

3 个答案:

答案 0 :(得分:3)

文档尚不清楚,但是getResource方法未在内部使用PathMatcher来解析资源(这意味着不允许使用通配符),请尝试使用getResources(String locationPattern)

例如:

Resource[] resources = resolver.getResources("file:C:/somePath/a.zip/META-INF/my*.properties");

for(Resource resource : resources) {
  // do something for each resource found
}

答案 1 :(得分:0)

官方文档对此进行了解释:

  

没有通配符:

     

在简单情况下,如果指定的位置路径不是以   “ classpath *:”前缀,并且不包含PathMatcher模式,   此解析器将仅通过getResource()返回单个资源   调用基础ResourceLoader。示例是真实的网址,例如   “ file:C:/context.xml”,伪URL(例如“ classpath:/context.xml”),   和简单的无前缀路径,例如“ /WEB-INF/context.xml”。后者   将以特定于基础ResourceLoader的方式解析   (例如,WebApplicationContext的ServletContextResource)

要尝试使用反模式,请查看:

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/io/support/PathMatchingResourcePatternResolver.html

答案 2 :(得分:0)

实际上,如果您看到原始的Spring代码,则可以建议SébastienHelbert getResource和getResources的工作原理有很大不同:

public class PathMatchingResourcePatternResolver implements ResourcePatternResolver {

....
@Override
    public Resource getResource(String location) {
        return getResourceLoader().getResource(location);
    }

    @Override
    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 {
            // Generally only look for a pattern after a prefix here,
            // and on Tomcat only after the "*/" separator for its "war:" protocol.
            int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
                    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)};
            }
        }
    }
...
}

阅读Spring代码很明显,getRersources使用AntPattern和geetResource no。我说对了,因为使用通配符隐含了您想要一个多重结果,而不仅仅是一个结果,获取资源不起作用,因为它并没有接受我是否拥有一个第一个结果的共识,那就是不起作用,因为在多结果的情况下,没有想到为了第一而工作,这只是一种选择。 因此,可以使用getResources()方法实现使用通配符的用例

我希望它可以帮助您采用正确的方法。