JMS学习(二)activeMQ

来源:互联网 发布:daemontools linux 编辑:程序博客网 时间:2024/04/30 07:57

1.JMS之activeMQ

由于最近比较的忙, 暂时没有更新,稍后有时间更新和spring的整合,关于activemq更深层次的,在今后的时间和大家一起学习了


2015-05-30,眼看就月底了,一个月该做的是还是要努力的完成,做人做事要有始有终,定的计划就要努力完成。
之前的一篇文章简单的介绍了下JMS以及activeMQ的一个入门,这篇就总结和activeMQ的使用


话不多说, 先上一个例子,然后再慢慢分析,我习惯先看到东西, 再来慢慢了解他,这样理解更加形象。

2.实例分析

spring整合activemq就是把连接工厂和创建连接的事交由spring处理,然后使用JmsTemplate做收发消息

2.1实例

spring-activemq.xml 配置如下:

<!-- ActiveMQ 连接    -->   <bean id="targetConnectionFactory"  class="org.apache.activemq.ActiveMQConnectionFactory">         <property name="brokerURL" value="tcp://localhost:61616" />         <property name="useAsyncSend" value="true"/>     </bean>     <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->      <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">          <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->          <property name="targetConnectionFactory" ref="targetConnectionFactory"/>      </bean>      <bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">             <constructor-arg index="0" value="myqueue"></constructor-arg>      </bean>   <!--    <bean id="myMessageConverter" class="fun.activemq.myMessageConverter"></bean>    -->   <bean id="jmsTemplate"             class="org.springframework.jms.core.JmsTemplate">         <property name="connectionFactory" ref="connectionFactory"></property>         <property name="defaultDestination" ref="destination"></property>        <!--  <property name="messageConverter" ref="myMessageConverter"></property>   -->   </bean>   <bean id="messageListener" class="fun.spring_activemq.MyMessageListener"></bean>    <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer" lazy-init="false">         <property name="connectionFactory" ref="connectionFactory"></property>         <property name="destination" ref="destination"></property>         <property name="messageListener" ref="messageListener"></property>         <!-- 0:CACHE_NONE,1:CACHE_CONNECTION,2:CACHE_SESSION,3:CACHE_CONSUMER,4:CACHE_AUTO  -->        <property name="cacheLevel" value="0"/>     </bean>

Sender.java

package fun.spring_activemq;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.Session;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jms.core.JmsTemplate;import org.springframework.jms.core.MessageCreator;import org.springframework.stereotype.Component;@Component("sender")public class Sender{    @Autowired    private JmsTemplate jmsTemplate;    public void sendMsg(Destination destination,final String message){        jmsTemplate.send(destination,new MessageCreator() {            @Override            public Message createMessage(Session session) throws JMSException {                return session.createTextMessage(message);            }        });    }}

接收消息者:这里整合的时候使用的是异步接收消息的,使用实现MessageListener接口的java类

MyMessageListener.java
“`java
package fun.spring_activemq;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class MyMessageListener implements MessageListener{

@Overridepublic void onMessage(Message message) {    // TODO implement MessageListener.onMessage     TextMessage textMsg = (TextMessage) message;      try {        System.out.println("收到消息:"+textMsg.getText());    } catch (JMSException e) {        e.printStackTrace();    }}

}

“`
test程序

    @Test    public void sendMsg(){        ApplicationContext ac = new ClassPathXmlApplicationContext("spring/*.xml");        Sender sender = (Sender) ac.getBean("sender");        Destination destination = (Destination) ac.getBean("destination");        System.out.println("send message: hello activemq");        sender.sendMsg(destination,"hello activemq");        System.out.println("after send message: hello activemq");    }

2.2实例代码分析

  1. 上面这个例子中sender类里面注入JmsTemplate ,使用jmsTemplate进行发送消息,发送消息的时候从之前的一中说到的可以知道需要一个session,这里使用MessageCreator 这个类,他会使用内部的消息转换器来转换消息。然后返回一个Message,由jmsTemplate来发送。
  2. 消息接受者是一个MessageListener,实现了MessageListener接口,实现onMessage方法就行了,所以这里可以看出,如果要把消息持久化在数据库中的话,可以在这里进行处理。
  3. 关于配置,应该很明了,最简单的配置,分别配置了ConnectionFactory,Destination,MessageListener,JmsTemplate和jmsContainer。

可以看出来,其实和我在第一篇文章中写的步骤是差不多的,进过spring处理之后简化了不少步骤

3.spring+activeMQ

3.1 同步消息和异步消息

3.1.1 同步和异步

刚开始使用spring整合的时候我就发现,为什么这个里面没有使用receiver呢,MessageListener就是receiver,那么,这和直接写receiver有什么区别呢?后来和朋友交流才知道是同步和异步方式的问题。
同步的接收消息会使接受者处于阻塞的状态,知道接收到消息的时候为止,相反异步消息不会是应用程序发生阻塞,两种情况具体要看业务的需求,如果应用程序必须要接收到回应之后才做下一步的工作的话,那么我们就该选择使用同步的消息,相反可使用异步的消息

3.1.2 同步异步实现上的区别

不论同步还是发送消息的写法总是一样,唯一不同的是接受者的实现方式,如果使用MessageListener接口的话,这时就是一个异步接收消息的实现,如果使用自己写一个receiver的话,就如同JMS学习(一) 中的写法一样,使用循环接听接收消息,但是使用jmsTemplate的receive方法,类似使用send方法,这个方法是一个阻塞的方法,这个类似c/c++中网络编程中的receive一样。

3.2 Connectionfactory

在一本上上看到 JNDI factory之类的,不是很会用,可以再在网上查阅
一般我就使用例子中的集成方式,又activeMQ提供工厂,spring的SingleConnectionFactory 管理就行

3.3 JmsTemplate

使用过spring的都知道,spring在整合各种框架的时候都会提供一个叫做 xxxTemplate 的一个操作工具,帮助开发人员减少重复的代码,这里也是一样的,jmsTemplate就是发送和接收消息的模板。了解jmsTemlate,就需要了解他的一些方法

方法 参数 说明 补充 send 1.MessageCreateor;2.Destination,MessageCreator;3.String destinationName,MessageCreator MessageCreator创建消息,Destination是消息发送地,没有时使用默认 convertandsend 1.Message;2.Destination,Message;3.String destName,Message;4.前两个参数通之前,第三个参数MessagePostCreator 同send 类似,只不过会条用自己配置的消息转换器 ,MessagePostCreator可以对实际的Message对象的一些消息头和应用程序属性进行设置,例如设置优先级

接受消息的方法类似,对应的有 receiver ,receiverandconvert,receiverseleced
其中不同的就是receiverselected可以对要接受的消息进行筛选,例如接受优先级大于4的消息
Message msg = jmsTemplate.receiverselected(“JMSPriority > 4”);
具体用法就查阅API啦

3.4 消息转换器

说消息转换器之前先说说消息。

消息类型

在activeMQ中的有

java类 对应消息类 String TextMessage Object ObjectMessage Byte[] ByteMessage java.util.Map MapMessage

转换器实现

在上面说到了使用 带convert**的方法的时候,就会调用内部消息转换器对应的进行转换,如果不想使用内部消息转换器的话,就自己实现消息转换器
实现MessageConverter接口,实现里面的fromMessage和toMessage就可以了,然后再spring的配置文件中把这个bean**注入到JmsTemplate**就可以了,如同上面配置文件中被注释的代码。

3.5 MessageListener

消息侦听器需要注入到消息容器(JmsContainer)中才起作用,实现MessageListener的方法有3,
1. javax.jms.MessageListener ,实现这个接口的类
2. Spring的SeesionAwareMessageListener ,实现这个接口
3. 使用spring提供的MessageListenerAdapter

3.5.1 SeesionAwareMessageListener

三者的区别在于,如果在接受到消息之后需要拿到session对象来进行一些操作,这个时候sessionAwarelistener可以获得这个对象,例如拿到消息后需要作出回信,这个时候代码如下:

//消息接受完//.....//回应MessageProducer producer = session.createProducer(message.getJMSReplyto());TextMessage msg = session.createTextMessage();msg.setJMSCorrelationID(message.getJMSMessageID());msg.setText("message "+message.getJMSMessageID()+" received" );producer.send(msg);

3.5.2 MessageListenerAdapter

使用这个类的时候,可以将任何一个普通的java类的某个方法做为接受方法,单作为接受方法的类的参数类型要是对用消息类型的java类型,例如: handlerMessage(String msg)就只接受TextMessage了。

这是spring的Messagelistener的配置使用

<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">        <constructor-arg>            <bean class="fun.spring_activemq.MyListener"></bean>        </constructor-arg>        <!-- <property name="defaultListenerMethod" value="defaultReceive"></property> -->   </bean>  

使用 指明接收消息的类,还可以使用上面注释的部分来指明具体方法(要保证java类有此方法)

3.6 JmsContainer

JmsContainer的实现有两个

  1. DefaultMessageListnerContainer –>支持并发,动态调整线程数,和分布式事务可集成
  2. SimpleMessageListnerContainer –> 支持并发,本地事务集成

基出就差不多,关于activemq更深的东西就在应用中慢慢掌握加以深刻理解,熟练运用了。

0 0
原创粉丝点击