Pra*_*h K 4 java applet jar properties
我维护一个applet,帮助用户将照片上传到我们的服务.applet jar文件有几个.properties文件:
>> jar -tf applet.jar | grep prop
res/messages.properties
res/messages_ca.properties
res/messages_es.properties
...
Run Code Online (Sandbox Code Playgroud)
这些是在applet初始化期间加载的.
messages = ResourceBundle.getBundle("res.messages");
Run Code Online (Sandbox Code Playgroud)
然而,此调用会向服务器生成4到5个请求,以查找不在jar文件中的文件,然后再返回到.properties包含在文件中的文件.jar.
从服务器错误日志:
[error] File does not exist: /photos/res/messages.class
[error] File does not exist: /photos/res/messages_en.class
[error] File does not exist: /photos/res/messages_en.properties
[error] File does not exist: /photos/res/messages_en_US.class
[error] File does not exist: /photos/res/messages_en_US.properties
Run Code Online (Sandbox Code Playgroud)
ResourceManager.getBundle的文档解释了这是它的完成方式:
然后,getBundle迭代候选bundle名称,找到第一个可以实例化实际资源包的名称.对于每个候选包名称,它会尝试创建资源包:
首先,它尝试使用候选包名称加载类.如果可以使用指定的类加载器找到并加载这样的类,与ResourceBundle兼容的赋值,可以从ResourceBundle访问,并且可以实例化,则getBundle创建此类的新实例并将其用作结果资源包.
否则,getBundle会尝试查找属性资源文件.它通过替换所有"."从候选包名称生成路径名.带有"/"的字符并附加字符串".properties".它尝试使用ClassLoader.getResource查找具有此名称的"资源".
我确信这样做是有充分理由的,但在我看来,对于我来说,对于已知在服务器上不存在的文件应该有五个失败的请求似乎是浪费的.
有没有办法教applet .jar只在文件中查找这些文件?
注意:我不是Java程序员,所以如果有更好的方法来加载属性ResourceManager.getBundle,请告诉我.
Java 1.6引入了ResourceBundle.Control类,如果您不支持Java 1.4,它可能会提供一些帮助.就像你一样,编写自己的捆绑管理器并不是火箭科学.
此演示代码将捆绑加载限制为给定语言集中的属性文件:
public class CustomManager {
private static final Map BUNDLES = new HashMap();
public static ResourceBundle getBundle(String name, Set languages) {
Locale locale = Locale.getDefault();
if (languages.contains(locale.getLanguage())) {
name = name + "_" + locale.getLanguage();
}
synchronized (BUNDLES) {
ResourceBundle bundle = (ResourceBundle) BUNDLES.get(name);
if (bundle == null) {
ClassLoader loader = getContextClassLoader();
bundle = loadBundle(loader, name.replace('.', '/') + ".properties");
BUNDLES.put(name, BUNDLES);
}
return bundle;
}
}
private static ClassLoader getContextClassLoader() {
return Thread.currentThread().getContextClassLoader() != null ? Thread
.currentThread().getContextClassLoader() : CustomManager.class
.getClassLoader() != null ? CustomManager.class.getClassLoader()
: ClassLoader.getSystemClassLoader();
}
private static ResourceBundle loadBundle(ClassLoader loader, String res) {
try { InputStream in = loader.getResourceAsStream(res);
try { return new PropertyResourceBundle(in);
} finally { in.close(); }
} catch (IOException e) { throw new IllegalStateException(e.toString()); }
}
}
Run Code Online (Sandbox Code Playgroud)
此代码模拟调用以检索西班牙语/西班牙语区域设置的字符串:
Set languages = new HashSet(Arrays.asList(new String[] { "es", "ca" }));
Locale.setDefault(new Locale("es", "ES"));
ResourceBundle bundle = CustomManager.getBundle("l10n.res.foo", languages);
System.out.println(bundle.getString("bar"));
Run Code Online (Sandbox Code Playgroud)
由于一套语言是es和ca和CustomManager仅支持语言(不是国家代码或变体)仅将下列文件可以加载:
l10n/res/foo.properties
l10n/res/foo_es.properties
l10n/res/foo_ca.properties
Run Code Online (Sandbox Code Playgroud)
您希望通过Locale和ClassLoader支持获得的复杂程度以及您希望管理语言列表的位置取决于您.
警告:我认为我没有违反实施的任何安全限制,但我只测试了桌面应用程序中的代码.