Spring Cloud Stream of spring cloud: message driven

Keywords: Java Spring Maven xml Apache

Spring Cloud Stream is a framework for building message driven microservices. Based on Spring Boot, the framework integrates spring integration to connect message broker middleware (RabbitMQ, Kafka, etc.), provides personalized automatic configuration implementation, and introduces three core concepts: publish subscribe, consumption group and partition.
The application uses input channel or output channel to interact with the binder in Spring Cloud Stream, and uses configuration to bind. The binder of Spring Cloud Stream is responsible for interacting with middleware.

Development tool: IntelliJ idea February 3, 2019

I. server side

1. Create project

Create a new spring boot project named "spring server" in IDEA. Select 2.1.10 for the spring boot version. Check spring cloud discovery - > Eureka server in the dependency interface.
The complete content of pom.xml is as follows:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR4</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

</project>

2. Modify the configuration application.yml

Modify the port number to 8761; cancel the registration of your own information to Eureka server, and do not retrieve the registration information from Eureka server.

server:
  port: 8761
eureka:
  client:
    register-with-eureka: false
    fetch-registry: false

3. Modify startup code

Add annotation @ EnableEurekaServer

package com.example.springserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class SpringServerApplication {

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

}

II. Message producers

1. Create project
Create a new spring boot project named "spring producer" in IDEA. Select 2.1.10 for the spring boot version. Check Web - > spring web, spring cloud discovery - > Eureka discovery client in the dependency interface.
Open pom.xml and add a spring cloud starter stream rabbit. Spring cloud stream and spring cloud stream binder will be introduced automatically.
The complete content of pom.xml is as follows:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-producer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-producer</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR4</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

</project>

2. Modify the configuration application.yml

pom.xml uses rabbitmq, which by default connects to the local port 5672. The following rabbitmq can also be omitted.

server:
  port: 8081
spring:
  application:
    name: spring-producer
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
rabbitmq:
  host: localhost
  post: 5672
  username: guest
  password: guest

3. Write sending service

Method sendOrder uses the @ Output("myInput") annotation to represent the message channel where myInput is created. When this method is called, a message is posted to the myInput channel.
If the parameter myInput is not used, the method name is used as the channel name.

package com.example.springproducer;

import org.springframework.cloud.stream.annotation.Output;
import org.springframework.messaging.SubscribableChannel;

public interface SendService {
    @Output("myInput")
    SubscribableChannel sendOrder();
}

4. Modify startup code

Add the annotation @ EnableBinding to enable the binding function of the Spring container. Take SendService.class as the parameter. When the Spring container starts, the channel defined in the SendService interface will be bound automatically.

package com.example.springproducer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.stream.annotation.EnableBinding;

@SpringBootApplication
@EnableEurekaClient
@EnableBinding(SendService.class)
public class SpringProducerApplication {

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

}

5. Add a controller class

Call SendService's send method to send a message to the server.

package com.example.springproducer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ProducerController {

    @Autowired
    SendService sendService;

    @RequestMapping(value="/send",method= RequestMethod.GET)
    public String sendRequest(){
        //Create message
        Message msg = MessageBuilder.withPayload("hello world".getBytes()).build();
        //send message
        sendService.sendOrder().send(msg);
        return "SUCCESS";
    }
}

III. message consumers

1. Create project

Create a new spring boot project named "spring consumer" in IDEA. Select 2.1.10 for the spring boot version. Check Web - > spring web, spring cloud discovery - > Eureka discovery client in the dependency interface.
Open pom.xml and add dependency

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-consumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-consumer</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR4</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

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

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

</project>

2. Modify the configuration application.yml

server:
  port: 8080
spring:
  application:
    name: spring-consumer
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
rabbitmq:
  host: localhost
  post: 5672
  username: guest
  password: guest

3. Abbreviate the channel interface for receiving messages

package com.example.springconsumer;

import org.springframework.cloud.stream.annotation.Input;
import org.springframework.messaging.SubscribableChannel;

public interface ReceiveService {
    @Input("myInput")
    SubscribableChannel myInput();
}

4. Modify startup code

Also bind message channel

package com.example.springconsumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;

@SpringBootApplication
@EnableBinding(ReceiveService.class)
public class SpringConsumerApplication {

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

    //Subscribe myInput Message for channel
    @StreamListener("myInput")
    public void receive(byte[] msg){
        System.out.println("Message received:" + new String(msg));
    }
}

5, test

(1) check whether RabbitMQ in the service is started (default start);

(2) start spring server (port 8761);

(3) start spring producer (port 8081);

(4) start spring consumer (Port 8080);

(5) the browser accesses http://localhost:8081/send, the console output of the spring consumer project:

Message received: hello world

Indicates that the consumer can get the message from the message broker.

IV. replace the binder

RabbitMQ is used as the message broker above. If Kafka is used, Maven dependency implementation can be replaced.
In pom.xml of producers and consumers, change spring cloud starter stream rabbit to spring cloud starter stream Kafka.

Posted by courtewing on Sat, 23 Nov 2019 09:56:15 -0800