В папке DOC sql-скрипты и др. полезные файлы.
Док. (ссылки) для изучения:
- Spring Security ;
- Security with Spring (by www.baeldung.com) ;
- SWAGGER DOC (может понадобится прокси);
- Spring Boot Reference Documentation ;
- Spring Framework 6.1.5 Documentation ;
- Spring Framework 3.2.x Reference Documentation ;
- Getting Started Guides ;
- Developing with Spring Boot ;
Для начала проведем предварительную подготовку (подгрузим зависимости в build.gradle):
/*
Плагин Spring Boot добавляет необходимые задачи в Gradle
и имеет обширную взаимосвязь с другими plugin-ами.
*/
id 'org.springframework.boot' version '3.1.3'
/*
Менеджер зависимостей позволяет решать проблемы несовместимости
различных версий и модулей Spring-а
*/
id "io.spring.dependency-management" version '1.0.11.RELEASE'
/* Подключим Lombok */
id "io.freefair.lombok" version "8.3"
/*
Автоматически Gradle создал тестовую зависимость на Junit5, мы можем
использовать как Junit4, так и TestNG
*/
test {
useJUnitPlatform()
}
/*
Подключим Spring Boot Starter он включает поддержку
авто-конфигурации, логирование и YAML
*/
implementation 'org.springframework.boot:spring-boot-starter'
/* Подключим блок для работы с БД (Spring Boot Starter Data Jpa) */
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
/* Для работы с PostgreSQL подключим и его зависимости */
implementation 'org.postgresql:postgresql'
!!! НЕ ЗАБЫВАЕМ !!! У нас есть классы (см. ConnectionPool.java и комментарии), где мы пытаемся внедрить параметры в
поля через аннотации, с использованием аннатационного же конструктора @RequiredArgsConstructor. Фокус не пройдет без
создания и настройки файла конфигурации: lombok.config - 'контекст' просто завалится.
Либо все делаем руками от начала и до конца, либо помним какие вспомогательные средства используем и какие их особенности
могут повлиять на работу приложения.
implementation 'org.springframework.data:spring-data-envers'
/* Подключим миграционный фреймворк Liquibase */
implementation 'org.liquibase:liquibase-core'
/* Подключаем Wed - Starter */
implementation 'org.springframework.boot:spring-boot-starter-web'
/* Подключим Thymeleaf */
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
/* Подключим валидацию */
implementation 'org.springframework.boot:spring-boot-starter-validation'
/* Подключим стартер безопаности */
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
/* Зависимости необходимые при тестировании Spring Boot приложения */
testImplementation 'org.springframework.boot:spring-boot-starter-test'
/* Зависимости позволяет тестировать приложение с подключенным Spring Security */
testImplementation 'org.springframework.security:spring-security-test'
testImplementation "org.testcontainers:postgresql:${versions.testcontainers}"
Как и в Servlet-ах процесс интернационализации идет через ResourceBundle. И конечно в Spring-e это реализуется чуть по-другому, все bundle имеют зарезервированные названия и настройку можно провести за 3-и шага:
-
Шаг 1. - В application.yml добавляем префикс messages из MessageSourceAutoConfiguration, это конфигурационный файл для MessageSource, а значит и для ResourceBundle:
messages: basename: messages fallback-to-system-locale: false
-
Шаг 2. - Создаем файлы message-ей для разных языков в папке resources нашего приложения:
- messages.properties - с default настройками (в нашем варианте язык EN);
- messages_ru.properties - с настройками для русского языка (_ru - указан только язык, если добавить _RU, то мы добавляем намек на регион, хотя это и необязательно и т.д.);
По умолчанию приложение Spring Boot будет искать файлы messages, содержащие ключи и значения интернационализации, в папке src/main/resources. Обычно файлы для каждой локали называются messages_XX.properties, где XX — код локали. Мы также можем определить резервный файл messages.properties.
!!! Однако, резервный файл не следует считать связанным с локалью по умолчанию. Это два отдельных понятия !!!
Языковой стандарт по умолчанию - это языковой стандарт, используемый по умолчанию, когда запрошенный языковой стандарт недоступен или имеет значение NULL. С другой стороны, резервный файл — это место для поиска свойств в случае сбоя перевода локали.
Если ключ не существует в определенном файле локали, приложение просто вернется к резервному файлу. Ключи для значений, которые будут локализованы, должны быть одинаковыми в каждом файле, а значения должны соответствовать языку выбранной локали.
IDEA сразу объединила оба свойства в ассоциированный комплект: Resource Bundle 'messages'. Теперь необходимо удостовериться, что в настройках среды разработки, кодирование файлов идет в UTF-8 см. DOC/IDEASettingFileEncodingUTF-8.jpg
- Шаг 3. - Фактически уже все готово, но нам нужно убедиться, что интернационализация работает. Для этого создадим REST endpoint позволяющий тестировать работу нашей - Internationalization (i18n) - MessageRestController.java см. комментарии в коде класса.
Теперь проверяем работу наших настроек на REST контроллере, запускаем приложение, переходим по http://localhost:8080/swagger-ui/index.html и тестируем *.getMessage() метод. Например, 'key' у нас это 'login.username', тогда 'lang' это 'ru', 'fr' или 'en', см. DOC/message-rest-controller-ru-test.jpg и DOC/message-rest-controller-fr-test.jpg.
На HTML страницах для использования интернационализации применяется тег #{.....} см. пример:
<span th:text="#{login.username}">Username:</span>
Т.е. нам необходимо по данному шаблону интернационализировать все наши страницы. Однако у нас нет возможности выбора языка ни на одной странице, нужно это исправить. Добавим блок выбора языка в папку fragment - language_selection.html.
И так повторим, что необходимо сделать для внедрения интернационализации и локализации в Spring приложение:
- Шаг 1. - Настроить application.yml см. выше предыдущий Lesson 116.
- Шаг 2. - Создать файлы message-ей для разных языков в папке resources нашего приложения см. выше предыдущий Lesson 116.
- Шаг 3. - Предоставить пользователю возможность изменять язык интерфейса, желательно, на всех доступных страницах. Для этого создаем отдельную страницу language_selection.html, которая будет интегрироваться в другие HTML страницы.
- Шаг 4. - Используя синтаксис Thymeleaf описанный выше внесем изменения в файлы: language_selection.html, logout.html и user.html (только в них, другие можно изменить по данному же принципу, но тут мы этого делать не будем)
И вот тут начинается самое интересное. Нам необходимо отслеживать запрос генерируемый language_selection.html на нашем сервере (в нашем приложении). Т.е. наше приложение должно увидеть что параметр lang=en изменился на lang=ru или другой язык. Для этого нам нужно внести изменения в WebConfiguration.java:
- Шаг 5. - Создаем bean метод перехватчик изменений локали *.localeChangeInterceptor(), который будет возвращать LocaleChangeInterceptor. Однако Spring не внедряет LocaleChangeInterceptor автоматически, мы должны это прописать в коде сами.
- Шаг 6. - Создаем метод *.addInterceptors() и уже через него добавляем наш перехватчик изменений локали в реестр перехватчиков - InterceptorRegistry. Только в этом случае, каждый запрос на смену локали (языка) будет обрабатываться приложением (сервером), еще раз см. language_selection.html.
- Шаг 7. - Теперь нам нужно хранить выбранную пользователем локаль (в healers, в cookies, т.е. в параметрах сессии). Для этого нам нужен еще один bean метод *.localeResolver(), который будет возвращать реализацию LocaleResolver, а их несколько, т.е. мы можем выбрать, где хранить состояние локали (языка), например:
В cookies мы храним сессию, поэтому (на данном этапе), затолкаем туда и сведение о выбранном языке. Теперь можно проверить работу локализации в приложении - запускаем и смотрим что получилось см. SelectLanguageMenu.jpg.
См. официальные Guides:
- Getting Started Guides - Эти руководства, рассчитанные на 15–30 минут, содержат быстрые практические инструкции по созданию «Hello World» для любой задачи разработки с помощью Spring. В большинстве случаев единственными необходимыми требованиями являются JDK и текстовый редактор.
- Topical Guides - Тематические руководства предназначенные для прочтения и понимания за час или меньше, содержит более широкий или субъективный контент, чем руководство по началу работы.
- Tutorials - Эти учебники, рассчитанные на 2–3 часа, обеспечивают более глубокое контекстное изучение тем разработки корпоративных приложений, что позволяет вам подготовиться к внедрению реальных решений.