@Data
@ConfigurationProperties(prefix="tacocloud.email")
@Component
public class EmailProperties {
private String username;
private String password;
private String host;
private String mailbox;
private long pollRate = 30000;
public String getImapUrl() {
return String.format("imaps://%s:%s@%s/%s",
this.username, this.password, this.host, this.mailbox);
}
}
Как вы можете видеть, EmailProperties содержит свойства, которые используются для создания URL-адреса IMAP. Этот поток использует этот URL-адрес для подключения к серверу электронной почты Taco Cloud и опроса электронных писем. К числу свойств относятся имя пользователя и пароль пользователя электронной почты, а также имя хоста сервера IMAP, почтовый ящик для опроса и скорость, с которой опрашивается почтовый ящик (по умолчанию каждые 30 секунд).
Класс EmailProperties аннотируется на уровне класса @ConfigurationProperties с атрибутом prefix, установленным в tacocloud.email. Это означает, что вы можете настроить детали использования электронной почты в файле application.yml следующим образом:
tacocloud:
email:
host: imap.tacocloud.com
mailbox: INBOX
username: taco-in-flow
password: 1L0v3T4c0s
poll-rate: 10000
Теперь давайте воспользуемся EmailProperties для настройки потока интеграции. Поток, который вы создадите, будет немного похож на рисунок 9.10.
1)Email (IMAP)адаптер входящего канала
3)Mail-to-ordertransformer
5)Отправить заказ на адаптер исходящего канала
Рисунок 9.10 Поток интеграции для приема заказов тако по электронной почте
У вас есть два варианта определения этого потока:
-Определить внутри приложения Taco Cloud - в конце потока сервис-активатор вызовет репозитории, которые вы определили, чтобы создать заказ тако.
-Определите как отдельное приложение.- В конце потока активатор службы отправит запрос POST в Taco Cloud API для отправки заказа тако.
Что вы выберете, мало влияет на сам поток, помимо того, как реализован сервисный активатор. Но поскольку вам потребуются некоторые типы, которые представляют собой тако, заказы и ингредиенты, которые несколько отличаются от тех, которые вы уже определили в основном приложении Taco Cloud, продолжите определение определять интеграционный поток в отдельном приложении, чтобы избежать путаница с существующими типами доменов.
У вас также есть выбор определения потока с использованием XML конфигурации, Java конфигурации или Java DSL. Мне нравится элегантность Java DSL, так что и вы вслед за мной будете ее использовать. Не стесняйтесь писать поток, используя один из других стилей конфигурации, если вам требуются какие-то дополнительные возможности. А пока давайте взглянем на Java DSL конфигурацию для потока электронной почты заказа тако, как показано ниже.
Листинг 9.5. Определение потока интеграции для приема электронных писем и отправки их в качестве заказов
package tacos.email;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.Pollers;
@Configuration
public class TacoOrderEmailIntegrationConfig {
@Bean
public IntegrationFlow tacoOrderEmailFlow(
EmailProperties emailProps,
EmailToOrderTransformer emailToOrderTransformer,
OrderSubmitMessageHandler orderSubmitHandler) {
return IntegrationFlows
.from(Mail.imapInboundAdapter(emailProps.getImapUrl()),
e -> e.poller(
Pollers.fixedDelay(emailProps.getPollRate())))
.transform(emailToOrderTransformer)
.handle(orderSubmitHandler)
.get();
}
}
Поток электронной почты заказа тако, определенный в методе tacoOrderEmailFlow(), состоит из трех отдельных компонентов:
-Адаптер входящего канала электронной почты IMAP - этот адаптер канала создается с помощью URL-адреса IMP, созданного методом getImapUrl() объекта EmailProperties, и опрашивает с задержкой, установленной в свойстве pollRate объекта EmailProperties. Входящие письма передаются по каналу, соединяющему его с трансформатором.
-Трансформатор, который преобразует электронную почту в объект заказа - Преобразователь реализуется в EmailToOrderTransformer, который внедряется в метод tacoOrderEmailFlow(). Заказы, полученные в результате преобразования, передаются конечному компоненту через другой канал.
-Обработчик (выступающий в качестве адаптера исходящего канала)- Обработчик принимает объект заказа и отправляет его по REST API Taco Cloud.
Вызов Mail.imapInboundAdapter() стал возможен благодаря включению endpoint модуля электронной почты в качестве зависимости в сборку проекта. Зависимость Maven выглядит так:
Класс EmailToOrderTransformer является реализацией интерфейса Spring Integration Transformer посредством расширения AbstractMailMessageTransformer (показано в следующем листинге).
Листинг 9.6. Преобразование входящих писем в тако-заказы с использованием интеграционного преобразователя
@Component
public class EmailToOrderTransformer
extends AbstractMailMessageTransformer
@Override
protected AbstractIntegrationMessageBuilder
throws Exception {
Order tacoOrder = processPayload(mailMessage);
return MessageBuilder.withPayload(tacoOrder);
}
…
}
AbstractMailMessageTransformer - удобный базовый класс для обработки сообщений, чья полезная нагрузка - это электронная почта. Он заботится о извлечении информации электронной почты из входящего сообщения в объект Message, который передается в метод doTransform().
В методе doTransform() вы передаете Message private методу с именем processPayload() для анализа электронной почты на получения объекта Order. Несмотря на то, что этот объект Order не похож на объект Order, используемый в основном приложении TacoCloud; это немного проще:
package tacos.email;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
@Data
public class Order {
private final String email;
private List
public void addTaco(Taco taco) {
this.tacos.add(taco);
}
}
Вместо того, чтобы содержать всю информацию о доставке и выставлении счетов клиентам, этот класс Order несет только электронную почту клиента, полученную из входящей электронной почты.
Парсинг электронных писем в тако-заказы является нетривиальной задачей. На самом деле, даже простенькая реализация включает в себя несколько десятков строк кода. И эти несколько десятков строк кода ничего не дадут для дальнейшего обсуждения Spring Integration и того, как реализовать трансформер. Поэтому, чтобы сэкономить место, я опускаю детали метода processPayload().
Последнее, что делает EmailToOrderTransformer, это возвращает MessageBuilder с полезной нагрузкой, содержащей объект Order. Сообщение, сгенерированное MessageBuilder, отправляется последнему компоненту в потоке интеграции: обработчику сообщений, который отправляет заказ в Taco Cloud API. OrderSubmitMessageHandler, показанный в следующем листинге, реализует GenericHandler в Spring Integration для обработки сообщений с полезной нагрузкой Order.
Листинг 9.7. Отправка заказов в Taco Cloud API через обработчик сообщений
package tacos.email;
import java.util.Map;
import org.springframework.integration.handler.GenericHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class OrderSubmitMessageHandler implements GenericHandler
private RestTemplate rest;
private ApiProperties apiProps;
public OrderSubmitMessageHandler(
ApiProperties apiProps, RestTemplate rest) {
this.apiProps = apiProps;
this.rest = rest;
}
@Override
public Object handle(Order order, Map
rest.postForObject(apiProps.getUrl(), order, String.class);
return null;
}
}
Чтобы удовлетворить требования интерфейса GenericHandler, OrderSubmitMessageHandler переопределяет метод handle(). Этот метод получает входящий объект Order и использует внедренный RestTemplate для отправки Order посредством POST запроса на URL-адрес, полученный из объекте ApiProperties. Наконец, метод handle() возвращает null, чтобы указать, что этот обработчик отмечает конец потока.
ApiProperties используется, чтобы избежать жесткого кодирования URL-адреса при вызове postForObject(). Это файл свойств конфигурации, который выглядит следующим образом:
@Data
@ConfigurationProperties(prefix="tacocloud.api")
@Componentpublic class ApiProperties {
private String url;
}
А в application.yml URL-адрес для Taco Cloud API может быть настроен следующим образом:
tacocloud:
api:
url: http://api.tacocloud.com
Чтобы сделать RestTemplate доступным в проекте, чтобы его можно было внедрить в OrderSubmitMessageHandler, необходимо добавить веб-стартер Spring Boot в сборку проекта:
<