申博在线娱乐登入

Spring boot集成Rabbit MQ使用初体验

Spring boot集成Rabbit MQ使用初体验

本文来源:http://www.yu833.com/tech_ifeng_com/

申博在线娱乐登入,12月8日,澎湃新闻从重庆市沙坪坝区新闻办公室发布的通报了解到,针对李琳家属反映该区机关干部郑某隐瞒婚姻状况造成李琳自杀一事,区纪检监察部门已成立调查组开展调查核实。律师提醒表示,消费者一旦被侵权,可以通过起诉拍摄者和商家来维权。”中央追逃办有关负责人强调,腐败分子必须认清形势,放弃幻想。那么我们采取的方式呢,是每一个人都是一个独体的研究个体,他们的研究方向可以由他们自己去自由选定。

他变得更加警觉,甚少出入公众场合。齐先生先后毕业于贵州大学哲学系和长江商学院工商管理专业,并分别取得哲学学士和工商管理硕士学位,是高级政工师。与BAT合作频繁中国联通三季报显示,前三季度实现营业收入2071.4亿元,同比减少2.3%;净利润4.9亿元,同比下滑81.8%。不过,冯萧认为自己具备还款能力,只是可能会还的慢一点。

【理财】美股:美股收盘大涨,道指、标普500均创历史新高。信息安全我们仅在本《隐私政策》所述目的所必需的期间和法律法规要求的时限内保留您的个人信息。为了搞清楚这个问题,我们需要了解以下三个重要的时间点:权益登记日:基金管理人进行红利分配时,需要定出某一天,这一天登记在册的持有人可以参加分红,这一天就是权益登记日。”他声称,说巴铁停运的都是造谣,积满尘土的“巴铁1号”是扬尘和雾霾所致,“家里的轿车三四天不洗不也有灰吗?”关于寻找新投资人的进展,宋有洲向澎湃新闻记者透露,巴铁科技已经谈妥了一笔新的投资,对方是一家在北京的央企,主业在能源领域,将与公司合作建设巴铁。

undefined

1.rabbit mq基本特性

首先介绍一下rabbitMQ的几个特性

Asynchronous Messaging
Supports multiple messaging protocols, message queuing, delivery acknowledgement, flexible routing to queues, multiple exchange type.

异步消息

支持多种消息传递协议,消息排队,传递确认,灵活路由规则,多种交换类型。这些应该是rabbitmq最核心的特性了。

Developer Experience

Deploy with BOSH, Chef, Docker and Puppet. Develop cross-language messaging with favorite programming languages such as: Java, .NET, PHP, Python, JavaScript, Ruby, Go, and many others.

部署体验?

与BOSH,Chef,Docker和Puppet一起部署。使用喜欢的编程语言来开发跨语言消息传递,例如Java,.NET,PHP,Python,JavaScript,Ruby,Go等。

Distributed Deployment

Deploy as clusters for high availability and throughput; federate across multiple availability zones and regions.

分布式部署

部署为集群以实现高可用性和吞吐量;跨多个可用区域和区域联合。

Enterprise & Cloud Ready

Pluggable authentication, authorisation, supports TLS and LDAP. Lightweight and easy to deploy in public and private clouds.

企业和云就绪

可插拔身份验证,授权,支持TLS和LDAP。轻巧且易于在公共和私有云中进行部署。

Tools & Plugins

Diverse array of tools and plugins supporting continuous integration, operational metrics, and integration to other enterprise systems. Flexible plug-in approach for extending RabbitMQ functionality.

工具&插件

工具和插件的种类繁多,支持持续集成,运营指标以及与其他企业系统的集成。灵活的插件方法,用于扩展RabbitMQ功能。

Management & Monitoring

HTTP-API, command line tool, and UI for managing and monitoring RabbitMQ.

管理和监控

HTTP-API支持,命令行工具,管理和监控界面。

undefined

2.rabbit mq核心概念

①Message

消息,消息就是数据的载体,由消息头和消息体组成。消息体是不透明的,而消息头由一系列的可选属性组成,这些属性包括routing-key(路由键,也就是消息是如何分发给队列的),priority(相对于其它消息的优先权),delivery-mode(指定是否需要持久化存储)

②Publisher

消息的生产者,向交换机发布消息的客户端应用程序。

③Exchange

交换机用来接收生产者发送的消息并将这些消息按照路由规则或者交换机类型路由到指定的队列。交换机有4种类型:direct(默认),fanout,topic,以及headers,这四种类型支持不同的路由策略。

undefined

④Queue

消息队列,用于保存消息直到发送给消费者,是消息的容器。一个消息可以存入一个或多个队列,一直到消费者消费这个消息,才会从队列中删除。

⑤Binding

绑定,指定交换机和队列的绑定规则,可以理解为一个过滤器,当路由键符合这个绑定规则时,就会将消息发送给队列。交换机和队列之间的绑定可以是多对多的关系

⑥Connection

一个TCP连接

⑦Channel

信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。

⑧Consumer

消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。

⑨Virtual Host

虚拟主机,表示一批交换机、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,RabbitMQ 默认的 vhost 是 / 。

⑩Broker

表示消息队列服务器实体。

更详细的说明请参考官方文档:/www_rabbitmq_com/tutorials/amqp-concepts.html

3.交换机类型和消息路由

  • Direct Exchange

rabbitmq-direct.png

消息中的路由键(routing key)如果和 Binding中的 binding key 一致,交换器就将消息发到对应的队列中。路由键与队列名完全匹配,如果一个队列绑定到交换机要求路由键为“dog”,则只转发 routing key 标记为“dog”的消息,不会转发“dog.puppy”,也不会转发“dog.guard”等等。它是完全匹配、单播的模式。

  • Fanout Exchange

rabbitmq-fanout.png

每个发到 fanout 类型交换器的消息都会分到所有绑定的队列上去。fanout 交换器不处理路由键【路由键被忽略】,只是简单的将队列绑定到交换器上,每个发送到交换器的消息都会被转发到与该交换器绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout 类型转发消息是最快的。

  • Topic Exchange

rabbitmq-topic.png

topic 交换器通过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成单词,这些单词之间用点隔开。它同样也会识别两个通配符:符号“#”和符号“

注意#匹配0个或者多个单词,*匹配一个单词

4.开始使用

我们先看spring boot的申博在线娱乐登入官方文档是怎么说的吧。

首先,添加这些配置

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /test

rabbitmq默认用户名密码为guest:guest

先上配置类,RabbitTemplate使用自动配置好的,自动注入进来就可以了,我们还需要配置一个RabbitAdmin对象,RabbitAdmin有两个构造方法

/**
* Construct an instance using the provided {@link ConnectionFactory}.
* @param connectionFactory the connection factory - must not be null.
*/
public RabbitAdmin(ConnectionFactory connectionFactory) {
    Assert.notNull(connectionFactory, "ConnectionFactory must not be null");
    this.connectionFactory = connectionFactory;
    this.rabbitTemplate = new RabbitTemplate(connectionFactory);
}

/**
* Construct an instance using the provided {@link RabbitTemplate}. Use this
* constructor when, for example, you want the admin operations to be performed within
* the scope of the provided template's {@code invoke()} method.
* @param rabbitTemplate the template - must not be null and must have a connection
* factory.
* @since 2.0
*/
public RabbitAdmin(RabbitTemplate rabbitTemplate) {
    Assert.notNull(rabbitTemplate, "RabbitTemplate must not be null");
    Assert.notNull(rabbitTemplate.getConnectionFactory(), "RabbitTemplate's ConnectionFactory must not be null");
    this.connectionFactory = rabbitTemplate.getConnectionFactory();
    this.rabbitTemplate = rabbitTemplate;
}

但实际看他们的构造函数,发现如果我们不需要自己定制RabbitTemplate,直接使用第一个构造方法即可。

@Configuration
public class RabbitMqConfig {
    @Autowired
    RabbitTemplate rabbitTemplate;

    @Bean
    public RabbitAdmin rabbitAdmin() {
        return new RabbitAdmin(rabbitTemplate);
    }
}

类似这样,就配置好了。

接下来写一个测试类,测试声明交换机,队列,以及发送消息和接收消息等操作。

首先是声明交换机类型,四种交换机对应的构造方法如下

/参数列表分别是:1.交换器名称,2.是否持久化,3.是否自动删除【指的是当最后一个与它绑定的队列删除时,是否自动删除该交换机】
TopicExchange topicExchange = new TopicExchange("default.topic", true, false);
DirectExchange directExchange = new DirectExchange("default.direct", true, false);
FanoutExchange fanoutExchange = new FanoutExchange("default.fanout", true, false);
HeadersExchange headersExchange = new HeadersExchange("default.headers", true, false);
rabbitAdmin.declareExchange(topicExchange);
rabbitAdmin.declareExchange(directExchange);
rabbitAdmin.declareExchange(fanoutExchange);
rabbitAdmin.declareExchange(headersExchange);

然后是声明队列

/1.队列名称,2.声明一个持久队列,3.声明一个独立队列,4.是否自动删除队列
Queue queue1 = new Queue("queue1", true, false, false);
Queue queue2 = new Queue("queue2", true, false, false);
Queue queue3 = new Queue("queue3", true, false, false);
Queue queue4 = new Queue("queue4", true, false, false);
rabbitAdmin.declareQueue(queue1);
rabbitAdmin.declareQueue(queue2);
rabbitAdmin.declareQueue(queue3);
rabbitAdmin.declareQueue(queue4);

然后把队列和交换机相互绑定

/1_queue:绑定的队列,2.topicExchange:绑定到那个交换器,3.test.send.topic:绑定的路由名称[routing key]
rabbitAdmin.declareBinding(BindingBuilder.bind(queue1).to(fanoutExchange));
rabbitAdmin.declareBinding(BindingBuilder.bind(queue2).to(fanoutExchange));
rabbitAdmin.declareBinding(BindingBuilder.bind(queue3).to(topicExchange).with("mq.*"));
rabbitAdmin.declareBinding(BindingBuilder.bind(queue4).to(directExchange).with("mq.direct"));

因为fanout类型的交换机忽略routing key属性,所以不需要设置。

完整测试代码如下

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class RabbitMqTest {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitAdmin rabbitAdmin;

    @Test
    public void testDeclare() {
        /参数列表分别是:1.交换器名称,2.是否持久化,3.是否自动删除【指的是当最后一个与它绑定的队列删除时,是否自动删除该交换机】
        TopicExchange topicExchange = new TopicExchange("default.topic", true, false);
        DirectExchange directExchange = new DirectExchange("default.direct", true, false);
        FanoutExchange fanoutExchange = new FanoutExchange("default.fanout", true, false);
        HeadersExchange headersExchange = new HeadersExchange("default.headers", true, false);
        rabbitAdmin.declareExchange(topicExchange);
        rabbitAdmin.declareExchange(directExchange);
        rabbitAdmin.declareExchange(fanoutExchange);
        rabbitAdmin.declareExchange(headersExchange);

        /1.队列名称,2.声明一个持久队列,3.声明一个独立队列,4.是否自动删除队列
        Queue queue1 = new Queue("queue1", true, false, false);
        Queue queue2 = new Queue("queue2", true, false, false);
        Queue queue3 = new Queue("queue3", true, false, false);
        Queue queue4 = new Queue("queue4", true, false, false);
        rabbitAdmin.declareQueue(queue1);
        rabbitAdmin.declareQueue(queue2);
        rabbitAdmin.declareQueue(queue3);
        rabbitAdmin.declareQueue(queue4);

        /1_queue:绑定的队列,2.topicExchange:绑定到那个交换器,3.test.send.topic:绑定的路由名称[routing key]
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue1).to(fanoutExchange));
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue2).to(fanoutExchange));
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue3).to(topicExchange).with("mq.*"));
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue4).to(directExchange).with("mq.direct"));
    }
}

运行结果如下:

Snipaste_2019-09-28_17-33-54.png

Snipaste_2019-09-28_17-35-35.png

再看一下绑定情况:

Direct交换机

Snipaste_2019-09-28_17-36-26.png

Fanout交换机

Snipaste_2019-09-28_17-37-06.png

Topic交换机

Snipaste_2019-09-28_17-38-59.png

全都测试成功,接下来就可以开始发送消息了。

发送消息有多个API可用,这里选择高亮的那个API,实际还有send方法可用,不过需要自己来构建消息

Snipaste_2019-09-28_17-45-28.png

Snipaste_2019-09-28_17-54-51.png

@Test
public void testSendMessage() {
    /1.交换机,2.路由键,3.发送的消息体【这里的消息体会自动转换为消息,也可以自己构建消息对象】
    rabbitTemplate.convertAndSend("default.topic","mq.whatever.this.is",new Student(1,"mmp","male",234));
}

测试结果如下:

Snipaste_2019-09-28_18-01-01.png

一定要注意topic类型的交换机的路由键的匹配规则,#匹配0个或者多个单词,*匹配一个单词

那如果不想每次都是在测试类里面创建交换机和队列,可以怎么做呢?可以在程序入口类里面实现CommandLineRunner接口,代码如下,这样的话,每次启动都会声明一次,当然重复声明不会报错,但会覆盖之前的声明,比如说之前声明的时候定义的routing key可能就会被覆盖。

@SpringBootApplication
@EnableRabbit
public class AmqpApplication implements CommandLineRunner {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitAdmin rabbitAdmin;

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


    @Override
    public void run(String... args) throws Exception {
        /参数列表分别是:1.交换器名称,2.是否持久化,3.是否自动删除【指的是当最后一个与它绑定的队列删除时,是否自动删除该交换机】
        TopicExchange topicExchange = new TopicExchange("default.topic", true, false);
        DirectExchange directExchange = new DirectExchange("default.direct", true, false);
        FanoutExchange fanoutExchange = new FanoutExchange("default.fanout", true, false);
        HeadersExchange headersExchange = new HeadersExchange("default.headers", true, false);
        rabbitAdmin.declareExchange(topicExchange);
        rabbitAdmin.declareExchange(directExchange);
        rabbitAdmin.declareExchange(fanoutExchange);
        rabbitAdmin.declareExchange(headersExchange);

        /1.队列名称,2.声明一个持久队列,3.声明一个独立队列,4.是否自动删除队列
        Queue queue1 = new Queue("queue1", true, false, false);
        Queue queue2 = new Queue("queue2", true, false, false);
        Queue queue3 = new Queue("queue3", true, false, false);
        Queue queue4 = new Queue("queue4", true, false, false);
        rabbitAdmin.declareQueue(queue1);
        rabbitAdmin.declareQueue(queue2);
        rabbitAdmin.declareQueue(queue3);
        rabbitAdmin.declareQueue(queue4);

        /1_queue:绑定的队列,2.topicExchange:绑定到那个交换器,3.test.send.topic:绑定的路由名称[routing key]
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue1).to(fanoutExchange));
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue2).to(fanoutExchange));
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue3).to(topicExchange).with("mq.*"));
        rabbitAdmin.declareBinding(BindingBuilder.bind(queue4).to(directExchange).with("mq.direct"));
    }
}

但其实这样做还是比较复杂的,而且完全没有必要,更加简单方便的做法是,把那些配置声明的对象直接添加到IOC容器中,让spring自动的去调用相应的声明方法,真是纵享丝滑呀,类似下面这样子:

@Bean
public Queue Queue() {
    return new Queue("hello");
}

继续测试接收消息,有一个注解很方便。

Snipaste_2019-09-28_18-10-09.png

@Service
public class ReceiverService {
    @RabbitListener(queues = {"queue3"})
    public void receive(Student student) {
        System.out.println("接收到消息并打印:"+student);
    }
}

测试结果如下:

接收到消息并打印:student{id=1, name='mmp', gender='male', age=234}

也可以直接使用方法接收消息

@Test
public void testReceive() {
    Student student = (Student) rabbitTemplate.receiveAndConvert("queue3");
    System.out.println(student);
}

测试结果如下:

student{id=1, name='mmp', gender='male', age=234}

如果想让发送的学生对象使用JSON格式怎么办呢?

需要定制一下:

@Configuration
public class RabbitMqConfig {
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
        return rabbitTemplate;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(RabbitTemplate rabbitTemplate) {
        return new RabbitAdmin(rabbitTemplate);
    }
}

测试一下:

Snipaste_2019-09-28_18-21-46.png

源码地址:/github_com/lingEric/springboot-integration-hello

更多官方tutorials请移步/github_com/rabbitmq/rabbitmq-tutorials

posted @ 2019-09-28 18:32 申博在线娱乐登入ericling 阅读(...) 评论(...) 申博在线娱乐登入 编辑 收藏
申博注册账户登入 申博太阳城登入 申博手机版下载网址 申博游戏平台直营网 菲律宾申博太阳城娱乐 www.tyc599.com
申博在线咨询登入 申博手机版下载网址 申博百家乐 申博现金网直营 申博138怎么登入不了 太阳城管理网
申博138娱乐支付宝充值 www.msc22.com 老虎机支付宝充值 太阳城提款申请登入 申博代理官网正网 www.7788shenbo.com