tomcat 部署 war 中的资源包未按预期工作

Resourcebundles in tomcat deployment war not working as expected

我遇到了一个与加载资源包有关的奇怪问题。经过一些调试后,我能够找出问题的原因,因为资源包正在按预期顺序加载。但是,我查询是什么原因造成的。 我有如下命名的资源包。

core_cs.properties
core_de.properties
core_en_GB.properties
core_en_US.properties
core_en.properties
core_fr.properties

当资源包通过spring配置加载时,基本名称应该是

../core
../core_en

但是,结果是

../core_en
../core

因此,每个语言环境都显示来自 core_en 资源包的翻译值。 在项目中,我在我的 Web 项目中添加 core.jar 作为依赖项。

当前行为。

found == META-INF/resourcebundles/core_en for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en_GB.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_cs.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_de.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_es.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_fr.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_hu.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_it.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_nl.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_pl.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_sl.properties
found == META-INF/resourcebundles/core_en for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en_US.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en.properties

预期加载应该是

found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_cs.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_de.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en.properties
found == META-INF/resourcebundles/core_en for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en_GB.properties
found == META-INF/resourcebundles/core_en for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_en_US.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_es.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_fr.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_hu.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_it.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_nl.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_pl.properties
found == META-INF/resourcebundles/core for file jar:file:/D:/Tomcat/WebProject/webapps/demo/WEB-INF/lib/core-SNAPSHOT.jar!/META-INF/resourcebundles/core_sl.properties

我正在使用 spring 框架中的 PathMatchingResourcePatternResolver 来解析来自类路径配置的路径

    <bean id="messageSource" class="com.company.core.spring.support.ClasspathResourceBundleMessageSource">
        <property name="basename" value="classpath*:/META-INF/resourcebundles/**/*.properties"/>  
    </bean>

ClasspathResourceBundleMessageSource 从 spring 框架

扩展 ResourceBundleMessageSource
public void setBasenames(final String... basenames) {
        List<String> basenamesList = new ArrayList<>();
        try {

            for (String basename : basenames) {
                LOGGER.info("==\t Base Name configured {}", basename);
                Resource[] resources = (new PathMatchingResourcePatternResolver()).getResources(basename);
                for (Resource resource : resources) {
                    LOGGER.info("==\t Name of resource found {}", resource.getURI());
                    String filename = resource.getURI().toString();
                    String newBasename = transformToBasename(filename);
                    if (newBasename != null && !basenamesList.contains(newBasename)) {
                        LOGGER.info("Adding resource bundle basename {}", newBasename);
                        basenamesList.add(newBasename);
                    }
                }
            }

            // Add the basenames found
            LOGGER.info("Resource bundle path:{}", basenamesList);
            String[] basenamesArray = basenamesList.toArray(new String[]{});
            super.setBasenames(basenamesArray);
        } catch (Exception ex) {
            LOGGER.error("Error setting base names", ex);
        }
    }

另一个见解是,如果我在本地构建存档 war,它就可以工作。但是,当存档由构建服务器 (jenkins) 构建时,它不会按预期工作。

我发现 java.util.jar.JarFile 中的 JarFile.entries() 方法返回未排序的文件列表。我用一个小程序测试了一下。

import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class JarFileTest {

    public static void main(String[] args) {

        File correctJarFile = new File("D:\target\budget.jar");
        File wrongJarFile = new File("D:\target\budget2.jar");
     
        try (JarFile jar = new JarFile(correctJarFile )) {
            for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); ) {
                JarEntry entry = entries.nextElement();
                String entryPath = entry.getName();
                if (entryPath.endsWith(".properties")) {
                    System.out.println(entryPath);
                }
            }
        }catch (IOException e) {
        }
        System.out.println("\n============ 2");
        try (JarFile jar = new JarFile(wrongJarFile)) {
            for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); ) {
                JarEntry entry = entries.nextElement();
                String entryPath = entry.getName();
                if (entryPath.endsWith(".properties")) {
                    System.out.println(entryPath);
                }
            }
        }catch (IOException e) {
        }
    }
}

以上程序产生以下输出。

META-INF/resourcebundles/core_cs.properties
META-INF/resourcebundles/core_de.properties
META-INF/resourcebundles/core_en.properties
META-INF/resourcebundles/core_en_GB.properties
META-INF/resourcebundles/core_en_US.properties
META-INF/resourcebundles/core_fr.properties

============ 2
META-INF/resourcebundles/core_en_GB.properties
META-INF/resourcebundles/core_cs.properties
META-INF/resourcebundles/core_de.properties
META-INF/resourcebundles/core_fr.properties
META-INF/resourcebundles/core_en_US.properties
META-INF/resourcebundles/core_en.properties

这与 Java8 流相同 API

        try (JarFile jar = new JarFile(jarFile)) {
            jar.stream().filter(entry -> entry.getName().endsWith(".properties")).forEach(System.out::println);
        } catch (IOException e) {
        }
        System.out.println("\n============ 0");
        try (JarFile jar = new JarFile(jarFile2)) {
            jar.stream().filter(entry -> entry.getName().endsWith(".properties")).forEach(System.out::println);
        } catch (IOException e) {
        }

因此,我已应用自定义排序来修复 ZipFile 中的排序,如

中所述