Spring Boot 消息队列与异步处理

4 阅读5分钟
28.2.2 异步处理的定义

定义:异步处理是指应用程序在处理请求时,不阻塞主线程,而是将请求发送到消息队列,由其他线程或进程处理。
作用

  • 提高应用程序的响应速度。
  • 提高应用程序的吞吐量。
  • 提高应用程序的可扩展性。

✅ 结论:异步处理是指应用程序在处理请求时,不阻塞主线程,作用是提高应用程序的响应速度、吞吐量、可扩展性。

28.3 Spring Boot与消息队列的集成

Spring Boot与消息队列的集成是Java开发中的重要内容。

28.3.1 集成RabbitMQ的步骤

定义:集成RabbitMQ的步骤是指使用Spring Boot与RabbitMQ集成的方法。
步骤

  1. 创建Spring Boot项目。
  2. 添加所需的依赖。
  3. 配置RabbitMQ。
  4. 创建消息生产者。
  5. 创建消息消费者。
  6. 测试应用。

示例
pom.xml文件中的依赖:

<dependencies>
    <!-- Web依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- RabbitMQ依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    
    <!-- 测试依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

AI写代码xml
1234567891011121314151617181920

application.properties文件中的配置:

# 服务器端口
server.port=8080

# RabbitMQ连接信息
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

AI写代码properties
12345678

消息生产者类:

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ProductMessageProducer {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    private static final String EXCHANGE_NAME = "product-exchange";
    private static final String ROUTING_KEY = "product-routing-key";
    
    public void sendProductMessage(String message) {
        rabbitTemplate.convertAndSend(EXCHANGE_NAME, ROUTING_KEY, message);
        System.out.println("消息已发送:" + message);
    }
}

AI写代码java
运行
1234567891011121314151617

消息消费者类:

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class ProductMessageConsumer {
    @RabbitListener(queues = "product-queue")
    public void receiveProductMessage(String message) {
        System.out.println("消息已接收:" + message);
        // 处理消息的业务逻辑
        processProductMessage(message);
    }
    
    private void processProductMessage(String message) {
        // 模拟处理消息的业务逻辑
        try {
            Thread.sleep(2000);
            System.out.println("消息处理完成:" + message);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

AI写代码java
运行
12345678910111213141516171819202122

RabbitMQ配置类:

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {
    @Bean
    public DirectExchange productExchange() {
        return new DirectExchange("product-exchange");
    }
    
    @Bean
    public Queue productQueue() {
        return new Queue("product-queue");
    }
    
    @Bean
    public Binding productBinding(Queue productQueue, DirectExchange productExchange) {
        return BindingBuilder.bind(productQueue).to(productExchange).with("product-routing-key");
    }
}

AI写代码java
运行
123456789101112131415161718192021222324

控制器类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/products")
public class ProductController {
    @Autowired
    private ProductMessageProducer productMessageProducer;
    
    @PostMapping("/send")
    public String sendProductMessage(@RequestBody String message) {
        productMessageProducer.sendProductMessage(message);
        return "消息已发送";
    }
}

AI写代码java
运行
123456789101112131415

应用启动类:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

AI写代码java
运行
123456789

测试类:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class RabbitMQApplicationTests {
    @LocalServerPort
    private int port;
    
    @Autowired
    private TestRestTemplate restTemplate;
    
    @Test
    void contextLoads() {
    }
    
    @Test
    void testSendProductMessage() {
        String message = "Hello, RabbitMQ!";
        String response = restTemplate.postForObject("http://localhost:" + port + "/api/products/send", message, String.class);
        assertThat(response).contains("消息已发送");
    }
}

AI写代码java
运行
123456789101112131415161718192021222324252627

✅ 结论:集成RabbitMQ的步骤包括创建Spring Boot项目、添加所需的依赖、配置RabbitMQ、创建消息生产者、创建消息消费者、测试应用。

28.4 Spring Boot的实际应用场景

在实际开发中,Spring Boot消息队列与异步处理的应用场景非常广泛,如:

  • 实现产品信息的异步处理。
  • 实现用户信息的异步处理。
  • 实现订单信息的异步处理。
  • 实现支付信息的异步处理。

示例

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
class ProductMessageProducer {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    private static final String EXCHANGE_NAME = "product-exchange";
    private static final String ROUTING_KEY = "product-routing-key";
    
    public void sendProductMessage(String message) {
        rabbitTemplate.convertAndSend(EXCHANGE_NAME, ROUTING_KEY, message);
        System.out.println("消息已发送:" + message);
    }
}

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
class ProductMessageConsumer {
    @RabbitListener(queues = "product-queue")
    public void receiveProductMessage(String message) {
        System.out.println("消息已接收:" + message);
        processProductMessage(message);
    }
    
    private void processProductMessage(String message) {
        try {
            Thread.sleep(2000);
            System.out.println("消息处理完成:" + message);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
class RabbitMQConfig {
    @Bean
    public DirectExchange productExchange() {
        return new DirectExchange("product-exchange");
    }
    
    @Bean
    public Queue productQueue() {
        return new Queue("product-queue");
    }
    
    @Bean
    public Binding productBinding(Queue productQueue, DirectExchange productExchange) {
        return BindingBuilder.bind(productQueue).to(productExchange).with("product-routing-key");
    }
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/products")
class ProductController {
    @Autowired
    private ProductMessageProducer productMessageProducer;
    
    @PostMapping("/send")
    public String sendProductMessage(@RequestBody String message) {
        productMessageProducer.sendProductMessage(message);
        return "消息已发送";
    }
}

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

// 测试类
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class RabbitMQApplicationTests {
    @LocalServerPort
    private int port;
    
    @Autowired
    private TestRestTemplate restTemplate;
    
    @Test
    void contextLoads() {
    }
    
    @Test
    void testSendProductMessage() {
        String message = "Hello, RabbitMQ!";
        String response = restTemplate.postForObject("http://localhost:" + port + "/api/products/send", message, String.class);
        assertThat(response).contains("消息已发送");
    }
}

AI写代码java
运行
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107

✅ 结论:在实际开发中,Spring Boot消息队列与异步处理的应用场景非常广泛,需要根据实际问题选择合适的消息队列和异步处理方法。

总结

本章我们学习了Spring Boot消息队列与异步处理,包括消息队列的定义与特点、异步处理的定义与特点、Spring Boot与消息队列的集成、Spring Boot的实际应用场景,学会了在实际开发中处理消息队列与异步处理问题。其中,消息队列的定义与特点、异步处理的定义与特点、Spring Boot与消息队列的集成、Spring Boot的实际应用场景是本章的重点内容。从下一章开始,我们将学习Spring Boot的其他组件、微服务等内容。