从零开始学习Spring boot 结合 Rabbitmq

RabbitMQ实战

目录

一、添加依赖

二、在application.yml 或者 application.properties文件中进行RabbitMQ的相关配置

三、确认Rabbitmq是启动的并且是能够连接上的

四、简单测试(代码)

五、进阶测试(代码)

 

 

闲言碎语不要讲,安排

开始前,我觉着有必要先了解下相关概念,便于后续开展:


Broker:它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保证数据能按照指定的方式进行传输, 
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。 
Queue:消息的载体,每个消息都会被投到一个或多个队列。 
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来. 
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。 
vhost:虚拟主机,一个broker里可以有多个vhost,用作不同用户的权限分离。 
Producer:消息生产者,就是投递消息的程序. 
Consumer:消息消费者,就是接受消息的程序. 
Channel:消息通道,在客户端的每个连接里,可建立多个channel.

--------------------- 
 

一、添加依赖

二、在配置文件对Rabbitmq进行配置

yaml格式

 

properti格式:

 

三、确认Rabbitmq是启动的并且是能够连接上的

首先,确保你的RabbitMQ已经安装好,并且已经启动,在你的本地确实可以连接的上(关于RabbitMQ的安装和相关配置在《rabbitmq集群搭建》进行设置,具体请自行查阅,谢谢。

 

四、简单测试(这是一对一的演示  另外一对多  多对多就不在这演示了)

这里说的一对多是指一个生产者对应多个消费者  多对多是多个生产者对应多个消费者

(1)配置队列:

package com.hh.demo;
 
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
/**
 * @Description:队列配置,队列的名称,发送者和接受者的名称必须一致,否则接收不到消息
 */
@Configuration
public class RabbitMqConfig {
    @Bean
    public Queue Queue1() {
        return new Queue("hhTest1");
    }
}


(2)发送者通过Controller类发送消息:

package com.hh.demo.controller;
 
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import java.util.Date;
 
@RestController
public class SendController {
    @Autowired
    private AmqpTemplate amqpTemplate;
 
    @RequestMapping("/send")
    public String send(){
        String content="Date:"+new Date();
        amqpTemplate.convertAndSend("hhTest1",content);
        return content;
    }
}


(3)创建接受者Receiver1,新建类:

package com.hh.demo.Receiver;
 
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
 
@Component
@RabbitListener(queues = "hhTest1")
public class Receiver1 {
 
    @RabbitHandler
    public void receiver(String msg){
        System.out.println("Test1 receiver1:"+msg);
    }
}

 

(4)测试

浏览器访问地址:http://localhost:8080/send,如下图:

终端输出接受的内容:

 

接下来演示下:

 

 

topic ExChange示例

topic 是RabbitMQ中最灵活的一种方式,可以根据binding_key自由的绑定不同的队列

首先对topic规则配置,这里使用两个队列来测试(也就是在Application类中创建和绑定的topic.message和topic.messages两个队列),其中topic.message的bindting_key为

“topic.message”,topic.messages的binding_key为“topic.#”;

生产者:

package com.rabbit.topic;

import java.util.Date;

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

@Component
public class TopicSender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send() {
        String msg1 = "I am topic.mesaage msg======";
        System.out.println("sender1 : " + msg1);
        this.rabbitTemplate.convertAndSend("exchange", "topic.message", msg1);
        
        String msg2 = "I am topic.mesaages msg########";
        System.out.println("sender2 : " + msg2);
        this.rabbitTemplate.convertAndSend("exchange", "topic.messages", msg2);
    }

}

消费者1(topic.message)

package com.rabbit.topic;

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

@Component
@RabbitListener(queues = "topic.message")
public class topicMessageReceiver {

    @RabbitHandler
    public void process(String msg) {
        System.out.println("topicMessageReceiver  : " +msg);
    }

}

 

消费者2(topic.messages)

package com.rabbit.topic;

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

@Component
@RabbitListener(queues = "topic.messages")
public class topicMessagesReceiver {

    @RabbitHandler
    public void process(String msg) {
        System.out.println("topicMessagesReceiver  : " +msg);
    }

}
controller:
    /**
     * topic exchange类型rabbitmq测试
     */
    @PostMapping("/topicTest")
    public void topicTest() {
           topicSender.send();
    }

 

用post方式执行:

http://127.0.0.1:8080/rabbit/topicTest

结果如下:

sender1 : I am topic.mesaage msg======
sender2 : I am topic.mesaages msg########
topicMessageReceiver  : I am topic.mesaage msg======
topicMessagesReceiver  : I am topic.mesaage msg======
topicMessagesReceiver  : I am topic.mesaages msg########
由以上结果可知:sender1发送的消息,routing_key是“topic.message”,所以exchange里面的绑定的binding_key是“topic.message”,topic.#都符合路由规则;所以sender1

发送的消息,两个队列都能接收到;

sender2发送的消息,routing_key是“topic.messages”,所以exchange里面的绑定的binding_key只有topic.#都符合路由规则;所以sender2发送的消息只有队列

topic.messages能收到。
 

fanout ExChange示例

Fanout 就是我们熟悉的广播模式或者订阅模式,给Fanout转发器发送消息,绑定了这个转发器的所有队列都收到这个消息。

这里使用三个队列来测试(也就是在Application类中创建和绑定的fanout.A、fanout.B、fanout.C)这三个队列都和Application中创建的fanoutExchange转发器绑定。

生产者:

package com.rabbit.fanout;

import java.util.Date;

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

@Component
public class FanoutSender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send() {
        String msgString="fanoutSender :hello i am hh";
        System.out.println(msgString);
        this.rabbitTemplate.convertAndSend("fanoutExchange","abcd.ee", msgString);
    }

}

消费者A:

package com.rabbit.fanout;

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

@Component
@RabbitListener(queues = "fanout.A")
public class FanoutReceiverA {

    @RabbitHandler
    public void process(String msg) {
        System.out.println("FanoutReceiverA  : " + msg);
    }

}

消费者b:

package com.rabbit.fanout;

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

@Component
@RabbitListener(queues = "fanout.B")
public class FanoutReceiverB {

    @RabbitHandler
    public void process(String msg) {
        System.out.println("FanoutReceiverB  : " + msg);
    }

}

消费者c:

package com.rabbit.fanout;

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

@Component
@RabbitListener(queues = "fanout.C")
public class FanoutReceiverC {

    @RabbitHandler
    public void process(String msg) {
        System.out.println("FanoutReceiverC  : " + msg);
    }

}

 

controller:

    /**
     * fanout exchange类型rabbitmq测试
     */
    @PostMapping("/fanoutTest")
    public void fanoutTest() {
           fanoutSender.send();
    }

用post方式执行:

http://127.0.0.1:8080/rabbit/fanoutTest

结果如下:

fanoutSender :hello i am hh
FanoutReceiverC  : fanoutSender :hello i am hh
FanoutReceiverB  : fanoutSender :hello i am hh
FanoutReceiverA  : fanoutSender :hello i am hh
由以上结果可知:就算fanoutSender发送消息的时候,指定了routing_key为"abcd.ee",但是所有接收者都接受到了消息

带callback的消息发送

增加回调处理,这里不再使用application.properties默认配置的方式,会在程序中显示的使用文件中的配置信息。该示例中没有新建队列和exchange,用的是第5节中的topic.messages队列和exchange转发器。消费者也是第5节中的topicMessagesReceiver

rabbitmq配置类:

package com.rabbit.callback;

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;

public class RabbitConfig {
    
    @Value("${spring.rabbitmq.host}")
    private String addresses;
    
    @Value("${spring.rabbitmq.port}")
    private String port;

    @Value("${spring.rabbitmq.username}")
    private String username;

    @Value("${spring.rabbitmq.password}")
    private String password;

    @Value("${spring.rabbitmq.virtual-host}")
    private String virtualHost;

    @Value("${spring.rabbitmq.publisher-confirms}")
    private boolean publisherConfirms;
    
    @Bean
    public ConnectionFactory connectionFactory() {

        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(addresses+":"+port);
        connectionFactory.setUsername(username);
        connectionFactory.setPassword(password);
        connectionFactory.setVirtualHost(virtualHost);
        /** 如果要进行消息回调,则这里必须要设置为true */
        connectionFactory.setPublisherConfirms(publisherConfirms);
        return connectionFactory;
    }
    
    @Bean
    /** 因为要设置回调类,所以应是prototype类型,如果是singleton类型,则回调类为最后一次设置 */
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate rabbitTemplatenew() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        return template;
    }

}

 

生产者: 

package com.rabbit.callback;

import java.util.Date;
import java.util.UUID;

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

@Component
public class CallBackSender implements  RabbitTemplate.ConfirmCallback{
    @Autowired
    private RabbitTemplate rabbitTemplatenew;
    public void send() {
        
        rabbitTemplatenew.setConfirmCallback(this);
        String msg="callbackSender : i am callback sender";
        System.out.println(msg );
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());  
        System.out.println("callbackSender UUID: " + correlationData.getId());  
        this.rabbitTemplatenew.convertAndSend("exchange", "topic.messages", msg, correlationData);  
    }

    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        // TODO Auto-generated method stub
        System.out.println("callbakck confirm: " + correlationData.getId());
    }
}

 

消费者:第5节中的topicMessagesReceiver

controller:

    @PostMapping("/callback")
    public void callbak() {
        callBackSender.send();
    }

用post方式执行:

http://127.0.0.1:8080/rabbit/callback

结果如下:

callbackSender : i am callback sender
callbackSender UUID: cd0c80a6-4c65-4bf9-b4f8-f3b1180755d6
callbakck confirm: cd0c80a6-4c65-4bf9-b4f8-f3b1180755d6
topicMessagesReceiver  : callbackSender : i am callback sender
从上面可以看出callbackSender发出的UUID,收到了回应,又传回来了。

<think>嗯,用户想从零开始学习Spring Boot,我需要给他一个清晰的学习路径。首先,我得想想Spring Boot本身是什么,以及它的优势在哪里。Spring Boot是基于Spring框架的,简化了配置和部署,所以应该先介绍Spring的核心概念,比如IoC和AOP,这样用户有基础后再过渡到Spring Boot会更容易。 接下来,用户可能需要知道如何搭建开发环境。Java和Maven/Gradle是必须的,还有IDE的选择,比如IntelliJ IDEA或者Eclipse。创建一个简单的Hello World项目能帮助用户快速上手,体验Spring Boot的便利性。 然后,项目结构的部分,用户需要了解标准的目录布局,比如src/main/java和application.properties的作用。配置文件这一块,YAML和Properties文件的区别和使用场景也很重要,特别是如何通过配置覆盖默认设置。 控制层是Web应用的基础,要介绍@RestController和@RequestMapping注解,处理HTTP请求的方法。参数传递的方式,比如@PathVariable和@RequestParam,这些是开发API的关键点。 数据持久化部分,JPA和Hibernate的关系需要讲清楚,如何定义实体类和使用Repository接口。数据库配置,比如连接H2或MySQL,还有事务管理,这部分可能需要示例代码来演示。 RESTful API设计,符合规范的方法和状态码,Swagger的集成可以提升API的可维护性,用户可能对自动化文档工具感兴趣。 测试环节不容忽视,单元测试和集成测试的区别,MockMvc的使用,以及如何用JUnit和SpringBootTest来保证代码质量。 高级特性方面,自动配置原理、Starter的作用、Actuator监控,这些能帮助用户深入理解Spring Boot的内部机制,优化应用性能。 最后,部署和运维,打包成JAR/WAR,Docker化,以及结合Jenkins的CI/CD流程,这些都是实际项目中的必备技能。 学习资源推荐官方文档、书籍和在线课程,建议用户通过实际项目练习,参与开源社区,持续关注更新。可能用户是刚入门的开发者,需要从基础到进阶的系统指导,避免一开始陷入复杂的配置中,保持学习的兴趣和动力。需要确保步骤清晰,每个阶段都有明确的目标和示例,帮助用户逐步构建完整的知识体系。</think>### 从零学习 Spring Boot 分步指南 #### 1. **前置知识准备** - **Java 基础** 掌握面向对象编程、集合框架、异常处理等,需熟悉 Java 8+ 特性(如 Lambda 表达式)。 - **Maven/Gradle** 了解依赖管理工具的基本使用,例如: ```xml <!-- Maven 依赖示例 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ``` - **HTTP 协议与 RESTful API** 理解 GET/POST 请求、状态码和资源表述格式(JSON/XML)。 #### 2. **Spring Boot 核心概念** - **核心优势** - 自动配置(Auto-Configuration) - 内嵌服务器(Tomcat/Jetty) - 简化依赖管理(Starter POMs) - **关键注解** `@SpringBootApplication`(启动类)、`@RestController`、`@Autowired` #### 3. **环境搭建** - **工具链安装** - JDK 11+ - IDE:IntelliJ IDEA(推荐)或 Eclipse + STS 插件 - 使用 [Spring Initializr](https://start.spring.io/) 生成项目骨架 - **第一个项目** 创建 `HelloController.java`: ```java @RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello, Spring Boot!"; } } ``` 运行 `main` 方法后访问 `http://localhost:8080/hello` #### 4. **项目结构解析** - **标准目录** ``` src/ main/ java/ com.example.demo/ # 代码主目录 resources/ static/ # 静态资源 templates/ # 模板文件 application.yml # 配置文件 ``` #### 5. **数据访问实战** - **整合 JPA + MySQL** 1. 添加依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> ``` 2. 配置 `application.yml`: ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/testdb username: root password: 123456 jpa: hibernate: ddl-auto: update ``` 3. 定义实体与 Repository: ```java @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // getters/setters } public interface UserRepository extends JpaRepository<User, Long> {} ``` #### 6. **进阶技能路线** - **中间件集成** | 技术 | 实现方案 | |------------|---------------------------| | 缓存 | Redis + `@Cacheable` | | 消息队列 | RabbitMQ/Kafka | | 安全 | Spring Security + JWT | - **微服务架构** - 服务注册与发现:Eureka/Nacos - 配置中心:Spring Cloud Config - 网关:Spring Cloud Gateway #### 7. **调试与优化** - **常用工具** - Postman:API 测试 - Actuator:监控端点 `/actuator/health` - Lombok:简化 POJO 代码 - **性能调优** - 连接池配置(HikariCP) - JVM 参数优化 - 异步处理 `@Async` #### 8. **学习资源推荐** - **官方文档** [Spring Boot Reference](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/) - **书籍** 《Spring Boot 实战》《Spring 揭秘》 - **实战项目** - 博客系统(用户+文章+评论) - 电商秒杀系统(高并发场景) #### 附:核心原理图示 $$ \begin{aligned} &\text{Spring Boot 启动流程} \\ &1.\ \text{加载自动配置类} \\ &2.\ \text{创建 ApplicationContext} \\ &3.\ \text{执行 CommandLineRunner} \end{aligned} $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值