消息列队有两种消息模式,一种是点对点的消息模式,还有一种就是订阅的模式.
(1)、点对点方式(point-to-point)
点对点的消息发送方式主要建立在 Message Queue,Sender,reciever上,Message Queue 存贮消息,Sneder 发送消息,receive接收消息.具体点就是Sender Client发送Message Queue ,而 receiver Cliernt从Queue中接收消息和"发送消息已接受"到Quere,确认消息接收。消息发送客户端与接收客户端没有时间上的依赖,发送客户端可以在任何时刻发送信息到Queue,而不需要知道接收客户端是不是在运行
(2)、发布/订阅 方式(publish/subscriber Messaging)
发布/订阅方式用于多接收客户端的方式.作为发布订阅的方式,可能存在多个接收客户端,并且接收端客户端与发送客户端存在时间上的依赖。一个接收端只能接收他创建以后发送客户端发送的信息。作为subscriber ,在接收消息时有两种方法,destination的receive方法,和实现message listener 接口的onMessage 方法。
发送消息的基本步骤:
(1)、创建连接使用的工厂类JMS ConnectionFactory
(2)、使用管理对象JMS ConnectionFactory建立连接Connection,并启动
(3)、使用连接Connection 建立会话Session
(4)、使用会话Session和管理对象Destination创建消息生产者MessageSender
(5)、使用消息生产者MessageSender发送消息
实现代码:生产者
import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.DeliveryMode; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; import static java.lang.Thread.sleep; public class TOPSend_Pb { //连接账号 private String userName = ""; //连接密码 private String password = ""; //连接地址 private String brokerURL = "tcp://localhost:61616"; //connection的工厂 private ConnectionFactory factory; //连接对象 private Connection connection; //一个操作会话 private Session session; //目的地,其实就是连接到哪个队列,如果是点对点,那么它的实现是Queue,如果是订阅模式,那它的实现是Topic private Destination destination; //生产者,就是产生数据的对象 private MessageProducer producer; public static void main(String[] args) { TOPSend_Pb send = new TOPSend_Pb(); send.start(); } public void start(){ try { //根据用户名,密码,url创建一个连接工厂 factory = new ActiveMQConnectionFactory(userName, password, brokerURL); //从工厂中获取一个连接 connection = factory.createConnection(); //测试过这个步骤不写也是可以的,但是网上的各个文档都写了 connection.start(); //创建一个session //第一个参数:是否支持事务,如果为true,则会忽略第二个参数,被jms服务器设置为SESSION_TRANSACTED //第二个参数为false时,paramB的值可为Session.AUTO_ACKNOWLEDGE,Session.CLIENT_ACKNOWLEDGE,DUPS_OK_ACKNOWLEDGE其中一个。 //Session.AUTO_ACKNOWLEDGE为自动确认,客户端发送和接收消息不需要做额外的工作。哪怕是接收端发生异常,也会被当作正常发送成功。 //Session.CLIENT_ACKNOWLEDGE为客户端确认。客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会当作发送成功,并删除消息。 //DUPS_OK_ACKNOWLEDGE允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认。 session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //创建一个到达的目的地,其实想一下就知道了,activemq不可能同时只能跑一个队列吧,这里就是连接了一个名为"text-msg"的队列,这个会话将会到这个队列,当然,如果这个队列不存在,将会被创建 //======================================================= //点对点与订阅模式唯一不同的地方,就是这一行代码,点对点创建的是Queue,而订阅模式创建的是Topic destination = session.createTopic("topic-msg"); //======================================================= //从session中,获取一个消息生产者 producer = session.createProducer(destination); //设置生产者的模式,有两种可选 //DeliveryMode.PERSISTENT 当activemq关闭的时候,队列数据将会被保存 //DeliveryMode.NON_PERSISTENT 当activemq关闭的时候,队列里面的数据将会被清空 producer.setDeliveryMode(DeliveryMode.PERSISTENT); //创建一条消息,当然,消息的类型有很多,如文字,字节,对象等,可以通过session.create..方法来创建出来 long s = System.currentTimeMillis(); for(int i = 0 ; i < 100 ; i ++){ //发送一条消息 sleep(1000); // textMsg.setText("fyw哇哈哈哈哈哈哈哈哈哈"); TextMessage textMsg = session.createTextMessage("wahhhhh哈哈"+i); producer.send(textMsg); System.out.println("fyw"+i); } long e = System.currentTimeMillis(); System.out.println("发送消息成功"); System.out.println(e - s); //即便生产者的对象关闭了,程序还在运行哦 producer.close(); } catch (JMSException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } }
消息接收者从JMS接受消息的步骤
(1)、创建连接使用的工厂类JMS ConnectionFactory
(2)、使用管理对象JMS ConnectionFactory建立连接Connection,并启动
(3)、使用连接Connection 建立会话Session
(4)、使用会话Session和管理对象Destination创建消息接收者MessageReceiver
(5)、使用消息接收者MessageReceiver接受消息,需要用setMessageListener将MessageListener接口绑定到MessageReceiver消息接收者必须实现了MessageListener接口,需要定义onMessage事件方法。
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.ActiveMQConnectionFactory; public class PTPReceive { //连接账号 private String userName = ""; //连接密码 private String password = ""; //连接地址 private String brokerURL = "tcp://localhost:61616"; //connection的工厂 private ConnectionFactory factory; //连接对象 private Connection connection; //一个操作会话 private Session session; //目的地,其实就是连接到哪个队列,如果是点对点,那么它的实现是Queue,如果是订阅模式,那它的实现是Topic private Destination destination; //消费者,就是接收数据的对象 private MessageConsumer consumer; public static void main(String[] args) { PTPReceive receive = new PTPReceive(); receive.start(); } public void start(){ try { //根据用户名,密码,url创建一个连接工厂 factory = new ActiveMQConnectionFactory(userName, password, brokerURL); //从工厂中获取一个连接 connection = factory.createConnection(); //测试过这个步骤不写也是可以的,但是网上的各个文档都写了 connection.start(); //创建一个session //第一个参数:是否支持事务,如果为true,则会忽略第二个参数,被jms服务器设置为SESSION_TRANSACTED //第二个参数为false时,paramB的值可为Session.AUTO_ACKNOWLEDGE,Session.CLIENT_ACKNOWLEDGE,DUPS_OK_ACKNOWLEDGE其中一个。 //Session.AUTO_ACKNOWLEDGE为自动确认,客户端发送和接收消息不需要做额外的工作。哪怕是接收端发生异常,也会被当作正常发送成功。 //Session.CLIENT_ACKNOWLEDGE为客户端确认。客户端接收到消息后,必须调用javax.jms.Message的acknowledge方法。jms服务器才会当作发送成功,并删除消息。 //DUPS_OK_ACKNOWLEDGE允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认。 session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); //创建一个到达的目的地,其实想一下就知道了,activemq不可能同时只能跑一个队列吧,这里就是连接了一个名为"text-msg"的队列,这个会话将会到这个队列,当然,如果这个队列不存在,将会被创建 destination = session.createTopic("topic-msg"); //根据session,创建一个接收者对象 consumer = session.createConsumer(destination); //实现一个消息的监听器 //实现这个监听器后,以后只要有消息,就会通过这个监听器接收到 consumer.setMessageListener(new MessageListener() { public void onMessage(Message message) { if (message instanceof TextMessage) { try { //获取到接收的数据 String text = ((TextMessage) message).getText(); System.out.println(text); } catch (JMSException e) { e.printStackTrace(); } } } }); //关闭接收端,也不会终止程序哦 // consumer.close(); } catch (JMSException e) { e.printStackTrace(); } } }
Topic和queue的最大区别在于topic是以广播的形式,通知所有在线监听的客户端有新的消息,没有监听的客户端将收不到消息;而queue则是以点对点的形式通知多个处于监听状态的客户端中的一个。