选用的服务器是apache-activemq-5.13.0,是在本机上打开的。
将服务器在电脑上找到对应的机型数下在bin文件夹下打开activemq.bat文件即开启了服务器。端口号61616
目录:
1,模型解析
2,参数解析
3,源代码
一模型解析:
JMS支持两种消息模型:Point-to-Point(P2P)和Publish/Subscribe(Pub/Sub),即点对点和发布订阅模型。
1,P2P模型
有以下概念:消息队列(Queue)、发送者(Sender)、接收者(Receiver)。每个消息都被发送到一个特定的队列,接收者从队列获取消息。队列保留着消息,直到它们被消费或超时。
(1) 每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)
(2) 发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列。
(3) 接收者在成功接受消息之后需要向队列应答成功
注:如果希望发送的每个消息都被成功处理,或被特定的消费者消费,那么需要采用P2P模型。
使用场合:想让接收者进行且只进行一次处理,组件之间进行同步通信。
个人理解:这种模型的应用很常见,例如:qq/微信/飞信聊天(私聊),(1)小A和小B互加qq好友,小A给小B发一条消息”你干嘛呢?”,这条消息只有小B能接收到,别人接收不到——每个消息只有一个消费者;(2)如果小B没有登录qq,也没关系,当小B登录qq后,就会看到这条消息——发送者和接收者之间在时间上没有依赖性,也就是说,当发送者发送了消息之后,不管接收者有没有正在运行,它不会影响到消息被发送到队列;
2,Pub/Sub模型
有以下概念:主题(Topic)、发布者(Publisher)、订阅者(Subscriber)。客户端将消息发送到主题。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。
(1) 每个消息可以有多个消费者
(2) 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅之后,才能消费发布者的消息,而且,为了消费消息,订阅者必须保持运行的状态。
为了缓和这种严格的时间上的依赖性,JMS允许订阅者创建一个可持久化的订阅(即,发送者和接收者之间在时间上没有依赖性。这样的话,即使订阅者没有运行,它也能接收到发布者的消息。)
如果希望发送的消息可以被一个/多个消费者消费,那么可以采用Pub/Sub模型。
个人理解:这种模型的应用也很常见,例如,如果qq群聊天是这样的:小A、小B、小C都是”聊天群”中的成员,小A、小B在线,小C不在线,小A发布一条消息”明天放假”,那么只有小B能接收到,当小C上线后也接收不到。这样是不是很不合理——发布者和订阅者之间有时间上的依赖性;因此,为了缓和这种严格的时间上的依赖性,JMS允许订阅者创建一个可持久化的订阅(即,发送者和接收者之间在时间上没有依赖性。这样的话,即使订阅者没有运行,它也能接收到发布者的消息。)——还是上面的例子,小A、小B、小C都是”聊天群”中的成员,小A、小B在线,小C不在线,小A发布一条消息”明天放假”,小B可以接收到,当小C上线后也可以接收到。
以上只是目前的个人理解,可能与实际有所偏差。
3,总结:
P2P模型与Pub/Sub模型的根本区别:对于p2p模型的每个消息只能有一个消费者 ; pub/sub模型可以有多个消费者 。
二参数详解:
1,创建共产参数解析:
new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, "tcp://localhost:61616");
分别表示默认用户名密码 和服务地址 注意:这里服务器是部署在本机上的。
除了以上的设置方法还有:通过下面的方法设置用户名和密码,这个用户名和密码在conf目录下的 credentials.properties文件中,也可以在activemq.xml中配置
connectionFactory.setUserName("system");
connectionFactory.setPassword("manager");
2, 创建Session,参数解释:
第一个参数是否使用事务:当消息发送者向消息提供者(即消息代理)发送消息时,
消息发送者等待消息代理的确认,没有回应则抛出异常,消息发送程序负责处理这个错误。
第二个参数消息的确认模式:
AUTO_ACKNOWLEDGE : 指定消息提供者在每次收到消息时自动发送确认。消息只向目标发送一次,但传输过程中可能因为错误而丢失消息。
CLIENT_ACKNOWLEDGE : 由消息接收者确认收到消息,通过调用消息的acknowledge()方法(会通知消息提供者收到了消息)
DUPS_OK_ACKNOWLEDGE : 指定消息提供者在消息接收者没有确认发送时重新发送消息(这种确认模式不在乎接收者收到重复的消息)。
三代码:
1发送者:
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Sender {
public static void main(String[] args) throws JMSException {
// 设置的默认用户名和密码 还有设置连接服务器的端口 这里服务器是部署在本机的
// 还可以通过下面的方法设置用户名和密码,这个用户名和密码在conf目录下的credentials.properties文件中,也可以在activemq.xml中配置
// connectionFactory.setUserName("system");
// connectionFactory.setPassword("manager");
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, "tcp://localhost:61616");
Connection connection=connectionFactory.createConnection();
connection.start();
Session session=connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
//创建一个目的地,它用来接收消息: 这里创建的是一个Queue,表明我们用的是 p2p方式,
//另一种Destination是 Topic,用于订阅模式
Destination destination=session.createQueue("testQueue");
//Topic destination = (Topic)context.lookup("topic/LeadfarTopic");
//创建生产者
MessageProducer producer=session.createProducer(destination);
// TopicPublisher publisher = session.createPublisher(destination);
//指定消息的保存发送模式 设置不持久化
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
//设置文本信息
Message messge=session.createTextMessage("hello jms");
//发送信息
producer.send(messge);
// publisher.send(msg);
//提交会话
session.commit();
System.out.println("消息发送成功");
}
}
2接受者:
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Receive {
/**
* @param args
* @throws JMSException
*/
public static void main(String[] args) throws JMSException {
ConnectionFactory connectionFactory=new ActiveMQConnectionFactory(ActiveMQConnection.DEFAULT_USER, ActiveMQConnection.DEFAULT_PASSWORD, "tcp://localhost:61616");
Connection connection=connectionFactory.createConnection();
connection.start();
//创建会话
Session session=connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
//创建一个目的地,它用来接收消息: 这里创建的是一个Queue,表明我们用的是 p2p方式, 另一种Destination是 Topic,用于订阅模式
Destination destination=session.createQueue( "testQueue" );
//Topic destination = (Topic)context.lookup("topic/LeadfarTopic");
//创建消费者
MessageConsumer consumer=session.createConsumer(destination);
consumer.setMessageListener(new MessageListener() {
@Override
public void onMessage(Message arg0) {
TextMessage text=(TextMessage)arg0;
System.out.println("接收到了"+text);
}
});
}
}