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