Spring in Action Covers Spring 5-1--11 — страница 28 из 63

5.3.3 Создание bean-ов в зависимости от профиля

Иногда полезно предоставить уникальный набор bean-компонентов для разных профилей. Обычно любой компонент, объявленный в классе конфигурации Java, создается независимо от того, какой профиль активен. Но предположим, что есть некоторые bean-компоненты, которые вам нужно создать, только если определенный профиль активен. В этом случае аннотация @Profile может определять bean-компоненты как применимые только к данному профилю.

Например, у вас есть компонент CommandLineRunner, объявленный в TacoCloudApplication, который используется для загрузки встроенной базы данных с данными об ингредиентах при запуске приложения. Это здорово для режима разработки, но было бы ненужным (и нежелательным) в приложении на продакшене. Чтобы предотвратить загрузку данных ингредиента при каждом запуске приложения при продакшен развертывании, вы можете аннотировать метод компонента CommandLineRunner с помощью @Profile следующим образом:

@Bean

@Profile("dev")

public CommandLineRunner dataLoader(IngredientRepository repo,

   UserRepository userRepo, PasswordEncoder encoder) {

 ...

}

Или предположим, что вам нужно создать CommandLineRunner, если активен либо dev-профиль, либо qa-профиль. В этом случае вы можете перечислить профили, для которых должен быть создан компонент:

@Bean

@Profile({"dev", "qa"})

public CommandLineRunner dataLoader(IngredientRepository repo,

   UserRepository userRepo, PasswordEncoder encoder) {

 ...

}

Теперь данные ингредиента будут загружены только если активны профили dev или qa. Это означало бы, что вам нужно активировать профиль разработчика при запуске приложения в среде разработки. Было бы еще удобнее, если бы этот компонент CommandLineRunner создавался всегда, если профиль prod не активен. В этом случае вы можете применить @Profile следующим образом:

@Bean

@Profile("!prod")

public CommandLineRunner dataLoader(IngredientRepository repo,

   UserRepository userRepo, PasswordEncoder encoder) {

 ...

}

Здесь восклицательный знак (!) отменяет имя профиля. По сути, он утверждает, что bean-компонент CommandLineRunner будет создан, если профиль prod не активен.

Также можно использовать @Profile для всего класса, аннотированного @Configuration. Например, предположим, что вы должны были извлечь компонент CommandLineRunner в отдельном классе конфигурации с именем DevelopmentConfig.Для этого достаточно аннотировать DevelopmentConfig с помощью @Profile:

@Profile({"!prod", "!qa"})

@Configuration

public class DevelopmentConfig {

 @Bean

 public CommandLineRunner dataLoader(IngredientRepository repo,

   UserRepository userRepo, PasswordEncoder encoder) {

 ...

 }

}

Здесь bean-компонент CommandLineRunner (как и любые другие bean-компоненты, определенные в DevelopmentConfig) будет создан, только если ни prod, ни qa-профили не активны.

Итог:

Spring bean-компоненты могут быть аннотированы с помощью @ConfigurationProperties, чтобы включить внедрение значений из одного из нескольких источников свойств.

Свойства конфигурации можно задавать в аргументах командной строки, переменных среды, системных свойствах JVM, файлах свойств или файлах YAML, а также в других параметрах.

Свойства конфигурации можно использовать для переопределения параметров автоконфигурации, включая возможность указать URL-адрес источника данных и уровни логирования.

Профили Spring можно использовать с источниками свойств для условной установки свойств конфигурации на основе активных профилей.

Spring in Action Covers Spring 5.0 перевод на русский. Глава 6

6. Создание REST сервисов

Эта глава охватывает

Определение REST endpoints в  Spring MVC

Включение гиперссылочных REST ресурсов

Автоматические REST endpoints на основе репозитория

«Веб-браузер мертв. Что теперь?"

Примерно дюжину лет назад я слышал, как кто-то предположил, что веб-браузер приближается к статусу legacy и что что-то другое возьмет верх. Но как такое могло случиться? Что может свергнуть почти вездесущий веб-браузер? Как бы мы использовали растущее количество сайтов и онлайн-сервисов, если бы не веб-браузер? Конечно, это был бред сумасшедшего!

Вернемся в день сегодняшний и станет очевидно, что веб-браузер не исчез. Но он больше не является основным средством доступа к Интернету. Мобильные устройства, планшеты, умные часы и голосовые устройства стали обычным явлением. И даже многие браузерные приложения на самом деле работают с приложениями JavaScript, а не позволяют браузеру быть тупым терминалом для рендеринга контента на сервере.

С таким широким выбором вариантов на стороне клиента многие приложения приняли общий дизайн, в котором пользовательский интерфейс перемещается ближе к клиенту, а сервер предоставляет API, через который все типы клиентов могут взаимодействовать с функциональностью бэкэнда.

В этой главе вы собираетесь использовать Spring для предоставления REST API для приложения TacoCloud. Вы будете использовать то, что узнали о Spring MVC в главе 2, для создания endpoints  RESTful с контроллерами Spring MVC. Вы также автоматически выставите REST endpoints для Spring Data repository-ев, которые вы определили в главе 4. Наконец, мы рассмотрим способы тестирования и защиты этих endpoint.

Но сначала вы напишите  несколько новых контроллеров Spring MVC, которые предоставляют функциональные возможности бэкэнда с endpoint REST, которые будут использоваться богатым веб-интерфейсом.

6.1 Написание RESTful контроллеров

Надеюсь, вы не возражаете, но пока вы переворачивали страницу и читали введение к этой главе, я взял на себя смелость переосмыслить пользовательский интерфейс для TacoCloud. То, с чем вы работали, было прекрасно для начала, но этого не хватало по части эстетики.

Рисунок 6.1 - это просто пример того, как выглядит Taco Cloud. Довольно шикарно, а?

Рисунок 6.1 Новая домашняя страница Taco Cloud

Когда я любовался внешним видом Taco Cloud, я решил создать веб-интерфейс в виде одностраничного приложения с использованием популярной платформы Angular. В конечном счете, этот новый пользовательский интерфейс браузера заменит серверные страницы, созданные вами в главе 2. Но для этого вам потребуется создать REST API, с которым пользовательский интерфейс построенный на Angular (Я решил использовать Angular, но выбор среды интерфейса не должен иметь никакого отношения к написанию бэккенд кода Spring. Не стесняйтесь выбирать Angular, React, Vue.js или любую другую технологию веб-интерфейса, которая подходит вам больше всего) будет связываться, чтобы сохранять и извлекать данные тако.

SPA или не  SPA?

Вы разработали традиционное многостраничное приложение (MPA) с Spring MVC в главе 2, и теперь вы заменяете его одностраничным приложением (SPA) на основе Angular. Но я не утверждаю, что SPA всегда лучший выбор, чем MPA.

Поскольку представление в значительной степени отделено от серверной обработки в SPA, это дает возможность разработать более одного пользовательского интерфейса (такого как собственное мобильное приложение) для одной и той же функциональности сервера. Это также открывает возможность для интеграции с другими приложениями, которые могут использовать API. Но не все приложения требуют такой гибкости, и MPA - это более простой дизайн, если все, что вам нужно, это отображать информацию на веб-странице.

Это не книга по Angular, поэтому код в этой главе будет сосредоточен в основном на бэккенд Spring-коде. Я покажу достаточно Angular-кода, чтобы вы могли понять, как работает клиентская часть. Будьте уверены, что полный набор кода, включая Angular frontend, доступен как часть загружаемого кода для книги и по адресу https://github.com/habuma/spring-in-action-5-samples. Вас также может заинтересовать чтение Angular in Action Джереми Уилкена (Manning, 2018) и Angular Development with TypeScript, второе издание Якова Файна и Антона Моисеева (Manning, 2018).

В двух словах, клиентский код Angular будет взаимодействовать с API, который вы создадите в этой главе посредством HTTP-запросов. В главе 2 вы использовали аннотации @GetMapping и @PostMapping для извлечения и публикации данных на сервере. Те же самые аннотации по-прежнему пригодятся, когда вы определите свой REST API. Кроме того, Spring MVC поддерживает несколько других аннотаций для различных типов HTTP-запросов, как указано в таблице 6.1.

Таблица 6.1. Spring MVC HTTP аннотации обработки запросов (Сопоставление методов HTTP для создания, чтения, обновления и удаления (CRUD) операций не является идеальным соответствием, но на практике именно так они часто используются и как вы будете их использовать в Taco Cloud.)

Аннотация  - HTTP метод  - Стандартное применение

@GetMapping  - HTTP GET requests  - Чтение данных

@PostMapping - HTTP POST requests -  Создание данных

@PutMapping - HTTP PUT requests - Изменение данных

@PatchMapping -  HTTP PATCH requests - Изменение данных

@DeleteMapping - HTTP DELETE requests - Удаление данных

@RequestMapping - Обработка запросов общего назначения; HTTP - метод, указанный как атрибут метода

Чтобы увидеть эти аннотации в действии, вы начнете с создания простой REST endpoint, которая выбирает несколько самых последних созданных тако.

6.1.1 Получение данных с сервера

Одна из самых крутых вещей в Taco Cloud - это то, что он позволяет фанатикам тако создавать свои собственные творения тако и делиться ими со своими коллегами-любителями тако. Для этого в Taco Cloud должна быть возможность отображать список самых последних созданных тако при нажатии на ссылку «Latest Designs».

В коде Angular я определил компонент RecentTacosComponent, который будет отображать самые последние созданные тако. Полный код TypeScript для RecentTacosComponent показан в следующем листинге.