ActiveMQ与SpringBoot整合实战:注解开发------p2p模式消息传输自定义对象

一、ActiveMQ中的p2p模式

p2p的过程则理解起来更加简单。它好比是两个人打电话,这两个人是独享这一条通信链路的。一方发送消息,另外一方接收,就这么简单。在实际应用中因为有多个用户对使用p2p的链路,它的通信场景如下图所示:
ActiveMQ与SpringBoot整合实战:注解开发------p2p模式消息传输自定义对象_第1张图片
在p2p的场景里,相互通信的双方是通过一个类似于队列的方式来进行交流。和pub-sub的区别在于一个topic有一个发送者和多个接收者,而在p2p里一个queue只有一个发送者和一个接收者。

二、下载MQ

ActiveMQ直接去apache官网下载最新版本即可,个人测试使用的是Windows版本。

三、消息生产者端代码实现

开发工具使用IDEA Communit版本。

  1. 新建一个SpringBoot项目并修改pom.xml,使用的springboot的版本为2.1.3
<!--    包含 logging 自动配置 注解等-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
    </dependency>

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

    <!-- 包含 mvc,aop 等jar资源 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-activemq</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-pool</artifactId>
    </dependency>
    <dependency>
      <groupId>org.messaginghub</groupId>
      <artifactId>pooled-jms</artifactId>
      <version>1.0.4</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.12</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.62</version>
    </dependency>
  1. application.yml中的配置
    我的配置中使用了连接池,这也是实际引用中需要配置的,我们这里直接就配置好了。
    因为我们需要传输的数据是自定义类的实例对象,那么activemq需要配置对象是否可信,spring.activemq.packages.trusted这个配置是配置某个包路径下的对象可信,那么需要传输的类就可以定义在这个包下,如果有多个包,使用“,”分割即可。
server:
  port: 8889

spring:
  activemq:
    broker-url: tcp://127.0.0.1:61616
    in-memory: false #true 表示使用内置的MQ,false则连接服务器
    user: admin
    password: admin
    packages:
      trusted: org.example.trust
    pool:
      enabled: true #true表示使用连接池;false时,每发送一条数据创建一个连接
      max-connections: 10 #连接池最大连接数
      idle-timeout: 30 #空闲的连接过期时间,默认为30秒
      expiry-timeout: 0 #强制的连接过期时间,与idleTimeout的区别在于:idleTimeout是在连接空闲一段时间失效,而expiryTimeout不管当前连接的情况,只要达到指定时间就失效。默认为0,never

logging:
  level:
    root: debug #项目其他日志不关注
#    org.apache.activemq.pool: debug #特别关注这个包下的输出
#    org.apache.activemq.broker: debug #特别关注这个包下的输出
#    org.apache.activemq.jms.pool: debug #特别关注这个包下的输出
#    org.apache.tomcat: warn

test:
  queue:
    simpletextqueue: TextQueue
  topic:
    simpletexttopic: TextTopic
  1. 配置Queue Bean
    文件中的Topic的配置可以忽略
package org.example.config;

import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.jms.Queue;
import javax.jms.Topic;

@Configuration
public class ActiveMqConfig {
     

	//从配置文件中获取队列名称的配置
    @Value("${test.queue.simpletextqueue}")
    private String textQueue;

    @Value("${test.topic.simpletexttopic}")
    private String textTopic;

    @Bean("simpleTextQueue")
    public Queue simpleTextQueue(){
     
        return new ActiveMQQueue(textQueue);
    }

    @Bean("simpleTextTopic")
    public Topic simpleTextTopic(){
     
        return new ActiveMQTopic(textTopic);
    }
}
  1. 传输实体定义
    传输的实体必须要实现Serializable接口
package org.example.trust;

import lombok.Data;
import lombok.ToString;

import java.io.Serializable;

@Data
@ToString
public class User implements Serializable {
     
    private String id;
    private String name;
}
  1. 定时发送消息
package org.example.schedule;

import org.example.trust.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import javax.jms.Queue;

@Configuration
@EnableScheduling
public class ScheduleTaskConfig {
     

    @Autowired
    private Queue simpleTextQueue;

    //注入springboot封装的工具类
    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Scheduled(cron = "0/10 * * * * ?")
    private void task1(){
     
        User user = new User();
        double r = Math.random();
        user.setId(r+"");
        user.setName("队"+r+"列");
        jmsMessagingTemplate.convertAndSend(simpleTextQueue,user);
        System.out.println("本次发送数据:" + user.toString());
    }
}

  1. 启动类
    需要加入注解@EnableJms
package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jms.annotation.EnableJms;

@SpringBootApplication
@EnableJms //启动消息队列
public class MqProviderApplication {
     
    public static void main(String[] args) {
     
        SpringApplication sa = new SpringApplication();
        sa.run(MqClientApplication.class,args);
    }
}
  1. 启动项目并发送数据
    因为是定时任务发送数据,等待发送10条数据关闭程序
    ActiveMQ与SpringBoot整合实战:注解开发------p2p模式消息传输自定义对象_第2张图片
    查看ActiveMq管理端的数据
    ActiveMQ与SpringBoot整合实战:注解开发------p2p模式消息传输自定义对象_第3张图片
    关注一下图片中的红框部分
    表格头部:
    Number Of Pending Messages:传入的消息数量
    Number Of Consumers:消费者数量(因为我们没有开启消费者程序所以为0)
    Messages Enqueued: 消息入队数量
    Messages Dequeued: 消息出队数量
    底部红框中的10正是我们传输的10条数据。
    接下来我们编写消费者端的代码。

四、消息消费者端代码实现

pom.xml和application.yml与生产者端相同,只有端口不同。直接开始编码

  1. 接收数据的实体类
    在application.yml中需要配置可信任包路径。
package org.example.trust;

import lombok.Data;
import lombok.ToString;

import java.io.Serializable;

@Data
@ToString
public class User implements Serializable {
     
    private String id;
    private String name;
}
  1. 消息监听

使用注解方式开发能够大大的提高开发效率,当注解方式不能满足的时候在自己去实现接口。
这里使用了注解@JmsListener(destination = “TextQueue”)
将方法handleMessage当做处理消息数据的方法,参数是需要转换的类。

package org.example.service;

import org.example.trust.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;

@Component
public class ConsumerService {
     

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @JmsListener(destination = "TextQueue")
    public void handleMessage(User user) {
     
//        User user = jmsMessagingTemplate.receiveAndConvert("TextQueue", User.class);
        System.out.println("接收到的数据:"+user.toString());
    }
}
  1. 启动消费端

同样需要添加注解@EnableJms

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jms.annotation.EnableJms;

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

启动项目查看console
ActiveMQ与SpringBoot整合实战:注解开发------p2p模式消息传输自定义对象_第4张图片
确实收到了消息,大家可以对比发送的数据,是相同的。
再来看ActiveMQ的管理端数据,大家看红框中的数据,消费者数量为1,消费了10条数据,看来我们确实成功了。
ActiveMQ与SpringBoot整合实战:注解开发------p2p模式消息传输自定义对象_第5张图片
至此,我们ActiveMQ的简单p2p数据传输就实现了,如有错误欢迎指正。接下来的文章还有关于订阅模式,大家敬请期待。

你可能感兴趣的:(中间件学习,实战)