Java >> Java tutorial >  >> Tag >> Spring

Spring Integration DirectChannel Eksempel

1. Introduktion

Denne artikel diskuterer implementeringen af ​​Spring Integration Direct Channel i en Spring Boot-applikation.

Spring Integration understøtter Enterprise Integration-mønstre, hvoraf meddelelseskanalmønsteret afkobler producent- og forbrugerslutpunkter og er agnostisk over for meddelelsens nyttelast. En beskedkanal sørger for forbindelse med forskellige komponenter som filtre og adaptere. Der er gode artikler, der giver mere detaljerede oplysninger om forskellige typer af Spring Integration-meddelelseskanaler sammen med deres komponenter og aspekter. Jeg har listet et par stykker i afsnittet Nyttige links nedenfor til din yderligere reference.

Nøglefunktionen i DirectChannel er, at selvom det fungerer på public-subscribe-modellen, giver det hver besked, den modtager, til kun én af abonnenterne på en rund-robin måde. Det er således en kombination af både publish-subscribe og punkt-til-punkt overførselsmodellerne.

2. Ansøgning

Den applikation, vi vil bygge, er et bogbibliotek. Funktionaliteten er, at en bogudgiver sender bøger til biblioteket. Bibliotekaren sender de nyankomne til Prioritetslæsere. Lad os antage, at biblioteket er i en lille by og har begrænset budget, så det køber kun et eksemplar af hver bog. Bibliotekaren er en gammel og hyggelig herre, der sender en fin sms sammen med bogen, og modtagerne tager bogen og svarer med lige så varme. I øjeblikket sender Bogforlaget 20 bøger, og der er tre Premium-læsere, der har abonneret. Når bøgerne sendes af bibliotekaren, går én bog til én Premium Reader på en round-robin måde.

3. Miljø

Jeg har brugt følgende teknologier til denne applikation:

  • Java 1.8
  • Spring Boot 1.5.8
  • Maven 4.0
  • Ubuntu 16.04

4. Kildekode

Lad os se på filerne og koden. Dette er et Maven-projekt, så vi starter med pom-filen.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

    <groupId>org.javacodegeeks.springintegration.channels</groupId>
    <artifactId>directchannel</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>directchannel</name>
    <description>Spring Integration Direct Channel example</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Nedenfor er Book klasse, der fungerer som model for applikationen.

Book.java

package org.javacodegeeks.springintegration.channels.directchannel.model;

public class Book {

    public enum Genre {
        fantasy,
        horror,
        romance,
        thriller
    }

    private long bookId;
    private String title;
    private Genre genre;

    public Book() {}

    public long getBookId() {
        return bookId;
    }

    public void setBookId(long bookId) {
        this.bookId = bookId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Genre getGenre() {
        return genre;
    }

    public void setGenre(Genre genre) {
        this.genre = genre;
    }

    public String toString() {
        return String.format("Book %s, Genre: %s.", title, genre);
    }
}

En Book har en enum angiver hvilken genre det hører til. De to andre egenskaber er bookId og title .

Nedenfor er BookPublisher klasse, der starter meddelelsesflowet i applikationen.

BookPublisher.java

package org.javacodegeeks.springintegration.channels.directchannel.incoming;

import org.javacodegeeks.springintegration.channels.directchannel.model.Book;
import org.javacodegeeks.springintegration.channels.directchannel.model.Book.Genre;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class BookPublisher {
    private long nextBookId;

    public BookPublisher() {
        this.nextBookId = 1001l;
    }

    public List<Book> getBooks() {
        List<Book> books = new ArrayList<Book>();

        books.add(createFantasyBook());
        books.add(createFantasyBook());
        books.add(createFantasyBook());
        books.add(createFantasyBook());
        books.add(createFantasyBook());
        books.add(createHorrorBook());
        books.add(createHorrorBook());
        books.add(createHorrorBook());
        books.add(createHorrorBook());
        books.add(createHorrorBook());
        books.add(createRomanceBook());
        books.add(createRomanceBook());
        books.add(createRomanceBook());
        books.add(createRomanceBook());
        books.add(createRomanceBook());
        books.add(createThrillerBook());
        books.add(createThrillerBook());
        books.add(createThrillerBook());
        books.add(createThrillerBook());
        books.add(createThrillerBook());

        return books;
    }

    Book createFantasyBook() {
        return createBook("", Genre.fantasy);
    }

    Book createHorrorBook() {
        return createBook("", Genre.horror);
    }

    Book createRomanceBook() {
        return createBook("", Genre.romance);
    }

    Book createThrillerBook() {
        return createBook("", Genre.thriller);
    }

    Book createBook(String title, Genre genre) {
        Book book = new Book();
        book.setBookId(nextBookId++);
        if (title == "") {
            title = "# " + Long.toString(book.getBookId());
        }
        book.setTitle(title);
        book.setGenre(genre);

        return book;
    }
}

Hovedfunktionaliteten i denne klasse er at oprette og returnere en liste med tyve bøger, fem hver med genrerne fantasy, horror, romantik og thriller. Der er en bogoprettelsesmetode for hver genretype, som kalder en hjælpefunktion createBook ved at sende den korrekte enum type. Bog-id'er starter fra 1001 og indstilles trinvist.

Nedenfor er Librarian klasse, der er udgiverens slutpunkt for applikationen.

Librarian.java

package org.javacodegeeks.springintegration.channels.directchannel.pub;

import org.javacodegeeks.springintegration.channels.directchannel.model.Book;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.stereotype.Component;

@Component
public class Librarian {

    private DirectChannel channel;

    @Value("#{bookChannel}")
    public void setChannel(DirectChannel channel) {
        this.channel = channel;
    }

    public void sendPremiumReaders(Book book) {
        System.out.println("Dear Premium Reader, Just Arrived - " + book.toString());
        channel.send(MessageBuilder.withPayload(book).build());
    }
}

Denne klasse har en privat DirectChannel medlem, som er refereret til en kanal identificeret som bookChannel ved hjælp af @Value anmærkning. sendPremiumReaders metode bruges til at udgive en bog med dens nyttelast til DirectChannel .

Nedenfor er PremiumReader klasse, der er abonnentens slutpunkt for applikationen.

PremiumReader.java

package org.javacodegeeks.springintegration.channels.directchannel.sub;

import org.javacodegeeks.springintegration.channels.directchannel.model.Book;
import org.springframework.messaging.Message;
import org.springframework.integration.MessageRejectedException;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.MessageHandler;
import org.springframework.stereotype.Component;

@Component
public class PremiumReader implements MessageHandler {

    @Override
    public void handleMessage(Message<?> message) throws MessagingException {
        Object payload = message.getPayload();

        if (payload instanceof Book) {
            receiveAndAcknowledge((Book) payload);
        } else {
            throw new MessageRejectedException(message, "Unknown data type has been received.");
        }
    }

    void receiveAndAcknowledge(Book book) {
        System.out.println("Hi Librarian, this is Reader #" + System.identityHashCode(this) +
                           ". " + "Received book - " + book.toString() + "\n");
    }
}

I handleMessage metode, validerer den, at meddelelsens nyttelast er en Book instans og kalder metoden receiveAndAcknowledge for at udskrive en bekræftelsesmeddelelse til konsollen.

Nedenfor er DirectchannelApplication klasse, der er applikationens hovedklasse.

DirectchannelApplication.java

package org.javacodegeeks.channels.directchannel;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;

import org.springframework.integration.channel.DirectChannel;
import org.springframework.messaging.MessageChannel;

import org.javacodegeeks.springintegration.channels.directchannel.model.Book;
import org.javacodegeeks.springintegration.channels.directchannel.incoming.BookPublisher;
import org.javacodegeeks.springintegration.channels.directchannel.pub.Librarian;
import org.javacodegeeks.springintegration.channels.directchannel.sub.PremiumReader;

@SpringBootApplication
@ComponentScan(basePackages = "org.javacodegeeks.springintegration.channels.directchannel")
public class DirectchannelApplication {

    @Autowired
    private BookPublisher bookPublisher;

    @Autowired
    private Librarian librarian;

    @Autowired
    private DirectChannel library;

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

    public static void main(String[] args) {
        SpringApplication.run(DirectchannelApplication.class, args);
    }

    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {

            library.subscribe(new PremiumReader());
            library.subscribe(new PremiumReader());
            library.subscribe(new PremiumReader());

            List<Book> books = bookPublisher.getBooks();

            for (Book book : books) {
                librarian.sendPremiumReaders(book);
            }
        };
    }
}

Denne klasse er analog med biblioteket i den virkelige verden. Det tager abonnementer fra premium-læsere, får bøger fra bogudgiveren og sender derefter disse bøger til premium-læserne.

Den kobler automatisk BookPublisher , Librarian og DirectChannel bønner. Den har hjælpemetoden bookChannel for at oprette en DirectChannel som påberåbes af udgiverklassen Librarian .

Hvordan identificerer programmet den læser, der fik bogen? Simpelthen ved at ringe til System.identityHashCodePremiumReader objekt. Denne hash-kode er trykt i bekræftelsesteksten. I outputtet vist nedenfor kan du således se, at de 20 bøger går til de tre abonnerede PremiumReaders en hver, på en cirkulær måde.

Applikationsoutput, der viser, at hver modtager kun får én besked

5. Sådan kører du

Fra kommandolinjen skal du bruge enten mvn spring-boot:run eller mvn test .

6. Nyttige links

  • https://www.javacodegeeks.com/2014/05/spring-integration-4-0-a-complete-xml-free-example.html
  • https://www.javacodegeeks.com/2015/09/spring-integration-full-example.html
  • https://www.javacodegeeks.com/2015/01/high-available-amqp-backed-message-channels-via-spring-integration-and-rabbitmq.html

7. Download kildekoden


Java tag