Einführung in die Spring Integration

1. Einführung

In diesem Artikel werden die Kernkonzepte von Spring Integration ** vor allem anhand von kleinen praktischen Beispielen vorgestellt.

Spring Integration bietet viele leistungsstarke Komponenten, die die Interkonnektivität von Systemen und Prozessen innerhalb einer Unternehmensarchitektur erheblich verbessern können.

Es verkörpert einige der besten und beliebtesten Designmuster und hilft Entwicklern, das Rollen der eigenen zu vermeiden.

Wir werden einen Blick auf die spezifischen Anforderungen werfen, die diese Bibliothek in einer Unternehmensanwendung erfüllt, und warum sie bei einigen ihrer Alternativen ratsam ist. Wir werden uns auch einige verfügbare Tools ansehen, um die Entwicklung von Spring Integration-basierten Anwendungen weiter zu vereinfachen.

2. Konfiguration

<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>

Sie können die neuesten Versionen von Spring Integration Core und die https://-Suche herunterladen. maven.org/classic/#search%7Cga%7C1%7Cspring-integration-file[Spring-Integrationsdatei-Unterstützung]von Maven Central.

3. Das Messaging-Muster

Eines der grundlegenden Muster in dieser Bibliothek ist Messaging. Das Muster konzentriert sich auf Nachrichten - diskrete Nutzlasten von Daten, die sich von einem Ursprungssystem oder -prozess über vordefinierte Kanäle zu einem oder mehreren Systemen oder Prozessen bewegen.

In der Vergangenheit war das Muster der flexibelste Weg, um mehrere unterschiedliche Systeme auf folgende Weise zu integrieren:

  • Koppelt die an der Integration beteiligten Systeme nahezu vollständig aus

  • Erlaubt Teilnehmersystemen bei der Integration vollständig

agnostisch voneinander abhängige Protokolle, Formatierungen oder andere Implementierungsdetails ** Ermutigt zur Entwicklung und Wiederverwendung von Komponenten, die an der EU beteiligt sind

Integration

4. Messaging-Integration in Aktion

Betrachten wir ein einfaches Beispiel , das eine MPEG-Videodatei aus einem bestimmten Ordner in einen anderen konfigurierten Ordner kopiert:

@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;
    }
}

Der obige Code konfiguriert einen Dienstaktivator, einen Integrationskanal und einen Inbound-Channel-Adapter.

Wir werden jeden dieser Komponententypen in Kürze genauer untersuchen.

Die Annotation @ EnableIntegration kennzeichnet diese Klasse als Spring-Integrationskonfiguration.

Beginnen wir mit dem Kontext der Spring Integration-Anwendung:

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);
}

Die obige Hauptmethode startet den Integrationskontext. Er akzeptiert auch die Eingabe des „ q “ -Zeichens über die Befehlszeile, um das Programm zu verlassen. Lassen Sie uns die Komponenten genauer untersuchen.

5. Federintegrationskomponenten

5.1. Botschaft

Die Schnittstelle org.springframework.integration.Message definiert die Federnachricht: Die Einheit der Datenübertragung innerhalb eines Spring-Integrationskontexts.

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

Es definiert Accessors für zwei Schlüsselelemente:

  • Nachrichtenköpfe, im Wesentlichen ein Schlüsselwertcontainer, der verwendet werden kann

Übertragen von Metadaten, wie in definiert org.springframework.integration.MessageHeaders class ** Die Nachrichtennutzlast, dh die eigentlichen Daten, deren Wert angezeigt werden soll

übertragen - in unserem Anwendungsfall ist die Videodatei die Nutzlast

5.2. Kanal

Ein Kanal in Spring Integration (und in der Tat EAI) ist die grundlegende Installation in einer Integrationsarchitektur. Es ist die Pipe, über die Nachrichten von einem System an ein anderes weitergeleitet werden.

Sie können es sich als eine literale Pipe vorstellen, durch die ein integriertes System oder ein integrierter Prozess Nachrichten an andere Systeme senden (oder Nachrichten von ihnen empfangen) kann.

Channels in Spring Integration sind je nach Bedarf in verschiedenen Ausführungen erhältlich. Sie sind weitgehend konfigurierbar und ohne benutzerdefinierten Code sofort einsatzbereit. Falls Sie jedoch spezielle Anforderungen haben, steht ein stabiles Framework zur Verfügung.

  • Punkt-zu-Punkt-Kanäle (P2P) ** werden verwendet, um 1: 1-Kommunikationsleitungen zwischen Systemen oder Komponenten herzustellen. Eine Komponente veröffentlicht eine Nachricht an den Kanal, damit eine andere sie abholen kann. Es kann nur eine Komponente an jedem Ende des Kanals vorhanden sein.

Wie wir gesehen haben, ist das Konfigurieren eines Kanals so einfach wie das Zurückgeben einer Instanz von DirectChannel :

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

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

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

Hier haben wir drei separate Kanäle definiert, die alle mit dem Namen ihrer jeweiligen Getter-Methode gekennzeichnet sind.

  • Publish-Subscribe (Pub-Sub) ** -Kanäle werden verwendet, um eine Kommunikationsverbindung zwischen Systemen oder Komponenten herzustellen. Dies ermöglicht uns die Veröffentlichung in allen drei der zuvor erstellten direkten Kanäle.

So können wir unserem Beispiel folgend den P2P-Kanal durch einen Pub-Sub-Kanal ersetzen:

@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;
}

Wir haben jetzt den Inbound-Channel-Adapter für die Veröffentlichung in einem Pub-Sub-Channel konvertiert. Dadurch können wir die Dateien, die gerade aus dem Quellordner gelesen werden, an mehrere Ziele senden.

5.3. Brücke

Eine Bridge in Spring Integration wird verwendet, um zwei Nachrichtenkanäle oder Adapter zu verbinden, wenn sie aus irgendeinem Grund nicht direkt verbunden werden

In unserem Fall können wir eine Brücke verwenden, um unseren Pub-Sub-Kanal mit drei verschiedenen P2P-Kanälen zu verbinden (da P2P- und Pub-Sub-Kanäle nicht direkt verbunden werden können):

@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();
}

Die obige Bean-Konfiguration verbindet nun den pubSubFileChannel mit drei P2P-Kanälen. Die @ BridgeFrom -Annotation definiert eine Brücke und kann auf eine beliebige Anzahl von Kanälen angewendet werden, die für den Pub-Sub-Kanal abonniert werden müssen.

Wir können den obigen Code als "eine Brücke von pubSubFileChannel nach fileChannel1, fileChannel2 und fileChannel3 erstellen, damit Nachrichten von pubSubFileChannel gleichzeitig an alle drei Kanäle geleitet werden können."

5.4. Dienstaktivator

Der Dienstaktivator ist ein beliebiger POJO, der die Annotation @ ServiceActivator für eine bestimmte Methode definiert. Dies ermöglicht uns, jede Methode in unserem POJO auszuführen, wenn eine Nachricht von einem eingehenden Kanal empfangen wird, und es ermöglicht uns, Nachrichten in einen externen Kanal zu schreiben.

In unserem Beispiel empfängt unser Dienstaktivator eine Datei vom konfigurierten input channel und schreibt sie in den konfigurierten Ordner.

5.5. Adapter

Bei dem Adapter handelt es sich um eine musterbasierte Komponente für die Integration von Unternehmen, die es einem ermöglicht, ein System oder eine Datenquelle zu "stecken". Es ist fast buchstäblich ein Adapter, wie wir ihn vom Stecken in eine Steckdose oder ein elektronisches Gerät kennen.

Es ermöglicht wiederverwendbare Konnektivität zu ansonsten „Black-Box“ -Systemen wie Datenbanken, FTP-Servern und Messagingsystemen wie JMS, AMQP und sozialen Netzwerken wie Twitter. Die Allgegenwart der Notwendigkeit, eine Verbindung zu diesen Systemen herzustellen, bedeutet, dass Adapter sehr portabel und wiederverwendbar sind (in der Tat gibt es einen kleinen http://cocs.spring.io/spring-integration/reference/html/endpoint-summary.html Adapter], frei verfügbar und für jedermann einsatzbereit).

  • Adapter lassen sich in zwei große Kategorien einteilen - Inbound und Outbound. **

Untersuchen wir diese Kategorien im Kontext der in unserem Beispielszenario verwendeten Adapter:

  • Inbound-Adapter ** werden, wie wir gesehen haben, verwendet, um Nachrichten vom externen System (in diesem Fall ein Dateisystemverzeichnis) einzugeben.

Unsere Inbound-Adapter-Konfiguration besteht aus:

  • Eine @ InboundChannelAdapter -Annotation, die die Bean markiert

Konfiguration als Adapter - wir konfigurieren den Kanal, auf den der Der Adapter füttert seine Nachrichten (in unserem Fall eine MPEG-Datei) und a poller , eine Komponente, die dem Adapter hilft, den konfigurierten Ordner abzufragen im angegebenen Intervall ** Eine standard Spring Java-Konfigurationsklasse, die a zurückgibt

FileReadingMessageSource, die Implementierung der Spring Integration-Klasse, die das Abfragen des Dateisystems abwickelt

  • Outbound-Adapter ** werden verwendet, um Nachrichten nach außen zu senden. Spring Integration unterstützt eine Vielzahl von sofort einsatzbereiten Adaptern für verschiedene Anwendungsfälle.

6. Fazit

Wir haben einen grundlegenden Anwendungsfall mit Spring Integration untersucht, der die Java-basierte Konfiguration der Bibliothek und die Wiederverwendbarkeit der verfügbaren Komponenten demonstriert.

Spring Integration Code kann sowohl als eigenständiges Projekt in JavaSE als auch als Teil eines größeren Teils in einer JavaEE-Umgebung bereitgestellt werden.

Obwohl es nicht direkt mit anderen EAI-zentrierten Produkten und Mustern wie Enterprise Service Buses (ESBs) konkurriert, ist es eine praktikable, leichte Alternative zur Lösung vieler der Probleme, mit denen ESBs zu lösen waren.

Den Quellcode für diesen Artikel finden Sie unter https://github.com/eugenp/tutorials/tree/master/spring-integration [im Github-Projekt.