○ Point-to-Point(P2P) ○ Publish/Subscribe(Pub/Sub)
-
P2P
-
涉及到的概念
-
消息队列(Queue)
-
发送者(Sender)
-
接收者(Receiver)
-
每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。
-
-
P2P的特点
如果你希望发送的每个消息都应该被成功处理的话,那么你需要P2P模式。
-
每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)
-
发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列
-
接收者在成功接收消息之后需向队列应答成功
-
-
Pub/Sub
-
涉及到的概念
-
主题(Topic)
-
发布者(Publisher)
-
订阅者(Subscriber)
客户端将消息发送到主题。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。
-
-
Pub/Sub的特点
-
每个消息可以有多个消费者
-
发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运行的状态。
-
为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。
-
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
public
class
Receiver {
public
static
void
main(String[] args) {
// ConnectionFactory :连接工厂,JMS 用它创建连接
ConnectionFactory connectionFactory;
// Connection :JMS 客户端到JMS Provider 的连接
Connection connection =
null
;
// Session: 一个发送或接收消息的线程
Session session;
// Destination :消息的目的地;消息发送给谁.
Destination destination;
// 消费者,消息接收者
MessageConsumer consumer;
connectionFactory =
new
ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616"
);
try
{
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接
session = connection.createSession(Boolean.FALSE,
Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
destination = session.createQueue(
"FirstQueue"
);
consumer = session.createConsumer(destination);
while
(
true
) {
//设置接收者接收消息的时间,为了便于测试,这里谁定为100s
TextMessage message = (TextMessage) consumer.receive(
100000
);
if
(
null
!= message) {
System.out.println(
"收到消息:"
+ message.getText());
}
else
{
break
;
}
}
}
catch
(Exception e) {
e.printStackTrace();
}
finally
{
try
{
if
(
null
!= connection)
connection.close();
}
catch
(Throwable ignore) {
}
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
public
class
Sender {
private
static
final
int
SEND_NUMBER =
5
;
public
static
void
main(String[] args) {
// ConnectionFactory :连接工厂,JMS 用它创建连接
ConnectionFactory connectionFactory;
// Connection :JMS 客户端到JMS Provider 的连接
Connection connection =
null
;
// Session: 一个发送或接收消息的线程
Session session;
// Destination :消息的目的地;消息发送给谁.
Destination destination;
// MessageProducer:消息发送者
MessageProducer producer;
// TextMessage message;
// 构造ConnectionFactory实例对象,此处采用ActiveMq的实现jar
connectionFactory =
new
ActiveMQConnectionFactory(
ActiveMQConnection.DEFAULT_USER,
ActiveMQConnection.DEFAULT_PASSWORD,
"tcp://localhost:61616"
);
try
{
// 构造从工厂得到连接对象
connection = connectionFactory.createConnection();
// 启动
connection.start();
// 获取操作连接
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 获取session注意参数值xingbo.xu-queue是一个服务器的queue,须在在ActiveMq的console配置
destination = session.createQueue(
"FirstQueue"
);
// 得到消息生成者【发送者】
producer = session.createProducer(destination);
// 设置不持久化,此处学习,实际根据项目决定
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
// 构造消息,此处写死,项目就是参数,或者方法获取
sendMessage(session, producer);
session.commit();
}
catch
(Exception e) {
e.printStackTrace();
}
finally
{
try
{
if
(
null
!= connection)
connection.close();
}
catch
(Throwable ignore) {
}
}
}
public
static
void
sendMessage(Session session, MessageProducer producer)
throws
Exception {
for
(
int
i =
1
; i <= SEND_NUMBER; i++) {
TextMessage message = session.createTextMessage(
"ActiveMq 发送的消息-"
+ i);
// 发送消息到目的地方
System.out.println(
"发送消息:"
+
"ActiveMq 发送的消息-"
+ i);
producer.send(message);
}
}
}
|
1
2
3
4
5
|
发送消息:ActiveMq 发送的消息-1
发送消息:ActiveMq 发送的消息-2
发送消息:ActiveMq 发送的消息-3
发送消息:ActiveMq 发送的消息-4
发送消息:ActiveMq 发送的消息-5
|
1
2
3
4
5
|
收到消息:ActiveMq 发送的消息-1
收到消息:ActiveMq 发送的消息-2
收到消息:ActiveMq 发送的消息-3
收到消息:ActiveMq 发送的消息-4
收到消息:ActiveMq 发送的消息-5
|
-
ConnectionFactory
-
Destination
-
Connection
-
Session
-
消息的生产者
-
消息消费者
-
MessageListener
-
提供消息灵活性
-
松散耦合
-
异步性