SpringBoot 整合RabbitMQ使用

添加用户。

在这里插入图片描述

  1. none
    不能访问 management plugin
  2. management
    列出自己可以通过AMQP登入的virtual hosts
    查看自己的virtual hosts中的queues, exchanges 和 bindings
    查看和关闭自己的channels 和 connections
    查看有关自己的virtual hosts的“全局”的统计信息,包含其他用户在这些virtual hosts中的活动。
  3. policymaker
    查看、创建和删除自己的virtual hosts所属的policies和parameters
  4. monitoring
    列出所有virtual hosts,包括他们不能登录的virtual hosts
    查看其他用户的connections和channels
    查看节点级别的数据如clustering和memory使用情况
    查看真正的关于所有virtual hosts的全局的统计信息
  5. administrator
    创建和删除virtual hosts
    查看、创建和删除users
    查看创建和删除permissions
    关闭其他用户的connections

导入jar包

<!--rabbitmq-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

添加配置

spring:
  #项目名
  application:
    name: rabbitmq-provider
  #配置rabbitMq 服务器
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: wsd
    password: rabbitmq
    #取决于自己是否需要使用,可以不用
    virtual-host: VirtualHosts1

配置文件释意(大概看一下)

  • base
    spring.rabbitmq.host: 服务Host
    spring.rabbitmq.port: 服务端口
    spring.rabbitmq.username: 登陆用户名
    spring.rabbitmq.password: 登陆密码
    spring.rabbitmq.virtual-host: 连接到rabbitMQ的vhost
    spring.rabbitmq.addresses: 指定client连接到的server的地址,多个以逗号分隔(优先取addresses,然后再取host)
    spring.rabbitmq.requested-heartbeat: 指定心跳超时,单位秒,0为不指定;默认60s
    spring.rabbitmq.publisher-confirms: 是否启用【发布确认】
    spring.rabbitmq.publisher-returns: 是否启用【发布返回】
    spring.rabbitmq.connection-timeout: 连接超时,单位毫秒,0表示无穷大,不超时
  • ssl
    spring.rabbitmq.ssl.enabled: 是否支持ssl spring.rabbitmq.ssl.key-store: 指定持有SSL certificate的key store的路径
    spring.rabbitmq.ssl.key-store-password: 指定访问key store的密码
    spring.rabbitmq.ssl.trust-store: 指定持有SSL certificates的Trust store
    spring.rabbitmq.ssl.trust-store-password: 指定访问trust store的密码
    spring.rabbitmq.ssl.algorithm: ssl使用的算法,例如,TLSv1.1
  • cache
    spring.rabbitmq.cache.channel.size: 缓存中保持的channel数量
    spring.rabbitmq.cache.channel.checkout-timeout:当缓存数量被设置时,从缓存中获取一个channel的超时时间,单位毫秒;如果为0,则总是创建一个新channel
    spring.rabbitmq.cache.connection.size: 缓存的连接数,只有是CONNECTION模式时生效
    spring.rabbitmq.cache.connection.mode: 连接工厂缓存模式:CHANNEL 和 CONNECTION
  • listener
    spring.rabbitmq.listener.simple.auto-startup: 是否启动时自动启动容器
    spring.rabbitmq.listener.simple.acknowledge-mode:表示消息确认方式,其有三种配置方式,分别是none、manual和auto;默认auto
    spring.rabbitmq.listener.simple.concurrency: 最小的消费者数量
    spring.rabbitmq.listener.simple.max-concurrency: 最大的消费者数量
    spring.rabbitmq.listener.simple.prefetch:指定一个请求能处理多少个消息,如果有事务的话,必须大于等于transaction数量.
    spring.rabbitmq.listener.simple.transaction-size:指定一个事务处理的消息数量,最好是小于等于prefetch的数量.
    spring.rabbitmq.listener.simple.default-requeue-rejected:决定被拒绝的消息是否重新入队;默认是true(与参数acknowledge-mode有系)
    spring.rabbitmq.listener.simple.idle-event-interval: 多少长时间发布空闲容器时间,单位毫秒 spring.rabbitmq.listener.simple.retry.enabled: 监听重试是否可用 spring.rabbitmq.listener.simple.retry.max-attempts: 最大重试次数
    spring.rabbitmq.listener.simple.retry.initial-interval:第一次和第二次尝试发布或传递消息之间的间隔
    spring.rabbitmq.listener.simple.retry.multiplier: 应用于上一重试间隔的乘数
    spring.rabbitmq.listener.simple.retry.max-interval: 最大重试时间间隔
    spring.rabbitmq.listener.simple.retry.stateless: 重试是有状态or无状态
  • template
    spring.rabbitmq.template.mandatory: 启用强制信息;默认false spring.rabbitmq.template.receive-timeout: receive() 操作的超时时间
    spring.rabbitmq.template.reply-timeout: sendAndReceive() 操作的超时时间
    spring.rabbitmq.template.retry.enabled: 发送重试是否可用
    spring.rabbitmq.template.retry.max-attempts: 最大重试次数
    spring.rabbitmq.template.retry.initial-interval: 第一次和第二次尝试发布或传递消息之间的间隔
    spring.rabbitmq.template.retry.multiplier: 应用于上一重试间隔的乘数
    spring.rabbitmq.template.retry.max-interval: 最大重试时间间隔

简单模式

在这里插入图片描述

创建生产者

@RestController
public class RabbitMqController {

    /**
     * jar包提供的,直接使用即可
     */
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * helloWorld模型
     * @param msg
     * @return
     */
    @GetMapping("/testMQ")
    public void testMQ(String msg) {
        rabbitTemplate.convertAndSend("hello", UUID.randomUUID()+msg);
    }
}

创建消费者

/**
 * Queue注解即用来创建队列
 * name,value:队列名称
 * durable:指定此队列是否应持久。默认情况下,如果提供队列名称,则该名称是持久的。
 * exclusive:如果不是排外的,可以使用两个消费者都访问同一个队列,如果是排外的,其他通道channel是不能访问的,如果强制访问会报异常
 * autoDelete:指定在不使用时是否应自动删除此队列。默认情况下,如果提供了队列名称,则不会自动删除它
 * 
 */
@Component
@RabbitListener(queuesToDeclare = @Queue(value = "hello",durable = "true",autoDelete = "false"))
public class HelloConsumer {

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

每当有访问控制台机会输出msg

consumer2cd79e7b-58e0-4703-a695-d06b69d02c35

工作模型

在这里插入图片描述
在简单模式上多加一个或者多个消费者。默认使用轮询分发,一个消费者分发一个1,2,1,2。

创建生产者

@RestController
public class RabbitMqController {

    /**
     * jar包提供的,直接使用即可
     */
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @GetMapping("/workMQ")
    public void workMQ(String msg) {
        rabbitTemplate.convertAndSend("work", UUID.randomUUID().toString()+msg);
    }

}

创建消费者

@Component
@RabbitListener(queuesToDeclare = @Queue(value = "work",durable = "true",autoDelete = "false"))
public class WorkConsumer1 {

    @RabbitHandler
    public void consumer(String msg){
        System.out.println("work1:"+msg);
    }
}
@Component
@RabbitListener(queuesToDeclare = @Queue(value = "work",durable = "true",autoDelete = "false"))
public class WorkConsumer2 {

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

控制台输出,可以很明显的看到是轮询分发模式

work1:f523b681-f968-4440-b011-7b6aa495f329work
work2:e81ebe0a-96f6-4054-945b-8163cfe26aa1work
work1:5a03e3da-f033-48e9-90f4-c6776c0b42e9work
work2:5dfafd21-bdb4-4bde-bb7f-9cda79c3a65ework
work1:2fa85677-9faa-4603-974e-89cd34426e33work
work2:e438defd-9c56-490b-817e-31e1169e3ad3work

工作模式-能者多劳模式

广播模型

会将消息同时广博给多个消费者,多个消费者都对同一条消息进行了消费。
在这里插入图片描述

创建生产者

注意一点,如果只有生产者,访问接口,并不会创建交换机。交换机在消费者才会创建

@RestController
public class RabbitMqController {

    /**
     * jar包提供的,直接使用即可
     */
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @GetMapping("/broadcastMQ")
    public void broadcast(String msg) {
        rabbitTemplate.convertAndSend("broadcast","", UUID.randomUUID().toString()+msg);
    }
}

创建消费者

创建两个消费者,以及两个队列,并且将队列与交换机(如果没有一并创建)进行绑定。

/**
 * QueueBinding 将队列与交换机进行绑定
 */
@Component
@RabbitListener(bindings = {
        @QueueBinding(
                value = @Queue(name = "broadcastQueue2"),
                exchange = @Exchange("broadcast")
        )})
public class BroadcastConsumer2 {

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

/**
 * QueueBinding 将队列与交换机进行绑定
 */
@Component
@RabbitListener(bindings = {
        @QueueBinding(
                value = @Queue(name = "broadcastQueue1"),
                exchange = @Exchange("broadcast")
        )})
public class BroadcastConsumer {

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

控制台输出,两个消费者都对同一条消息进行了消费

broadcastQueue2consumer1:f93077a6-b2c4-4519-9ade-4cfc14383914work
broadcastQueue1consumer:f93077a6-b2c4-4519-9ade-4cfc14383914work
broadcastQueue2consumer1:e5f66613-5856-4b9a-8858-0e76811c28cawork
broadcastQueue1consumer:e5f66613-5856-4b9a-8858-0e76811c28cawork

路由模型

在这里插入图片描述
相对广播模型而言,多了一个路由键,消息在投递到路由机上,会根据路由键选择消息往哪个队列投递

创建生产者

在发送消息时指定路由机以及路由键

@RestController
public class RabbitMqController {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/infoMsg")
    public void routeMQ(String msg) {
        rabbitTemplate.convertAndSend("route","info", "infoMsg");
    }
    @GetMapping("/errMsg")
    public void routeErrMQ(String msg) {
        rabbitTemplate.convertAndSend("route","err", "errMsg");
    }
}

创建消费者

创建两个消费者,并且分别绑定队列routeQueue1与队列routeQueue2。这两个队列又根据路由键与路由机绑定。
其中routeQueue1与路由机route以绑定键“info”绑定。
其中routeQueue2与路由机route以绑定键“info”,“err”绑定。

@Component
public class RouteConsumer1 {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "routeQueue1"),
                    exchange = @Exchange(value = "route",type = "direct"),
                    key = {"info"}
            )})
    public void consumer1(String msg){
        System.out.println("routeQueue1consumer:"+msg);
    }
    
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "routeQueue2"),
                    exchange = @Exchange(value = "route",type = "direct"),
                    key = {"info","err"}
            )})
    public void consumer2(String msg){
        System.out.println("routeQueue2consumer:"+msg);
    }
}

控台输出

可以很明显的看到,因为两个队列都绑定了路由键info,所以info信息向两个队列都发送了,而err信息只向一个队列发送。

routeQueue2consumer:errMsg
routeQueue2consumer:infoMsg
routeQueue1consumer:infoMsg

动态路由模式

可以看到与路由模型的区别在于交换机的类型不同了,路由键不同了
其中路由键使用正则表达式进行匹配。其中“#”表示所有、全部的意思;“*”只匹配到一个词
在这里插入图片描述

创建生产者

在路由键上支持动态属性,以一定的规则匹配

@RestController
public class RabbitMqController {

    /**
     * jar包提供的,直接使用即可
     */
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @GetMapping("/dynamicRouteErr")
    public void dynamicRouteErr(String msg) {
        rabbitTemplate.convertAndSend("dynamicRoute",msg+".err", msg+"err");
    }
    @GetMapping("/dynamicRouteInfo")
    public void dynamicRouteInfo(String msg) {
        rabbitTemplate.convertAndSend("dynamicRoute",msg+".info", msg+"err");
    }
}

创建消费者

@Component
public class DynamicRouteConsumer {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "DynamicQueue1"),
                    exchange = @Exchange(value = "dynamicRoute",type = "topic"),
                    key = {"*.info"}
            )})
    public void consumer1(String msg){
        System.out.println("DynamicQueue1consumer:"+msg);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "DynamicQueue2"),
                    exchange = @Exchange(value = "dynamicRoute",type = "topic"),
                    key = {"*.info","*.err"}
            )})
    public void consumer2(String msg){
        System.out.println("DynamicQueue2consumer:"+msg);
    }
}

控制台输出

路由器dynamicRoute为topic路由机,其中DynamicQueue2绑定*.info,.err等动态路由键。
DynamicQueue1绑定
.info。接收到的内容也不一致。
info相关两个都能收到。err相关的只有DynamicQueue2能收到。
路由键使用正则表达式进行匹配。其中“#”表示所有、全部的意思;“*”只匹配到一个词

DynamicQueue2consumer:workerr
DynamicQueue2consumer:workerr
DynamicQueue1consumer:workerr

消费者开启手动确认

添加配置文件在rabbitmq级别下,开启手动应答模式,以及限制每次只发一条

listener:
      type: simple
      simple:
        #采用手动应答
        acknowledge-mode: manual
        #限制每次发送一条数据
        prefetch: 1

消费者

@Component
public class TestConsumer {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(name = "routeQueue1"),
                    exchange = @Exchange(value = "route", type = "direct"),
                    key = {"info"}
            )})
    public void consumer1(Message message, Channel channel) throws IOException {
        try {
            System.out.println("consumer1:" + new String(message.getBody()));
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
        }
    }
}

生产者confirm模式

添加配置文件

在rabbitmq级别下,开启发送确认模式

# 发送确认
    publisher-confirm-type: correlated

spring.rabbitmq.publisher-confirm-type新版发布确认属性有三种确认类型

	public enum ConfirmType {
		SIMPLE,
		CORRELATED,
		NONE
	}
  • NONE:值是禁用发布确认模式,是默认值
  • CORRELATED:值是发布消息成功到交换器后会触发回调方法
  • SIMPLE:

添加回调方法

@Component
public class RabbitCallback implements RabbitTemplate.ConfirmCallback{
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if (ack) {
            System.out.println("消息发送成功:"+correlationData);
        } else {
            System.out.println("消息发送失败:"+cause);
        }
    }
}

在配置文件中为RabbitTemplate 设置回调方法

@Configuration
public class RabbitMQConfig {
    @Autowired
    private CachingConnectionFactory connectionFactory;
    @Autowired
    private RabbitCallback callback;
    /* 
     * 需要对rabbitTemplate设置ConfirmCallback对象,
     * @return
     */
    @Bean
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setConfirmCallback(callback);
        return template;
    }
}

生产者发送消息

发送消息时,需要将消息id new CorrelationData(UUID.randomUUID().toString())一并发送。

@RestController
public class ProducerController {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @GetMapping(value = "/hello")
    public String producer(String key,HttpServletRequest request){
        rabbitTemplate.convertAndSend("route",key, "Msg:"+key,new CorrelationData(UUID.randomUUID().toString()));
        return request.getSession().getId();
    }
}
控制台输出,当消息投递成功时,会返回消息发送成功或失败信息

consumer1:Msg:info
消息发送成功:CorrelationData [id=fdba8796-cf5a-408d-bcc2-14c9cf6ef446]
consumer1:Msg:info
消息发送成功:CorrelationData [id=5a5d9c74-0554-4132-901d-a36ec1d67eab]

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:博客之星2020 设计师:CSDN官方博客 返回首页

打赏作者

吴顺达

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值