Выбрать главу

    return "orderList";

 }

}

Наиболее значительным изменением, внесенным в листинг 5.1, является добавление аннотации @ConfigurationProperties. Его префиксный атрибут имеет значение taco.orders, что означает, что при установке свойства pageSize необходимо использовать свойство конфигурации с именем taco.orders.pageSize.

Новое свойство pageSize по умолчанию равно 20. Но вы можете легко изменить его на любое желаемое значение, установив свойство taco.orders.pageSize. Например, вы можете установить это свойство в application.yml следующим образом:

taco:

 orders:

   pageSize: 10

Или, если вам нужно сделать быстрые изменения во время работы, вы можете сделать это без необходимости rebuild и redeploy приложения, задав свойство taco.orders.pageSize в качестве переменной среды:

$ export TACO_ORDERS_PAGESIZE=10

Любое средство, с помощью которого можно установить свойство конфигурации, можно использовать для настройки размера страницы последних заказов. Далее мы рассмотрим, как устанавливать данные конфигурации в хранилищах свойств (property holders).

5.2.1 Определение хранилища свойств конфигурации (configuration properties holders)

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

В случае свойства pageSize в OrderController вы можете перенести его в отдельный класс. Следующий листинг демонстрирует такой класс OrderProps.

Листинг 5.2. Извлечение pageSize в класс хранилища свойств

package tacos.web;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.stereotype.Component;

import lombok.Data;

 

@Component

@ConfigurationProperties(prefix="taco.orders")

@Data

public class OrderProps {

 private int pageSize = 20;

}

Как и в случае с OrderController, для свойства pageSize по умолчанию установлено значение 20, а для OrderProps добавлен @ConfigurationProperties с префиксом taco.orders. Он также помечен @Component, так что сканирование компонентов Spring автоматически обнаружит его и создаст как компонент в контексте приложения Spring. Это важно, так как следующим шагом является внедрение bean-компонента OrderProps в OrderController.

В хранилище конфигурации нет ничего особенного. Это bean, чьи свойства поступают из среды Spring. Они могут быть введены в любой другой компонент, которому нужны эти свойства. Для OrderController это означает удаление свойства pageSize из OrderController и вместо этого внедрение и использование компонента OrderProps:

@Controller

@RequestMapping("/orders")

@SessionAttributes("order")

public class OrderController {

 private OrderRepository orderRepo;

 private OrderProps props;

 public OrderController(OrderRepository orderRepo,

     OrderProps props) {

   this.orderRepo = orderRepo;

   this.props = props;

 }

 ...

 @GetMapping

 public String ordersForUser(

     @AuthenticationPrincipal User user, Model model) {

   Pageable pageable = PageRequest.of(0, props.getPageSize());

   model.addAttribute("orders",

     orderRepo.findByUserOrderByPlacedAtDesc(user, pageable));

   return "orderList";

 }

 ...

}

Теперь OrderController больше не отвечает за обработку своих собственных свойств конфигурации. Это делает код OrderController немного аккуратнее и позволяет повторно использовать свойства из OrderProps в любом другом компоненте, который может в них нуждаться. Кроме того, вы группируете свойства конфигурации, которые относятся к заказам в одном месте: класс OrderProps. Если вам нужно добавить, удалить, переименовать или иным образом изменить содержащиеся в нем свойства, вам нужно только произвести эти изменения в OrderProps.

Например, давайте представим, что вы используете свойство pageSize в нескольких других bean-компонентах, когда вдруг решили, что было бы лучше применить некоторую проверку к этому свойству, чтобы ограничить его значения не менее чем 5 и не более 25. Без отдельного bean-компонента вам нужно будет применить аннотации проверки к OrderController, свойству pageSize и во всех других классах, использующих это свойство. Но поскольку вы создали pageSize в OrderProps, вам нужно только внести изменения в OrderProps:

package tacos.web;

import javax.validation.constraints.Max;

import javax.validation.constraints.Min;

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.stereotype.Component;

import org.springframework.validation.annotation.Validated;

import lombok.Data;

 

@Component

@ConfigurationProperties(prefix="taco.orders")

@Data

@Validated

public class OrderProps {

   @Min(value=5, message="must be between 5 and 25")

   @Max(value=25, message="must be between 5 and 25")

   private int pageSize = 20;

}

//end::validated[]

Хотя вы могли бы так же легко применить аннотации @Validated, @Min и @Max к OrderController (и любым другим bean-компонентам, которые могут быть внедрены с помощью OrderProps), это просто намного больше загромождает OrderController. С помощью компонента-хранилища свойства конфигурации вы собрали спецификацию свойств конфигурации в одном месте, оставив классы, которым эти свойства нужны, относительно чистыми.