ActiveMQ总结

ActiveMQ
ActiveMQ简介
ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。

ActiveMQ能做什么?
ActiveMQ是Apache推出的,一款开源的,免费的,完全支持JMS1.1和J2EE1.4规范的JMS provider实现的消息中间件(Message Oriented Middleware)

主要特点:

  1. 多种语言和协议编写客户端。语言: Java, C, C++, C#, Ruby, Perl, Python, PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP
  2. 完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)
  3. 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性
  4. 通过了常见J2EE服务器(如 Geronimo,JBoss 4, GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上
  5. 支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
  6. 支持通过JDBC和journal提供高速的消息持久化
  7. 从设计上保证了高性能的集群,客户端-服务器,点对点
  8. 支持Ajax
  9. 支持与Axis的整合
  10. 可以很容易得调用内嵌JMS provider,进行测试

1.消息中间件
MOM的基本功能:将信息以消息的形式,从一个应用程序传送到另一个或多个应用程序
MOM的主要特点:
(1)消息异步接受,类似手机短息的行为,消息发送者不需要等待消息接受者的响应,减少软件多系统集成的耦合度;
(2)消息可靠接受,确保消息在中间件可靠保存,只有接受方接受后才删除消息,多个消息也可以组成原子事务
消息中间件的主要应用场景:
在多个系统之间进行整合和通信的时候,通常会要求;
(1):可靠传输,数据不能丢失,有的时候,也会要求不能重复传输;
(2):异步传输,否则各个系统同步发送接受数据,互相等待,造成系统瓶颈
竞争者:
其他开源JMS供应商jbossmq(jboss 4)jboss messaging (jboss 5)RabbitMQjoram-4.3.21 2006-09-22openjms-0.7.7-alpha-3.zip December 26,2005mantamqubermqSomnifugiJMS 2005-7-27开源的JMS Provider大部分都已经停止发展了,剩下的几个都是找到了东家,和某种J2EE 服务器挂钩,比如jboss mq 与jboss,joram与jonas(objectweb组织),ActiveMQ 与Geronimo(ASF APACHE基金组织),而在这3个之间,从网络底层来看,只有ActiveMQ使用了NIO,单从这个角度来看ActiveMQ在性能上会有一定的优势。商业JMS供应商IBM WebSphereMQBEAWebLogicJMSOracleAQNonStop Server for Java Message Service(JMS)Sun Java System Message QueueSonic jmsTIBCO Enterprise For JMSKafka现在的商业J2EE 应用服务器大部分都会有JMS Provider的实现,毕竟应用服务器都已经花费不薄,也不在乎在里面送一个JMS Provider了,当然还是有独立的比如IBM WebSphere MQ,Sonic JMS,前者肯定是商用MQ(这个概念不仅仅是JMS Provier了,只能说JMS 只是它提供的一个应用)中间的巨无霸了。从这点来看,ActiveMQ明显的竞争者并不多,因为它是作为独立的开源JMS Provider出现的,很容易被用于多种结构设计中,使用ActiveMQ作为默认JMS Provider的开源项目有ServiceMix,Geronimo.
ActiveMQ的安装
进入http://activemq.apache.org/下载ActiveMQ

1.1. 安装环境:
1、activemq是java语言开发的,需要jdk
Jdk步骤:略 去linux.doc找
2、安装Linux系统。生产环境都是Linux系统。

1.2. 安装步骤
第一步: 把ActiveMQ 的压缩包上传到Linux系统。
使用SecureCRT连接linux系统,连接成功后 alt + p打开如下页面,直接拖入。

拖入的文件默认在/home目录下 输入 cd ~ 直接进入

第二步:解压缩。 解压到/usr/local
tar -zxf apache-activemq-5.12.0-bin.tar.gz -C /usr/local
第三步:启动。
使用bin目录下的activemq命令
启动:
[root@localhost bin]# ./activemq start
关闭:
[root@localhost bin]# ./activemq stop
查看状态:
[root@localhost bin]# ./activemq status

进入管理后台:
http://192.168.25.130:8161/admin
用户名:admin
密码:admin

进入如下页面:

1.3. ActiveMQ的消息形式
对于消息的传递有两种类型:
一种是点对点的,即一个生产者和一个消费者一一对应;
另一种是发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。
JMS定义了五种不同的消息正文格式,以及调用的消息类型,允许你发送并接收以一些不同形式的数据,提供现有消息格式的一些级别的兼容性。
  · StreamMessage – Java原始值的数据流
  · MapMessage–一套名称-值对
  · TextMessage–一个字符串对象
  · ObjectMessage–一个序列化的 Java对象
  · BytesMessage–一个字节的数据流
1.4. ActiveMQ的使用方法
点对点:

发布/订阅:

入门案例:

1.5. Queue
1.5.1. Producer
生产者:生产消息,发送端。
第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
第二步:使用ConnectionFactory对象创建一个Connection对象。
第三步:开启连接,调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个Queue对象。
第六步:使用Session对象创建一个Producer对象。
第七步:创建一个Message对象,创建一个TextMessage对象。
第八步:使用Producer对象发送消息。
第九步:关闭资源。
@Test     public void testQueueProducer() throws Exception {          // 第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。          //brokerURL服务器的ip及端口号          ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.25.130:61616”);          // 第二步:使用ConnectionFactory对象创建一个Connection对象。          Connection connection = connectionFactory.createConnection();          // 第三步:开启连接,调用Connection对象的start方法。          connection.start();          // 第四步:使用Connection对象创建一个Session对象。          //第一个参数:是否开启事务。true:开启事务,第二个参数忽略。          //第二个参数:当第一个参数为false时,才有意义。消息的应答模式。1、自动应答2、手动应答。一般是自动应答。          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);          // 第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个Queue对象。          //参数:队列的名称。          Queue queue = session.createQueue(“queue-test”);          // 第六步:使用Session对象创建一个Producer对象。          MessageProducer producer = session.createProducer(queue);          // 第七步:创建一个Message对象,创建一个TextMessage对象。          /TextMessage message = new ActiveMQTextMessage();          message.setText(“hello activeMq,this is my first test.”);/          TextMessage textMessage = session.createTextMessage(“hello activeMq,this is my first test.”);          // 第八步:使用Producer对象发送消息。          producer.send(textMessage);          // 第九步:关闭资源。          producer.close();          session.close();          connection.close();     }

1.5.2. Consumer
消费者:接收消息。
第一步:创建一个ConnectionFactory对象。
第二步:从ConnectionFactory对象中获得一个Connection对象。
第三步:开启连接。调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象。和发送端保持一致queue,并且队列的名称一致。
第六步:使用Session对象创建一个Consumer对象。
第七步:接收消息。
第八步:打印消息。
第九步:关闭资源
public class QueueCustomer {     @Test     public void recieve() throws Exception{          // 1.创建一个连接工厂 (Activemq的连接工厂)参数:指定连接的activemq的服务          ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.25.130:61616”);          // 2.获取连接          Connection connection = connectionFactory.createConnection();          // 3.开启连接          connection.start();          // 4.根据连接对象创建session          // 第一个参数:表示是否使用分布式事务(JTA)          // 第二个参数:如果第一个参数为false,第二个参数才有意义;表示使用的应答模式 :自动应答,手动应答.这里选择自动应答。          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);          // 5.根据session创建Destination(目的地,queue topic,这里使用的是queue)          Queue queue = session.createQueue(“queue-test”);          // 6.创建消费者          MessageConsumer consumer = session.createConsumer(queue);          //7.接收消息          //第一种//             while(true){//                  //接收消息 (参数的值表示的是超过一定时间 以毫秒为单位就断开连接)//                  Message message = consumer.receive(10000);//                  //如果message为空,没有接收到消息了就跳出//                  if(message==null){//                       break;//                  }//                 //                  if(message instanceof TextMessage){//                       TextMessage messaget = (TextMessage)message;//                       System.out.println(">>>获取的消息内容:"+messaget.getText());//获取消息内容//                  }//             }          System.out.println(“start”);          //第二种:               //设置监听器,其实开启了一个新的线程。          consumer.setMessageListener(new MessageListener() {               //接收消息,如果有消息才进入,如果没有消息就不会进入此方法               @Override               public void onMessage(Message message) {                    if(message instanceof TextMessage){                         TextMessage messaget = (TextMessage)message;                         try {                              //获取消息内容                              System.out.println(">>>获取的消息内容:"+messaget.getText());                         } catch (JMSException e) {                              e.printStackTrace();                         }                    }               }          });     System.out.println(“end”);          Thread.sleep(10000);//睡眠10秒钟。                   // 9.关闭资源          consumer.close();          session.close();          connection.close();     }}

1.6. Topic

1.6.1. Producer
使用步骤:
第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
第二步:使用ConnectionFactory对象创建一个Connection对象。
第三步:开启连接,调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个Topic对象。
第六步:使用Session对象创建一个Producer对象。
第七步:创建一个Message对象,创建一个TextMessage对象。
第八步:使用Producer对象发送消息。
第九步:关闭资源。

public class TopicProducer {     @Test     public void send() throws Exception{          // 1.创建一个连接工厂 (Activemq的连接工厂)参数:指定连接的activemq的服务          ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.25.130:61616”);          // 2.获取连接          Connection connection = connectionFactory.createConnection();          // 3.开启连接          connection.start();          // 4.根据连接对象创建session          // 第一个参数:表示是否使用分布式事务(JTA)          // 第二个参数:如果第一个参数为false,第二个参数才有意义;表示使用的应答模式 :自动应答,手动应答.这里选择自动应答。          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);          // 5.根据session创建Destination(目的地,queue topic,这里使用的是topic)          Topic topic = session.createTopic(“topic-test”);//---------------------          // 6.创建生产者          MessageProducer producer = session.createProducer(topic);          // 7.构建消息对象,(构建发送消息的内容) 字符串类型的消息格式(TEXTMessage)          TextMessage textMessage = new ActiveMQTextMessage();          textMessage.setText(“发送消息123”);// 消息的内容          // 8.发送消息          producer.send(textMessage);          // 9.关闭资源          producer.close();          session.close();          connection.close();     }}

1.6.2. Consumer
消费者:接收消息。
第一步:创建一个ConnectionFactory对象。
第二步:从ConnectionFactory对象中获得一个Connection对象。
第三步:开启连接。调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象。和发送端保持一致topic,并且话题的名称一致。
第六步:使用Session对象创建一个Consumer对象。
第七步:接收消息。
第八步:打印消息。
第九步:关闭资源
public class TopicCustomer1 {     @Test     public void reieve() throws Exception{           // 1.创建一个连接工厂 (Activemq的连接工厂)参数:指定连接的activemq的服务          ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.25.130:61616”);          // 2.获取连接          Connection connection = connectionFactory.createConnection();          // 3.开启连接          connection.start();          // 4.根据连接对象创建session          // 第一个参数:表示是否使用分布式事务(JTA)          // 第二个参数:如果第一个参数为false,第二个参数才有意义;表示使用的应答模式 :自动应答,手动应答.这里选择自动应答。          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);          // 5.根据session创建Destination(目的地,queue topic,这里使用的是queue)          Topic topic = session.createTopic(“topic-test”);//---------------------          // 6.创建消费者          MessageConsumer consumer = session.createConsumer(topic);          // 7.接收消息          while(true){               //接收消息 (参数的值表示的是超过一定时间 以毫秒为单位就断开连接)               Message message = consumer.receive(100000);               //如果message为空,没有接收到消息了就跳出               if(message==null){                    break;               }                             if(message instanceof TextMessage){                    TextMessage messaget = (TextMessage)message;                    System.out.println(">>>获取的消息内容:"+messaget.getText());//获取消息内容               }          }          // 第二种:          // 设置监听器,其实开启了一个新的线程。//        consumer.setMessageListener(new MessageListener() {//             // 接收消息,如果有消息才进入,如果没有消息就不会进入此方法//             @Override//             public void onMessage(Message message) {//                  if (message instanceof TextMessage) {//                       TextMessage messaget = (TextMessage) message;//                       try {//                            // 获取消息内容//                            System.out.println(">>>获取的消息内容:" + messaget.getText());//                       } catch (JMSException e) {//                            e.printStackTrace();//                       }//                  }//             }//        });          //Thread.sleep(10000);// 睡眠10秒钟。           // 9.关闭资源          consumer.close();          session.close();          connection.close();      }}

1.7. 小结
queue 是点对点模式,只能是一个生产者产生一个消息,被一个消费者消费。
topic 是发布订阅模式,一个生产者可以一个消息,可以被多个消费者消费。

queue 默认是存在于MQ的服务器中的,发送消息之后,消费者随时取。但是一定是一个消费者取,消费完消息也就没有了。
topic 默认是不存在于MQ服务器中的,一旦发送之后,如果没有订阅,消息则丢失。

JMS基本概念

  1. jms是什么?
    

Jms Java Message Service ,Java消息服务,是java EE 中的一个技术
2. JMS 规范
Jms定义了java中访问消息中间件的接口,并没有给予实现,实现JMS接口的消息中间件成为JMS Provider 例如activemq,kafka…
3. JMS provider: 实现JMS接口和规范的消息中间件
4. JMS message:JMS的消息,JMS消息由以下三个部分组成:
(1) 消息头:每个消息字段都有响应的getter和setter方法
(2) 消息属性:如果需要除消息头字段以外的值,那么可以使用消息属性
(3) 消息体:封装具体的消息数据
5. JMS producer 消息生产者,创建和发送JMS消息的客户端应用
6. JMS consumer 消息消费者,接受和处理JMS消息的客户端应用
消息的消费可以采用以下两种方式之一:

  1.    消息同步:通过调用消费者的receive方法从目的地中显示提取消息,receive方法可以一直阻塞消息到达
    
  2.    异步消息:客户可以为消费者注册一个消息监听器,以定义在消息到达时所采取的动作
    

JMS domains:消息传递域,jms规范定义了两种消息传递域:点对点(point-to-point 简称PTP)消息传递域和发布订阅消息传递域(publish/subscribe 简称pub/sub)

  1. 点对点消息传递域的特点如下:
    

(1) 每个消息只能有一个消费者
(2) 消息的生产者和消费者之间没有时间上的相关性。无论消费者在生产者发送消息的时候是否处于运行状态,他都可以提取消息。

  1. 发布/订阅消息传递域的特点如下:
    

(1) 每个消息可以有多个消费者
(2) 生产者和消费者之间有时间上的相关性。订阅一个主题的消费者只能消费它订阅之后发布的消息。JMS规范允许客户创建持久性订阅,或者在一定程度上放松了时间上的相关性要求,持久订阅允许消费者消费它在位处于激活状态时发送的消息。
3. 在点对点消息传递域中,目的地被称为队列(queue);在发布订阅消息传递域中,目的地被称为主题(topic)

4.JMS对象含义:
Connection factory:连接工厂,用来创建连接对象,以连接到JMS的provider
JMS Connection:封装了客户与JMS 提供者之间的一个虚拟的连接
JMS Session:是生产和消费消息的一个单线程上下文。会话用于创建消息生产者(producer)、消息消费者(consumer)和消息(message)等.会话提供了一个事务性的上下文,在这个上下文中,一组发送和接收被组合到了一个原子操作中。
Destination: 消息发送到的目的地
Acknowledge:签收
Transaction: 事务
JMS client: 用来收发消息的Java用
Non-JMS client:使用JMS provider本地API写的应用,用来替换JMS API实现收发消息的功能,通常会提供其他的一此特性,比如:CORBA,RMI等.
Administered objects:预定义的JMS对象,通常íprovider规范中有定义,提供给JMS客广端来访问,比如:ConnectionFactory和Destination

5.JMS消息组成
JMS 消息由以下几部分组成:消息头,属性和消息体
消息头包含消息的识别信息和路由信息,消息头包含一些标准的属性如下:
1:JMSDestination:由send方法设置
2:JMSDeliveryMode:由send方法设置
3:JMSExpiration:由send方法设置
4:JMSPriority:由send方法设置
5:JMSMessageID:由send方法设置
6:JMSTimestamp:由客户端设置
7:JMSCorrelationID:由客户端设置
8:JMSReplyTo:由客户端设置
9:JMSType:由客户端设置
10:JMSRedelivered:由JMS Provider设置
标准的 JMS 消息头包含以下属性:
1:JMSDestination:消息发送的目的地:主要是指Queue和Topig,自动分配
2:JMSDeliveryMode:(Topic中)传送模式。有两种:持久模式和非持久模式。 一条持久性的消息应该被传送“一次仅仅一次”,这就意味者如果JMS提供者出现故障, 该消息并不会丢失,它会往服务器恢复之后再次传递.一条非持久的消息最多会传送一次,这意味这服务器出现故障,该消息将永远消失,自动分配
3:JMSExpiration:消息过期时间,等与Destination的send 方法中的
timeToLive值加上发送时刻的GMT 时间值.如果timeToLive 值等于零,则
JMSExpiration 被设为零,表示该消息永不过期. 如果发送后, 在消息过期时间之后消息还没有被发送到目的地,则该消息被清除.自动分配
4:JMSPriority:消息优先级,从0-9十个级别, 0-4是普通消息, 5-9 是加急消息。 JMS不个要求JMS Provider严格按照这十个优先级发送消息, 但必须保证加急消息要先于普通消息到达.默认是4级:自动分配
5:JMSMessageID:唯一识别每个消息的标识,由JMS Provider 产生。.自动分配
6:JMSTimestamp:一个JMS Provider调send()方法时自动设置的。 它是消息被发送和消费者实际接收的时间差。自动分配
7:JMSCorrelationID:用来连接到另外一个消息,典型的应用是在回复消息中连接到原消息。在大多数情况下,JMSCorrelationID用于将一条消息标记为对
JMSMessageID标识的上一条消息的应答,不过,JMSCorrelationID可以是任何值,不仅仅是JMSMessageID.由开发者设置
8:JMSReplyTo:提供本消息回复消息的目的地址。由开发者设置
9:JMSType:消息类型的识别符。由开发者设置
10:JMSRedelivered:如果一个客户端收到一个设置了JMSRedelivered属性的消息,则表示可能客户端曾经在早此时候收到过该消息, 但并没有签收
(acknowledged).如果该消息被重新传送,JMSRedelivered=true反之,
JMSRedelivered =false.自动设置

  1. JMS的可靠性机制
    消息接收确认
    JMS消息只有在被确认之后,才认为已经被成功地消费了。 消息的成功消费通常包含三个阶段: 客户接收消息、客户处理消息和消息被确认。
    在事务性会话中,当一个事务被提交的时候,确认自动发生。 在非事务性会话中,消息何时被确认取决于创建会话时的应答模式(acknowledgement mode)该参数有以下三个可选值:
    Session.AUTO_ACKNOWLEDGE:当客户成功的从receive方法返回的时候,或者从MessageListener.onMessage方法成功返回的时候,会话自动确认客户收到的消息。
    Session.CLIENT_ACKNOWLEDGE:客户通过调用消息的acknowledge方法确认消息。 需要注意的是,在这种模式中,确认是在会话层上进行,确认一个被消费的消息将自动确认所有已被会话消费的消息。 例如,如果一个消息消费者消费了10个消
    息,然后确认第5 个消息,那么第五条之前的消息都被确认,之后的并未确认。
    Session.DUPS_ACKNOWLEDGE:该选择只是会话迟钝的确认消息的提交。 如果JMS provider失败, 那么可能会导致一些重复的消息。 如果是重复的消息,那么JMS provider 必须把消息头的JMSRedelivered字段设置为true

消息持久性,
JMS 支持以下两种消息提交模式:
PERSISTENT:指小JMS provider封寺久保存消息,以保证消息个会因为JMSprovider的尖败而丢失
NON_PERSISTENT:个要求JMS provider持久保存消息
消息优先级
可以使用消息优先级来指尔JMS provider首先提交紧急的消息。 优先级分10个级别,从0(最低)到9(最高)。如果个指定优先级,默认级别是4。 需要注意的是,JMS provider并不一定保证按照优先级的顺庁提交消息
消息过期
可以设置消息在一定时间后过期,默认是永个过期
消息的临时目的地
可以通过会话上的createTenporaryQueue 法利lcreateTemporary Topic方法来创建临时目的地。 它们的存在时间県限丁创建它们的连接所保持的时间。只有创建该临时目的地的连接上的消息消费者才能够从临时目的地中提取消息

持久订阅
首先消息生产者必须使用PERSISTENT提交消息。 客户可以通过会话上的createDurableSubscriber方法来创建一个持久订阅, 该方法的第一个参数必须是一个topic。第二个参数是订阅的名称。
JMS provider会存储发布到持久订阅对应的topic上的消息。 如果最初创建持久订阅的客户或者任何其它客户,使用相同的连接工厂和连接的客广ID,相同的主题和相同的订阅名,再次调用会话上的createDurableSubscriber方法,那么该持久订阅就会被激活。JMS provider会向客户发送客户处于非激活状念时所发布的消息。
持久订阅在某个时刻只能有一个激活的订阅者。 持久订阅在创建之后会直保留,直到应用程序调用会话上的unsubscribe方法

本地事务
在一个JMS客户端,可以使用本地事务来组合消息的发送和接收。 JMS
Session接口提供了commit和rol1back方法。事务提交意味着生产的所有消息被发送,消费的所有消息被确认: 事务回滚意味着生产的所有消息被销毁,消费的所有消息被恢复并重新提交,除非它们已经过期
事务性的会话总是车涉到事务处理,commit或rollback方法 一旦被调用,一个事务就结束了,而另一个事务被开始。关闭事务性会话将回滚其中的事务
需要注意的是, 如果使用请求/回复机制,即发一个消息,同时希望在同一个事务中等待接收该消息的回复,那么程庁将被挂起,因为知道事务提交,发送操作才会真正执行.
需要注意的还有 一个, 消息的生产和消费个能包含住同一个事务中。

JMS的PTP模型

非持久的Topic消息示例
对于非持久的Topic消息的发送
基本跟前面发送队列信息是一样的,只是把创建Destination的地方
建队列替换成创建Topic,例如:
Destination destination=session.createTopic(”MyTopic“);
对于非持久的Topic消息的接收
1.必须要接收方在线,然后客户端再发送信息,接收方才能接收到消息
2.同样把创建 Destination的地方,由创建队列替换成创建Topic,例如
Destination destination=session.createTopic(”MyTopic“);
3.由于不知道客户端发送多少信息,因此改成while循环的方式了,例如:
Message message= consumer.receive();
while(message!=null){
TextMessage txtMsg=(TextMessage)message;
System.out.printIn(“收到消息:”+txtMsg.getText());
message= consumer.receive(1000L);
}
持久的Topic消息示例
■对于持久的Topic消息的接收
ConnectionFactory cf=new ActiveMQConnectionFactory(tcp://192.1681.106:61616);
Connection connection= cf.createConnection();
connection.setClientID(“ccl”);
final Session session=connection.createSession(Boolean.TRUE,Session.AUTO_ACKNORZEDCE);
Topic destination=session.createTopic(”myTopic”);
TopicSubscriber ts=session.createDurableSubscriber(destination,”T1”);
connection.start();
Message message=ts.receive();
while(message!=null){
TextMessage txtMsg=(TextMessage)message;
session.commit();
System.out.println(“收到消息:”+ txtMsg.getText());
message=ts.receive(1000L);
session.close();
connection.close();
1.需要在连接上设置消费者id,用来识别消费者
2.需要创建TopicSubscriber来订阅
3.要设置好了过后再start这个connection
4.一定要先运行一次,等于向消息服务中间件注册这个消费者,然后再运行客户端发送信息,这个时候
无论消费者是否在线,都会接收到,不在线的话,下次连接的时候,会把没有收过的消息都接收下

启动activemq的方式:

已知启动方式:在activemq的bin目录下:./activemq start

此方法启动。默认调用/conf/activemq.xml
如何手动加载配置文件启动activemp呢?
这时我们将activemq.xml改名为activemq-2.xml

启动命令为: ./activemq start xbean:file …/conf/activemq-2.xml
如何查看activemq的日志呢?
在data的目录下 activemq.log 使用cat或者vi 或者vim 都可以查看

  1. Activemq整合springboot
    整合pom.xml
    导入:activemq相关依赖,和mq连接池依赖
    org.springframework.bootspring-boot-starter-activemqorg.apache.activemqactivemq-pool5.14.5

整合配置文件:application.yml
server: port: 8080context-path: /prospring:activemq:#mq服务的用户名user: admin#mq服务的密码password: admin#mq服务的链接地址broker-url: tcp://192.168.153.129:61616#连接池配置,默认不开启,需要手动开启pool:enabled: truemax-connections: 10#初始化queue的名称queueName: publish.queue#初始化Topic的名称topicName: publish.topic
配置文件 ActiveMQConfig :声明:Springboot对activemq完全支持:进行了很多自动配置,可以只配置url就可使用
package com.buba.witkey.boot.config; import org.apache.activemq.ActiveMQConnectionFactory; 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 org.springframework.jms.config.DefaultJmsListenerContainerFactory; import org.springframework.jms.config.JmsListenerContainerFactory; import javax.jms.Queue; import javax.jms.Topic; @Configuration public class ActiveMQConfig {    //取出application.yml中初始化的queue的name    @Value(" q u e u e N a m e &quot; )       p r i v a t e S t r i n g q u e u e N a m e ;       / / 取 出 a p p l i c a t i o n . y m l 中 初 始 化 的 t o p i c 的 n a m e       @ V a l u e ( &quot; {queueName}&quot;)    private String queueName;    //取出application.yml中初始化的topic的name    @Value(&quot; queueName")   privateStringqueueName;   //application.ymltopicname   @Value("{topicName}")    private String topicName;    //取出application.yml中初始化的topic的n用户名    @Value(" s p r i n g . a c t i v e m q . u s e r &quot; )       p r i v a t e S t r i n g u s r N a m e ;       / / 取 出 a p p l i c a t i o n . y m l 中 初 始 化 的 t o p i c 的 密 码       @ V a l u e ( &quot; {spring.activemq.user}&quot;)    private String usrName;    //取出application.yml中初始化的topic的密码    @Value(&quot; spring.activemq.user")   privateStringusrName;   //application.ymltopic   @Value("{spring.activemq.password}")    private  String password;    //取出application.yml中初始化的topic的url    @Value("${spring.activemq.broker-url}")    private  String brokerUrl;    //向spring容器中创建queue对象    @Bean    public Queue queue(){        return new ActiveMQQueue(queueName);    }    //向spring容器中创建topic对象    @Bean    public Topic topic(){        return new ActiveMQTopic(topicName);    }    //创建ActiveMQ的连接工厂    @Bean    public ActiveMQConnectionFactory connectionFactory() {        return new ActiveMQConnectionFactory(usrName, password, brokerUrl);    }    //创建监听器的连接工厂(PTP模式)    @Bean    public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ActiveMQConnectionFactory connectionFactory){        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();        bean.setConnectionFactory(connectionFactory);        return bean;    }    //创建监听器的连接工厂(pub/sub模式)    @Bean    public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ActiveMQConnectionFactory connectionFactory){        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();        //设置为发布订阅方式, 默认情况下使用的生产消费者方式        bean.setPubSubDomain(true);        bean.setConnectionFactory(connectionFactory);        return bean;    }}

测试:
创建生产者服务:
构建spring项目,按照如上方式加入pom,进行相关配置
开发生产者:

PubController
package com.buba.witkey.boot.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.annotation.JmsListener; import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.jms.Queue; import javax.jms.Topic; @RestController public class PubController {    //springboot提供操作消息收发的模板    @Autowired    private JmsMessagingTemplate jms;    //注入的queue消息传递域对象    @Autowired    private Queue queue;    @Autowired    //注入的topic消息传递域对象    private Topic topic;    //发送消息的方法,此时使用的是yml文件中的queueName,也就是publish.queue    @RequestMapping("/queue")    public String queue(){        for (int i = 0; i < 10 ; i++){            jms.convertAndSend(queue, “queue”+i);        }        return “queue 发送成功”;    }//此处监听消费者的反馈信息  即为SendTo注解返回的消息    @JmsListener(destination = “out.queue”)    public void consumerMsg(String msg){        System.out.println(msg);    }//topic模式发送消息    @RequestMapping("/topic")    public String topic(){        for (int i = 0; i < 10 ; i++){            jms.convertAndSend(topic, “topic”+i);        }        return “topic 发送成功”;    }} 
创建消费者a

QueueListener
此处作为消费者监听publish.queue中的消息
package com.buba.witkey.boot.controller; import org.springframework.jms.annotation.JmsListener; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Component; @Component public class QueueListener {     @JmsListener(destination = “publish.queue”, containerFactory = “jmsListenerContainerQueue”)    @SendTo(“out.queue”)//调用receive方法接受消息 使用@SendTo方法返回到out.queue中//生产者又可以从out.queue中获取消息,达到一个交互消息的作用    public String receive(String text){        System.out.println("QueueListener: consumer-a 收到一条信息: " + text);        return "consumer-a received : " + text;    }}

TopicListener:(此订阅者为非持久订阅)
此处作为消费者监听publish.topic中的消息

package com.buba.witkey.boot.controller; import org.springframework.jms.annotation.JmsListener; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Component; @Component public class TopicListener {        @JmsListener(destination = “publish.topic”, containerFactory = “jmsListenerContainerTopic”)        //@SendTo()        public void receive(String text){            System.out.println("TopicListener: consumer-a 收到一条信息: " + text);        }} 
持久订阅者:配置
找到ActiveMQConfig

更改topic的监听工厂:添加如下内容
@Bean public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ActiveMQConnectionFactory connectionFactory){    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();    //设置为发布订阅方式, 默认情况下使用的生产消费者方式//此方式为持久订阅    factory.setPubSubDomain(true);     factory.setClientId(“10001”);    factory.setSubscriptionDurable( true );    factory.setConnectionFactory(connectionFactory);    return factory;}

  1. activemq整合到项目中

ActiveMQ
ActiveMQ简介
ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线。ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,尽管JMS规范出台已经是很久的事情了,但是JMS在当今的J2EE应用中间仍然扮演着特殊的地位。

ActiveMQ能做什么?
ActiveMQ是Apache推出的,一款开源的,免费的,完全支持JMS1.1和J2EE1.4规范的JMS provider实现的消息中间件(Message Oriented Middleware)

主要特点:

  1. 多种语言和协议编写客户端。语言: Java, C, C++, C#, Ruby, Perl, Python, PHP。应用协议: OpenWire,Stomp REST,WS Notification,XMPP,AMQP
  2. 完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,事务)
  3. 对Spring的支持,ActiveMQ可以很容易内嵌到使用Spring的系统里面去,而且也支持Spring2.0的特性
  4. 通过了常见J2EE服务器(如 Geronimo,JBoss 4, GlassFish,WebLogic)的测试,其中通过JCA 1.5 resource adaptors的配置,可以让ActiveMQ可以自动的部署到任何兼容J2EE 1.4 商业服务器上
  5. 支持多种传送协议:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
  6. 支持通过JDBC和journal提供高速的消息持久化
  7. 从设计上保证了高性能的集群,客户端-服务器,点对点
  8. 支持Ajax
  9. 支持与Axis的整合
  10. 可以很容易得调用内嵌JMS provider,进行测试

1.消息中间件
MOM的基本功能:将信息以消息的形式,从一个应用程序传送到另一个或多个应用程序
MOM的主要特点:
(1)消息异步接受,类似手机短息的行为,消息发送者不需要等待消息接受者的响应,减少软件多系统集成的耦合度;
(2)消息可靠接受,确保消息在中间件可靠保存,只有接受方接受后才删除消息,多个消息也可以组成原子事务
消息中间件的主要应用场景:
在多个系统之间进行整合和通信的时候,通常会要求;
(1):可靠传输,数据不能丢失,有的时候,也会要求不能重复传输;
(2):异步传输,否则各个系统同步发送接受数据,互相等待,造成系统瓶颈
竞争者:
其他开源JMS供应商jbossmq(jboss 4)jboss messaging (jboss 5)RabbitMQjoram-4.3.21 2006-09-22openjms-0.7.7-alpha-3.zip December 26,2005mantamqubermqSomnifugiJMS 2005-7-27开源的JMS Provider大部分都已经停止发展了,剩下的几个都是找到了东家,和某种J2EE 服务器挂钩,比如jboss mq 与jboss,joram与jonas(objectweb组织),ActiveMQ 与Geronimo(ASF APACHE基金组织),而在这3个之间,从网络底层来看,只有ActiveMQ使用了NIO,单从这个角度来看ActiveMQ在性能上会有一定的优势。商业JMS供应商IBM WebSphereMQBEAWebLogicJMSOracleAQNonStop Server for Java Message Service(JMS)Sun Java System Message QueueSonic jmsTIBCO Enterprise For JMSKafka现在的商业J2EE 应用服务器大部分都会有JMS Provider的实现,毕竟应用服务器都已经花费不薄,也不在乎在里面送一个JMS Provider了,当然还是有独立的比如IBM WebSphere MQ,Sonic JMS,前者肯定是商用MQ(这个概念不仅仅是JMS Provier了,只能说JMS 只是它提供的一个应用)中间的巨无霸了。从这点来看,ActiveMQ明显的竞争者并不多,因为它是作为独立的开源JMS Provider出现的,很容易被用于多种结构设计中,使用ActiveMQ作为默认JMS Provider的开源项目有ServiceMix,Geronimo.
ActiveMQ的安装
进入http://activemq.apache.org/下载ActiveMQ

1.1. 安装环境:
1、activemq是java语言开发的,需要jdk
Jdk步骤:略 去linux.doc找
2、安装Linux系统。生产环境都是Linux系统。

1.2. 安装步骤
第一步: 把ActiveMQ 的压缩包上传到Linux系统。
使用SecureCRT连接linux系统,连接成功后 alt + p打开如下页面,直接拖入。

拖入的文件默认在/home目录下 输入 cd ~ 直接进入

第二步:解压缩。 解压到/usr/local
tar -zxf apache-activemq-5.12.0-bin.tar.gz -C /usr/local
第三步:启动。
使用bin目录下的activemq命令
启动:
[root@localhost bin]# ./activemq start
关闭:
[root@localhost bin]# ./activemq stop
查看状态:
[root@localhost bin]# ./activemq status

进入管理后台:
http://192.168.25.130:8161/admin
用户名:admin
密码:admin

进入如下页面:

1.3. ActiveMQ的消息形式
对于消息的传递有两种类型:
一种是点对点的,即一个生产者和一个消费者一一对应;
另一种是发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。
JMS定义了五种不同的消息正文格式,以及调用的消息类型,允许你发送并接收以一些不同形式的数据,提供现有消息格式的一些级别的兼容性。
  · StreamMessage – Java原始值的数据流
  · MapMessage–一套名称-值对
  · TextMessage–一个字符串对象
  · ObjectMessage–一个序列化的 Java对象
  · BytesMessage–一个字节的数据流
1.4. ActiveMQ的使用方法
点对点:

发布/订阅:

入门案例:

1.5. Queue
1.5.1. Producer
生产者:生产消息,发送端。
第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
第二步:使用ConnectionFactory对象创建一个Connection对象。
第三步:开启连接,调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个Queue对象。
第六步:使用Session对象创建一个Producer对象。
第七步:创建一个Message对象,创建一个TextMessage对象。
第八步:使用Producer对象发送消息。
第九步:关闭资源。
@Test     public void testQueueProducer() throws Exception {          // 第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。          //brokerURL服务器的ip及端口号          ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.25.130:61616”);          // 第二步:使用ConnectionFactory对象创建一个Connection对象。          Connection connection = connectionFactory.createConnection();          // 第三步:开启连接,调用Connection对象的start方法。          connection.start();          // 第四步:使用Connection对象创建一个Session对象。          //第一个参数:是否开启事务。true:开启事务,第二个参数忽略。          //第二个参数:当第一个参数为false时,才有意义。消息的应答模式。1、自动应答2、手动应答。一般是自动应答。          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);          // 第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个Queue对象。          //参数:队列的名称。          Queue queue = session.createQueue(“queue-test”);          // 第六步:使用Session对象创建一个Producer对象。          MessageProducer producer = session.createProducer(queue);          // 第七步:创建一个Message对象,创建一个TextMessage对象。          /TextMessage message = new ActiveMQTextMessage();          message.setText(“hello activeMq,this is my first test.”);/          TextMessage textMessage = session.createTextMessage(“hello activeMq,this is my first test.”);          // 第八步:使用Producer对象发送消息。          producer.send(textMessage);          // 第九步:关闭资源。          producer.close();          session.close();          connection.close();     }

1.5.2. Consumer
消费者:接收消息。
第一步:创建一个ConnectionFactory对象。
第二步:从ConnectionFactory对象中获得一个Connection对象。
第三步:开启连接。调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象。和发送端保持一致queue,并且队列的名称一致。
第六步:使用Session对象创建一个Consumer对象。
第七步:接收消息。
第八步:打印消息。
第九步:关闭资源
public class QueueCustomer {     @Test     public void recieve() throws Exception{          // 1.创建一个连接工厂 (Activemq的连接工厂)参数:指定连接的activemq的服务          ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(“tcp://192.168.25.130:61616”);          // 2.获取连接          Connection connection = connectionFactory.createConnection();          // 3.开启连接          connection.start();          // 4.根据连接对象创建session          // 第一个参数:表示是否使用分布式事务(JTA)          // 第二个参数:如果第一个参数为false,第二个参数才有意义;表示使用的应答模式 :自动应答,手动应答.这里选择自动应答。          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);          // 5.根据session创建Destination(目的地,queue topic,这里使用的是queue)          Queue queue = session.createQueue(“queue-test”);          // 6.创建消费者          MessageConsumer consumer = session.createConsumer(queue);          //7.接收消息          //第一种//             while(true){//                  //接收消息 (参数的值表示的是超过一定时间 以毫秒为单位就断开连接)//                  Message message = consumer.receive(10000);//                  //如果message为空,没有接收到消息了就跳出//                  if(message==null){//                       break;//                  }//                 //                  if(message instanceof TextMessage){//                       TextMessage messaget = (TextMessage)message;//                       System.out.println(">>>获取的消息内容:"+messaget.getText());//获取消息内容//                  }//             }          System.out.println(“start”);          //第二种:               //设置监听器,其实开启了一个新的线程。          consumer.setMessageListener(new MessageListener() {               //接收消息,如果有消息才进入,如果没有消息就不会进入此方法               @Override               public void onMessage(Message message) {                    if(message instanceof TextMessage){                         TextMessage messaget = (TextMessage)message;                         try {                              //获取消息内容                              System.out.println(">>>获取的消息内容:"+messaget.getText());                         } catch (JMSException e) {                              e.printStackTrace();                         }                    }               }          });     System.out.println(“end”);          Thread.sleep(10000);//睡眠10秒钟。                   // 9.关闭资源          consumer.close();          session.close();          connection.close();     }}

1.6. Topic

1.6.1. Producer
使用步骤:
第一步:创建ConnectionFactory对象,需要指定服务端ip及端口号。
第二步:使用ConnectionFactory对象创建一个Connection对象。
第三步:开启连接,调用Connection对象的start方法。
第四步:使用Connection对象创建一个Session对象。
第五步:使用Session对象创建一个Destination对象(topic、queue),此处创建一个Topic对象。
第六步:使用Session对象创建一个Producer对象。
第七步:创建一个Message对象,创建一个TextMessage对象。
第八步:使用Producer对象发送消息。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Angzush

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值