Как SpringBoot использует MessageSource для интернационализации

Spring Boot

Пожалуйста, укажите оригинальный источник при перепечатании, спасибо!

Блог HappyFeet

Интернационализация, как я понимаю, заключается в отображении соответствующего языка и подсказок в соответствии с языковыми настройками пользователя. В соответствии с кодом он должен вернуть описание соответствующего языка в соответствии с другой локалью. Например, среда по умолчанию — китайская.你好!, который должен отображаться при смене языка на английскийHello!, то есть интернационализация.

Самый ранний контакт с интернационализацией есть в существующем проекте, есть готовая конфигурация интернационализации, и есть специальный класс для интернационализации:I18nService.java, просто используйте его напрямую, если вам нужна интернационализация. Теперь мне поручили сделать новый проект Modu, и все нужно настроить самому. Мне повезло, что я самостоятельно завершил международную настройку. Хотя сейчас об этом очень просто думать, это все еще очень полезно на момент успешного завершения!


1. I18nService инкапсулирует класс MessageSource, добавляя методы или упрощая цепочку вызовов по мере необходимости.

public class I18nService {

    private final MessageSource messageSource;

    public I18nService(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    public String getMessage(String msgKey, Object[] args) {
        return messageSource.getMessage(msgKey, args, LocaleUtils.getCurrentLocale());
    }

    public String getMessage(String msgKey) {
        return messageSource.getMessage(msgKey, null, LocaleUtils.getCurrentLocale());
    }
}

2, конфигурацияI18nService,MessageSourceBean, в основном для настройки baseNames файла ресурсов; конечно, вы также можете передать атрибут yml (spring.messages.basename) конфигурация

    @Bean
    public I18nService i18nService() {
        return new I18nService(messageSource());
    }

    @Bean
    public ResourceBundleMessageSource messageSource() {
        Locale.setDefault(Locale.CHINESE);
        ResourceBundleMessageSource source = new ResourceBundleMessageSource();
        source.setBasenames("i18n/messages");// name of the resource bundle
        source.setUseCodeAsDefaultMessage(true);
        source.setDefaultEncoding("UTF-8");
        return source;
    }

3. Многоязычный файл конфигурации ресурса ( basenames = i18n/messages ), то есть каталог, в котором находится файл конфигурации, — i18n, а префикс файла — messages

(1) сообщения.свойства
message.key.test=测试!
message.key.hello=你好!{0}~
(2) Messages_en.properties
message.key.test=test!
message.key.hello=hello!{0}~

4, контроллер для тестирования

@Controller
@RequestMapping(value = "/api")
public class HelloJavaCoderController {

    private final I18nService i18nService;

    public HelloJavaCoderController(I18nService i18nService) {
        this.i18nService = i18nService;
    }

    @GetMapping("/hello-coder")
    public ResponseEntity greeting() {
        return ResponseEntity.ok(i18nService.getMessage("message.key.hello", new Object[]{"JavaCoder"}));
    }

    @GetMapping("/test")
    public ResponseEntity test() {
        return ResponseEntity.ok(i18nService.getMessage("message.key.test"));
    }

}

5. Используйте Postman для спокойного тестирования API (запустите службу, server.port=8888)

(1) Запросhttp://localhost:8888/api/testи указать в шапкеAccept-Languate=zh, результат следующий:

test_zh

(2) Запросhttp://localhost:8888/api/testи указать в шапкеAccept-Languate=en, результат следующий:

test_en

(3) запросhttp://localhost:8888/hello-coderи указать в шапкеAccept-Languate=zh, результат следующий:

hello_coder_zh

(4) Запросhttp://localhost:8888/hello-coderи указать в шапкеAccept-Languate=en, результат следующий:

在这里插入图片描述

(1) (2) — это обычное отображение интернационализации, (3) (4) показывает, что заполнители также могут использоваться в интернационализации для привязки определенных параметров во время выполнения, используя что-то вроде{0}Этим способом,getMessageпри прохождении вObject[] argsВыполнить подстановку параметров в соответствующей позиции

После запуска и проверки я хотел понять его внутреннюю реализацию (как MessageSource считывает интернационализированное значение из файла свойств?), я посмотрел исходный код и отладил его, и, наконец, узнал, что это msgKey и значение в файл свойств загружается вlookupВ HashMap (при первой загрузке он будет закэширован, а потом будет закэширован непосредственно позже. Заинтересованные учащиеся могут перейти наPropertyResourceBundle.java:157Найдите ответ в ), получите msgKey -> value, там же во внешнем слое есть локаль для индексации, то есть locale -> (msgKey -> value), и наконец получите соответствующее значение через locale + msgKey.

В конечном итоге файл свойств соответствуетPropertyResourceBundleобъект.

Вышеуказанные коды можно найти вgithubнайти на:spring-i18n-support