«1. Введение

В этой статье будут представлены основные концепции Spring Integration в основном на небольших практических примерах.

Spring Integration предоставляет множество мощных компонентов, которые могут значительно улучшить взаимосвязь систем и процессов в архитектуре предприятия.

Он воплощает в себе некоторые из лучших и самых популярных шаблонов проектирования, помогая разработчикам избежать создания собственных шаблонов.

Мы рассмотрим конкретные потребности, которые эта библиотека заполняет в корпоративном приложении, и почему она предпочтительнее некоторых ее альтернатив. Мы также рассмотрим некоторые доступные инструменты для дальнейшего упрощения разработки приложений на основе Spring Integration.

2. Настройка

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-core</artifactId>
    <version>4.3.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-file</artifactId>
    <version>4.3.5.RELEASE</version>
</dependency>

Последние версии Spring Integration Core и Spring Integration File Support можно загрузить с Maven Central.

3. Шаблон обмена сообщениями

Одним из основополагающих шаблонов в этой библиотеке является обмен сообщениями. Шаблон сосредоточен вокруг сообщений — дискретных полезных нагрузок данных, которые перемещаются из исходной системы или процесса в одну или несколько систем или процессов по заранее определенным каналам.

Исторически шаблон возник как наиболее гибкий способ интеграции нескольких разрозненных систем таким образом, чтобы:

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

4. Интеграция обмена сообщениями в действии.

Приведенный выше код настраивает активатор службы, канал интеграции и адаптер входящего канала.

@Configuration
@EnableIntegration
public class BasicIntegrationConfig{
    public String INPUT_DIR = "the_source_dir";
    public String OUTPUT_DIR = "the_dest_dir";
    public String FILE_PATTERN = "*.mpeg";

    @Bean
    public MessageChannel fileChannel() {
        return new DirectChannel();
    }

    @Bean
    @InboundChannelAdapter(value = "fileChannel", poller = @Poller(fixedDelay = "1000"))
    public MessageSource<File> fileReadingMessageSource() {
        FileReadingMessageSource sourceReader= new FileReadingMessageSource();
        sourceReader.setDirectory(new File(INPUT_DIR));
        sourceReader.setFilter(new SimplePatternFileListFilter(FILE_PATTERN));
        return sourceReader;
    }

    @Bean
    @ServiceActivator(inputChannel= "fileChannel")
    public MessageHandler fileWritingMessageHandler() {
        FileWritingMessageHandler handler = new FileWritingMessageHandler(new File(OUTPUT_DIR));
        handler.setFileExistsMode(FileExistsMode.REPLACE);
        handler.setExpectReply(false);
        return handler;
    }
}

Вскоре мы более подробно рассмотрим каждый из этих типов компонентов. Аннотация @EnableIntegration обозначает этот класс как конфигурацию Spring Integration.

Давайте запустим наш контекст приложения Spring Integration:

Основной метод выше запускает контекст интеграции; он также принимает ввод символа «q» из командной строки для выхода из программы. Разберем компоненты подробнее.

public static void main(String... args) {
    AbstractApplicationContext context 
      = new AnnotationConfigApplicationContext(BasicIntegrationConfig.class);
    context.registerShutdownHook();
    
    Scanner scanner = new Scanner(System.in);
    System.out.print("Please enter q and press <enter> to exit the program: ");
    
    while (true) {
       String input = scanner.nextLine();
       if("q".equals(input.trim())) {
          break;
      }
    }
    System.exit(0);
}

5. Компоненты интеграции Spring

5.1. Сообщение

Интерфейс org.springframework.integration.Message определяет Spring Message: единицу передачи данных в контексте Spring Integration.

Он определяет средства доступа к двум ключевым элементам:

public interface Message<T> {
    T getPayload();
    MessageHeaders getHeaders();
}

Заголовки сообщений, по сути, контейнер ключ-значение, который можно использовать для передачи метаданных, как определено в классе org.springframework.integration.MessageHeaders Полезная нагрузка сообщения, которые представляют собой фактические данные, которые представляют ценность для передачи — в нашем случае видеофайл является полезной нагрузкой

    5.2. Канал

Канал в Spring Integration (и, конечно же, EAI) — это основная сантехника в архитектуре интеграции. Это канал, по которому сообщения передаются из одной системы в другую.

Вы можете думать об этом как о буквальном канале, через который интегрированная система или процесс может передавать сообщения другим системам (или получать сообщения от них).

Каналы в Spring Integration бывают разных видов, в зависимости от ваших потребностей. Они в значительной степени настраиваются и могут использоваться «из коробки», без какого-либо пользовательского кода, но если у вас есть особые потребности, доступна надежная структура.

Каналы «точка-точка» (P2P) используются для установления линий связи «один к одному» между системами или компонентами. Один компонент публикует сообщение в канале, чтобы другой мог его подобрать. На каждом конце канала может быть только один компонент.

Как мы видели, настроить канал так же просто, как вернуть экземпляр DirectChannel:

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

@Bean
public MessageChannel fileChannel1() {
    return new DirectChannel();
}

@Bean
public MessageChannel fileChannel2() {
    return new DirectChannel();
}

@Bean
public MessageChannel fileChannel3() {
    return new DirectChannel();
}

«Каналы публикации-подписки (Pub-Sub) используются для установления линии связи «один ко многим» между системами или компонентами. Это позволит нам публиковать все 3 прямых канала, которые мы создали ранее.

Итак, следуя нашему примеру, мы можем заменить канал P2P каналом pub-sub:

Теперь мы преобразовали адаптер входящего канала для публикации в канал Pub-Sub. Это позволит нам отправлять файлы, которые считываются из исходной папки, в несколько мест назначения.

@Bean
public MessageChannel pubSubFileChannel() {
    return new PublishSubscribeChannel();
}

@Bean
@InboundChannelAdapter(value = "pubSubFileChannel", poller = @Poller(fixedDelay = "1000"))
public MessageSource<File> fileReadingMessageSource() {
    FileReadingMessageSource sourceReader = new FileReadingMessageSource();
    sourceReader.setDirectory(new File(INPUT_DIR));
    sourceReader.setFilter(new SimplePatternFileListFilter(FILE_PATTERN));
    return sourceReader;
}

5.3. Мост

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

В нашем случае мы можем использовать мост для подключения нашего канала Pub-Sub к трем различным каналам P2P (поскольку каналы P2P и Pub-Sub не могут быть подключены напрямую):

Приведенная выше конфигурация bean-компонента теперь соединяет pubSubFileChannel с тремя каналами P2P. Аннотация @BridgeFrom определяет мост и может применяться к любому количеству каналов, которым необходимо подписаться на канал Pub-Sub.

@Bean
@BridgeFrom(value = "pubSubFileChannel")
public MessageChannel fileChannel1() {
    return new DirectChannel();
}

@Bean
@BridgeFrom(value = "pubSubFileChannel")
public MessageChannel fileChannel2() {
    return new DirectChannel();
}

@Bean
@BridgeFrom(value = "pubSubFileChannel")
public MessageChannel fileChannel3() {
    return new DirectChannel();
}

Вышеприведенный код можно прочитать как «создание моста из pubSubFileChannel в fileChannel1, fileChannel2 и fileChannel3, чтобы сообщения из pubSubFileChannel могли передаваться по всем трем каналам одновременно».

5.4. Service Activator

Service Activator — это любой POJO, который определяет аннотацию @ServiceActivator для данного метода. Это позволяет нам выполнять любой метод в нашем POJO, когда сообщение получено из входящего канала, и позволяет нам писать сообщения во внешний канал.

В нашем примере наш сервисный активатор получает файл из настроенного входного канала и записывает его в настроенную папку.

5.5. Адаптер

Адаптер — это компонент, основанный на шаблоне корпоративной интеграции, который позволяет «подключаться» к системе или источнику данных. Это почти буквально адаптер, который мы знаем по подключению к настенной розетке или электронному устройству.

Это позволяет повторно использовать подключение к другим системам «черного ящика», таким как базы данных, FTP-серверы и системы обмена сообщениями, такие как JMS, AMQP, и социальные сети, такие как Twitter. Повсеместная потребность в подключении к этим системам означает, что адаптеры очень портативны и многоразовые (на самом деле существует небольшой каталог адаптеров, находящихся в свободном доступе и готовых к использованию кем угодно).

Адаптеры делятся на две большие категории — входящие и исходящие.

Давайте рассмотрим эти категории в контексте адаптеров, используемых в нашем примерном сценарии:

Входящие адаптеры, как мы видели, используются для доставки сообщений из внешней системы (в данном случае из каталога файловой системы).

Наша конфигурация входящего адаптера состоит из:

Аннотации @InboundChannelAdapter, которая помечает конфигурацию bean-компонента как адаптер — мы настраиваем канал, на который адаптер будет передавать свои сообщения (в нашем случае файл MPEG) и опросчик, компонент, который помогает адаптеру опрашивать настроенную папку с заданным интервалом. Стандартный класс конфигурации Java Spring, который возвращает FileReadingMessageSource, реализацию класса интеграции Spring, которая обрабатывает опрос файловой системы

    Исходящие адаптеры используются для отправки сообщений наружу. Spring Integration поддерживает большое количество готовых адаптеров для различных распространенных случаев использования.

6. Заключение

Мы рассмотрели базовый вариант использования Spring Integration, который демонстрирует конфигурацию библиотеки на основе Java и возможность повторного использования доступных компонентов.

Код Spring Integration можно развернуть как отдельный проект в JavaSE, а также как часть чего-то большего в среде Jakarta EE. Хотя он не конкурирует напрямую с другими ориентированными на EAI продуктами и шаблонами, такими как корпоративные сервисные шины (ESB), он представляет собой жизнеспособную и легкую альтернативу решению многих из тех же проблем, для решения которых были созданы ESB.

Исходный код этой статьи можно найти в проекте Github.

«