【问题标题】:Static ResourceBundle静态资源包
【发布时间】:2013-08-01 09:37:37
【问题描述】:

我目前正在为使用 ResourceBundle 的应用程序制作资源。问题是,使用当前代码来调度资源,我每次需要时都需要创建资源包的实例,我猜这不是一个好主意,因为我最终会一次又一次地加载资源.

第二种解决方案是将捆绑包分成许多,但我最终会得到捆绑包只有 2-3 个字符串,就像 15 个捆绑包。

我的问题是: 有没有办法在一个静态类中简单地加载所有资源并从那里访问它们。

我编写的这段代码似乎对我有用,但我怀疑它的质量。

public class StaticBundle
{
    private final static ResourceBundle resBundle = 
        ResourceBundle.getBundle("com.resources");
    public final static String STRING_A = resBundle.getString("KEY_A");
    public final static String STRING_B = resBundle.getString("KEY_B");
    public final static String STRING_C = resBundle.getString("KEY_C");
}

有了这个,我可以调用StaticBundle.STRING_A 并在项目中的任何位置获取值,但是由于捆绑包是与类本身同时初始化的......程序很可能没有时间从首选项中加载正确的本地。

有没有好的方法来做这个或任何其他可能的解决方案?

谢谢

【问题讨论】:

  • 如果您只使用默认语言环境来加载您的密钥,您所拥有的一切都很好。但不要太担心性能:ResourceBundle.getBundle() 使用缓存,并且不会在每次调用时重新加载资源。

标签: java static resources resourcebundle


【解决方案1】:

如果您打算只为默认语言环境提供消息,那么您所拥有的就可以了。

或者,您可以让调用者指定它需要的键而不是常量,如下所示:

public static String getMessage(String key) {
    return resBundle.getString(key);
}

如果您想支持多个语言环境,那么通常的方法是使用 Map<Locale, ResourceBundle>Map<Locale, Map<String, String>,您只需为每个语言环境加载一次资源。在这种情况下,您的类将有一个调用者可以指定语言环境的方法:

public static String getMessage(String key, Locale locale) {
    Map<String, String> bundle = bundles.get(locale);   // this is the map with all bundles
    if (bundle == null) {
        // load the bundle for the locale specified
        // here you would also need some logic to mark bundles that were not found so
        // to avoid continously searching bundles that are not present 

        // you could even return the message for the default locale if desirable
    }
    return bundle.get(key);
}

编辑:正如@JB Nizet 正确指出的(谢谢)ResourceBundle 已经存储了Map。我在源示例中提供的自定义解决方案是关于类似于ResourceBundle 的自定义机制,它使用Maps 的Map 以property=value 格式加载键的翻译,不仅来自文件,还来自数据库。我错误地认为我们在该解决方案中有MapResourceBundle。源示例现已修复。

【讨论】:

  • 事实上,我在一开始就更改了运行时的默认本地,所以我不需要每次需要资源时都获取本地(我有点懒)。所以你的第二个解决方案不适合我,我喜欢这个想法。最后,如果要更改资源密钥,我会不断集中在需要更改资源密钥的位置(再次是我的懒惰)。
  • 将捆绑包存储在地图中是没有意义的。 ResourceBundle.getBundle() 已经这样做了,而且做得对,以线程安全的方式。
  • @JBNizet 你当然是对的。我们在一个项目中有一个自定义解决方案,我们是否使用Map&lt;Locale, Map&lt;String, String&gt;&gt; 用于自定义解决方案。我的记忆背叛了我,以为我们有一个Map&lt;Locale, ResourceBundle&gt;。我已经编辑了我的答案以纠正这个问题。感谢您的评论
【解决方案2】:

你可以创建一个单例类:

public class MyResouceBundle extends ResourceBundle {

    private static MyResourceBundle instance = new MyResouceBundle();

    // private constructor, no one can instantiate this class, only itself
    private MyResourceBundle() {

    }

    public ResourceBundle getInstance() {
        return instance;
    }
}

然后,每个人都将访问该类的同一个实例(例如,获取 KEY_A 的字符串):

MyResourceBunde.getInstance().get("KEY_A");

【讨论】:

    猜你喜欢
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    • 2018-04-24
    • 2014-08-29
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多