Разница между Application#getResourceBundle() и ResourceBundle#getBundle() в JSF 2.0

Чтобы получить строки из пакета ресурсов, я пытаюсь сравнить результат этих двух методов, ниже пример кода:

Первый пример:

baseName: полное имя пакета ресурсов (<base-name> в <resource-bundle>).

FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
ResourceBundle bundle = app.getResourceBundle(context, baseName);

Второй пример:

varName: это строка, представляющая <var></var> в <resource-bundle>

FacesContext context = FacesContext.getCurrentInstance();
Locale locale = context .getViewRoot().getLocale();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ResourceBundle bundle = ResourceBundle.getBundle(varName, locale, loader);

В чем разница между этими двумя примерами? если нет разницы, как лучше всего получить ResourceBundle (использовать Application#getMessageBundle() или ResourceBundle#getBundle())?


person Tarik    schedule 13.01.2015    source источник


Ответы (1)


Прежде всего, вы перепутали varName/baseName подходов. Фактические подходы:

Application#getResourceBundle()

varName: это строка, представляющая <resource-bundle><var> в faces-config.xml

FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ResourceBundle bundle = application.getResourceBundle(context, varName);

ResourceBundle#getBundle()

baseName: полное имя пакета ресурсов, например <resource-bundle><base-name>.

FacesContext context = FacesContext.getCurrentInstance();
Locale locale = context.getViewRoot().getLocale();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, loader);

Первый получает его через JSF Application, который под прикрытием также использует UIViewRoot#getLocale() (с откатом к Locale#getDefault()), а второй получает его напрямую.

Что касается техники и конечного результата, то разницы никакой. Вы получите один и тот же пакет в обоих случаях (при условии, что локаль правильная). Однако, что касается ремонтопригодности, это определенно отличается. Пакеты ресурсов подпадают под конфигурацию и должны быть экстернализованы (в faces-config.xml).

Жесткое кодирование FQN, как в baseName, является плохой практикой. Вы не можете легко и быстро изменить FQN без повторной компиляции и повторной сборки всего кода. Если бы это было в стороннем файле JAR, это было бы еще более проблематично. В противном случае вы могли бы просто переопределить его другим <resource-bundle> на том же <var> из своего веб-приложения. Кроме того, библиотеки компонентов/служебных программ JSF могут предоставлять собственную оболочку Application, которая, возможно, могла бы украсить вызов getResourceBundle(), чтобы сделать его удивительным. Это было бы невозможно, если бы вы получили его напрямую через ResourceBundle#getBundle().


Есть, кстати, и третий подход: просто ввести его.

В управляемом компоненте JSF предоставлено <var>text</var>:

@ManagedProperty("#{text}")
private ResourceBundle text;

Или в управляемом компоненте CDI:

@Inject
private PropertyResourceBundle text;

С этим производителем:

public class BundleProducer {

    @Produces
    public PropertyResourceBundle getBundle() {
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getApplication().evaluateExpressionGet(context, "#{text}", PropertyResourceBundle.class);
    }

}

Примечание: оценка EL пакета #{text} используется под обложками Application#getResourceBundle().

person BalusC    schedule 13.01.2015
comment
это очень четкое объяснение, для сочетания varName/baseName это была просто ошибка, когда я писал вопрос, в моем собственном коде все было наоборот ... спасибо за ваши прекрасные ответы :) - person Tarik; 14.01.2015
comment
Не могли бы вы привести пример. Кроме того, библиотеки компонентов / утилит JSF могут предоставлять собственную оболочку приложения, которая, возможно, могла бы украсить вызов getResourceBundle(), чтобы сделать его удивительным. - person Tarik; 14.01.2015
comment
Он может возвращать пользовательскую реализацию ResourceBundle, поэтому у вас практически есть полная свобода изменять поведение пакета. Например. автоматическое слияние другого пакета или использование значения в качестве другого ключа или регистрация, когда ключей не существует, и т. д. - person BalusC; 14.01.2015
comment
Прошу прощения за все эти вопросы, но я с трудом искал, чтобы понять, как вы узнали, что оценка EL пакета #{text} используется под обложками Application#getResourceBundle(). но без каких-либо успехов, не могли бы вы сказать мне, как искать такую ​​​​информацию или просто где искать? NB: я видел исходный код javax.faces.bean.ManagedProperty, но не получил ответов - person Tarik; 16.01.2015
comment
Опыт, здравый смысл, наблюдение, исходный код и т. д. В случае с Мохаррой посмотрите на com.sun.faces.el.FacesResourceBundleELResolver. - person BalusC; 16.01.2015