SpringAMQP消息队列

安装RabbitMQ


在linux上安装RabbitMQ,并运行

docker run \
 -e RABBITMQ_DEFAULT_USER=zywzy \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 --name mq \
 --hostname mq1 \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3-management

http://ip:15672 访问控制台, 用户名zywzy,密码123321

引入依赖


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

配置文件


spring:
  rabbitmq:
    host: 172.27.99.52 # rabbitMQ的ip地址
    port: 5672 # 端口
    username: abc
    password: 123321
    virtual-host: /

发送消息


@SpringBootTest
public class SpringAmqpTest {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testSendMessage2SimpleQueue() {
        String queueName = "simple.queue";
        String message = "hello, spring amqp!";
        rabbitTemplate.convertAndSend(queueName, message);
    }
}

消费消息


	@RabbitListener(queues = "simple.queue")
    public void listenWorkQueue1(String msg) throws InterruptedException {
        System.out.println("消费者1接收到消息:【" + msg + "】" + LocalTime.now());
    }

消息预取


  • 每次只能取一条消息,处理完成才能取下一条消息
spring:
  rabbitmq:
    listener:
      simple:
        prefetch: 1

常见exchange类型


  • Fanout: 广播
  • Direct: 路由
  • Topic: 话题

Fanout Exchange

  • 绑定队列和交换机
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FanoutConfig {

    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("itcast.fanout");
    }
    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanout.queue1");
    }
    /**
     * 绑定队列1到交换机
     */
    @Bean
    public Binding fanoutBinding1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }
    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanout.queue2");
    }
    /**
     * 绑定队列2到交换机
     */
    @Bean
    public Binding fanoutBinding2(Queue fanoutQueue2, FanoutExchange fanoutExchange){
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }
}
  • 监听队列1和队列2
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class MyRabbitListener {

    @RabbitListener(queues = "fanout.queue1")
    public void listenFanoutQueue1(String msg){
        System.out.println("消费者接收到fanout.queue1的消息: {" + msg + "}");
    }

    @RabbitListener(queues = "fanout.queue2")
    public void listenFanoutQueue2(String msg){
        System.out.println("消费者接收到fanout.queue2的消息: {" + msg + "}");
    }
}
  • 发布消息
	@Test
    void name() {
        String exchangeName = "itcast.fanout";
        String message = "hello , everyone!";
        rabbitTemplate.convertAndSend(exchangeName, "", message);
    }
  • 运行结果

在这里插入图片描述
缺点:
不能缓存消息, 路由失败, 消息丢失

Direct Exchange

在这里插入图片描述

  • 绑定
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class MyRabbitListener {

    @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue1"),
            exchange = @Exchange(name = "zhouyu.direct", type = ExchangeTypes.DIRECT),
            key = {"red", "blue"}))
    public void listenDirectQueue1(String msg){
        System.out.println("消费者1接收到direct的消息: [" + msg + "]");
    }

    @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "direct.queue2"),
            exchange = @Exchange(name = "zhouyu.direct", type = ExchangeTypes.DIRECT),
            key = {"red", "yellow"}))
    public void listenDirectQueue2(String msg){
        System.out.println("消费者2接收到direct的消息: [" + msg + "]");
    }
}
  • 发布消息
	@Test
    void name() {
        String exchangeName = "zhouyu.direct";
        String message = "hello red";
        rabbitTemplate.convertAndSend(exchangeName, "red", message);
    }

Topic Exchange

在这里插入图片描述

  • 绑定
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class MyRabbitListener {

    @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue1"),
            exchange = @Exchange(name = "zhouyu.topic", type = ExchangeTypes.TOPIC),
            key = "china.#"))
    public void listenTopicQueue1(String msg){
        System.out.println("消费者1接收到topic1的消息: [" + msg + "]");
    }

    @RabbitListener(bindings = @QueueBinding(value = @Queue(name = "topic.queue2"),
            exchange = @Exchange(name = "zhouyu.topic", type = ExchangeTypes.TOPIC),
            key = "#.news"))
    public void listenTopicQueue2(String msg){
        System.out.println("消费者2接收到topic2的消息: [" + msg + "]");
    }
}
  • 发布消息
	@Test
    void name() {
        String exchangeName = "zhouyu.topic";
        String message = "china.weather";
        rabbitTemplate.convertAndSend(exchangeName, "china.weather", message);
    }

基于bean实现topic


  • MqConstants.java
public class MqConstants {


    public static final String HOTEL_EXCHANGE = "hotel.topic";
    public static final String HOTEL_INSERT_QUEUE = "hotel.insert.queue";
    public static final String HOTEL_DELETE_QUEUE = "hotel.delete.queue";
    public static final String HOTEL_INSERT_KEY = "hotel.insert.key";
    public static final String HOTEL_DELETE_KEY = "hotel.delete.key";

}
  • MqConfig.java

import cn.zyw.MqConstants;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MqConfig {

    @Bean
    public TopicExchange topicExchange(){
        return new TopicExchange(MqConstants.HOTEL_EXCHANGE, true, false);
    }

    @Bean
    public Queue insertQueue(){
        return new Queue(MqConstants.HOTEL_INSERT_QUEUE, true);
    }

    @Bean
    public Queue deleteQueue(){
        return new Queue(MqConstants.HOTEL_DELETE_QUEUE, true);
    }

    @Bean
    public Binding insertQueueBinding(){
        return BindingBuilder.bind(insertQueue()).to(topicExchange()).with(MqConstants.HOTEL_INSERT_KEY);
    }

    @Bean
    public Binding deleteQueueBinding(){
        return BindingBuilder.bind(deleteQueue()).to(topicExchange()).with(MqConstants.HOTEL_DELETE_KEY);
    }
}
  • HotelListener.java
import cn.zyw.MqConstants;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class HotelListener {

    @RabbitListener(queues = MqConstants.HOTEL_INSERT_QUEUE)
    public void listenHotelInsertOrUpdate(Long id){
        // TODO 根据id查询数据库更新缓存
        System.out.println("监听到数据更新" + id);
    }

    @RabbitListener(queues = MqConstants.HOTEL_DELETE_QUEUE)
    public void listenHotelDelete(Long id){
        // TODO 根据id删除缓存
        System.out.println("监听到数据删除" + id);
    }
}

消息转换器


  • 依赖
		<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
  • 声明MessageConverter
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class ConsumerApplication {

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

    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}

附录


消息中间件比较

请添加图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值