p2p的过程则理解起来更加简单。它好比是两个人打电话,这两个人是独享这一条通信链路的。一方发送消息,另外一方接收,就这么简单。在实际应用中因为有多个用户对使用p2p的链路,它的通信场景如下图所示:
在p2p的场景里,相互通信的双方是通过一个类似于队列的方式来进行交流。和pub-sub的区别在于一个topic有一个发送者和多个接收者,而在p2p里一个queue只有一个发送者和一个接收者。
ActiveMQ直接去apache官网下载最新版本即可,个人测试使用的是Windows版本。
开发工具使用IDEA Communit版本。
<!-- 包含 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>
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
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);
}
}
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;
}
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());
}
}
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);
}
}
pom.xml和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;
}
使用注解方式开发能够大大的提高开发效率,当注解方式不能满足的时候在自己去实现接口。
这里使用了注解@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());
}
}
同样需要添加注解@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的管理端数据,大家看红框中的数据,消费者数量为1,消费了10条数据,看来我们确实成功了。
至此,我们ActiveMQ的简单p2p数据传输就实现了,如有错误欢迎指正。接下来的文章还有关于订阅模式,大家敬请期待。