0

我有一个打包如下的应用程序:

+EAR
  +WAR
  +ejb.jar
  +lib
     +core.jar
     +plugin1.jar
     +plugin2.jar
     ...

每个“pluginX.jar”在根目录下都包含一个spring 配置文件。当应用程序启动时,core.jar 会尝试加载 spring 配置文件:

String matchString = "classpath*:/./Plugin.*.spring.xml";
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources(matchString);

这适用于 JBoss EAP 5.1,但不适用于 WebSphere 7。

我尝试直接加载资源:

ClassLoader cl = this.getClass().getClassLoader();
log.info("class loader: " + cl.toString());
URL u = cl.getResource("Plugin.1.spring.xml");

并得到了相同的结果,尽管 WebSphere 的日志告诉本地类路径包含“pluginX.jar”:

com.ibm.ws.classloader.CompoundClassLoader@48da48da[app:CG EAR]

本地类路径:/opt/IBM/WAS7/AppServer/profiles/srv01/installedApp/cell01/CG.EAR.ear/lib/pluginX.jar
父级:com.ibm.ws.classloader.ProtectionClassLoader@4c654c65
委托模式:PARENT_LAST

有任何想法吗?

4

3 回答 3

1

我今天在 WebSphere 8.5 上遇到了同样的问题,看起来问题是,ClassLoader.getResources() 返回带有协议“文件”而不是“jar”的 URL,并且在某些情况下不会返回共享库中的 jar 文件为单独的资源 URL,但共享库位置(例如包含 JAR 的文件夹)作为单个资源 URL。这似乎混淆PathMatchingResourcePatternResolver了路上的某个地方。

我解决了

  1. 如果 URL 协议为“file”且扩展名为“.jar”,则覆盖该convertClassLoaderURL方法并显式实例化 JAR 资源,并且
  2. 覆盖doFindPathMatchingFileResources在 JAR 文件中搜索表示目录的资源的方法。
AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext() {

    protected ResourcePatternResolver getResourcePatternResolver() {
        return new ServletContextResourcePatternResolver(this) {

            protected Resource convertClassLoaderURL(URL url) {
                if (url.getProtocol().equals("file") && url.getFile().endsWith(".jar")) {
                    try {
                        return new UrlResource("jar", url + "!/");
                    } catch (final MalformedURLException ex) {
                        //LOG.catching(ex);
                    }
                }
                return new UrlResource(url);
            }

            protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource, String subPattern) throws IOException {
                Set<Resource> matches = super.doFindPathMatchingFileResources(rootDirResource, subPattern);
                try {
                    File rootDir = rootDirResource.getFile();
                    if (rootDir.isDirectory()) {
                        Set<Resource> containedJARs = doFindMatchingFileSystemResources(rootDir, "*.jar");
                        for (Resource jar : containedJARs) {
                            Set<Resource> matchingResourcesFoundInJar = doFindPathMatchingJarResources(convertClassLoaderURL(jar.getURL()), subPattern);
                            matches.addAll(matchingResourcesFoundInJar);
                        }
                    }
                } catch (final IOException ex) {
                    // LOG.catching(ex);
                }
                return matches;
            }

        }

    };

此更改还消除了日志消息:

WARN  org.springframework.core.io.support.PathMatchingResourcePatternResolver:
* Skipping [.m2/repository/org/springframework/spring-webmvc/4.1.2.RELEASE/spring-webmvc-4.1.2.RELEASE.jar] because it does not denote a directory
于 2015-10-05T12:38:36.203 回答
0

这是一个类加载器问题。我建议您尝试为您的 EAR 和 WAR 更改类加载策略。

我们有一个非常相似的部署,我们在 WAS 6 中这样配置:转到 WAS 控制台,访问Enterprise Application => Your App => Class loader并在General 属性集下:

类加载器顺序:“使用应用程序类加载器加载的类”。

War 类加载器策略:“应用程序中每个 WAR 文件的类加载器”。

关于源代码,下面的代码片段更安全,建议在加载资源时避免类加载问题:

Thread.currentThread().getContextClassLoader().getResource("Plugin.1.spring.xml"))

希望能帮助到你 !!

于 2013-07-02T20:34:59.757 回答
0

虽然这适用于 WAS 8:我偶然发现了这个线程,但它可能值得一提

http://www.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.base.doc/ae/rweb_custom_props.html

有这个设置:“ com.ibm.ws.webcontainer.SkipMetaInfResourcesProcessing ”您可能需要将它从您的 websphere 配置中删除(如果有人设置)或将值设置为 false。

于 2016-09-14T17:44:14.943 回答