ActiveMQ(5.10.0) - Spring Support

本文介绍了如何使用Spring框架与ActiveMQ实现消息发送与接收。详细讲述了配置文件设置、同步及异步消息处理,并提供了示例代码。同时,还讨论了Spring JmsTemplate的高效用法。

Maven Dependency:

<dependencies>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-all</artifactId>
        <version>${activemq.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-jaas</artifactId>
        <version>${activemq.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.activemq</groupId>
        <artifactId>activemq-spring</artifactId>
        <version>${activemq.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.1</version>
    </dependency>
</dependencies>
View Code

 

Using Spring to Send JMS Messages

1. applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
         
    <context:component-scan base-package="com.huey.hello" />

    <!-- 配置 JMS 连接工厂 -->
    <bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://10.1.242.146:61616" />
    </bean>
    
    <!-- 配置 JMS 模版 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory" />
        <!-- 指定默认的目的地 -->
        <property name="defaultDestination" ref="helloQueue" />
    </bean>

    <!-- 配置消息的目的地 -->
    <bean id="helloQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg index="0" value="example.HelloQueue" />
    </bean>

</beans>

2. Test Code: 

public class AMQTest extends SpringTest {

    @Resource(name = "jmsTemplate")
    JmsTemplate jmsTemplate;
    @Resource(name = "helloQueue")
    Destination helloQueue;

    @Test
    public void testSendMessage() throws Exception {
        
        jmsTemplate.send(helloQueue, new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {            
                return session.createTextMessage("Hello, ActiveMQ!");
            }
        });

        System.out.println("Send the message successfully.");
    }
    
}

 

Using Spring to Receive JMS Messages Synchronously

1. applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com.huey.hello" />


    <bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://10.1.242.146:61616" />
    </bean>

    
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="defaultDestination" ref="helloQueue" />
    </bean>

    <bean id="helloQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg index="0" value="example.HelloQueue" />
    </bean>
    
</beans>

2. Test Code: 

public class AMQTest extends SpringTest {

    @Resource(name = "jmsTemplate")
    JmsTemplate jmsTemplate;
    @Resource(name = "helloQueue")
    Destination helloQueue;
  
    @Test  
    public void testReceiveSyncMessage() throws Exception {  
        Message message = jmsTemplate.receive();  
        
        if (message == null) {
            System.out.println("There are not any messages.");
            return;
        }
        
        if (message instanceof TextMessage) {
            TextMessage textMessage = (TextMessage) message;
            System.out.println("Receive a text message: " + textMessage.getText());
        } else {
            System.out.println("Receive a non-text message.");
        }
        
    }   
    
}

 

Using Spring to Receive JMS Messages Asynchronously

1. applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com.huey.hello" />

    <bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://10.1.242.146:61616" />
    </bean>

    <bean id="helloQueue" class="org.apache.activemq.command.ActiveMQQueue">
        <constructor-arg index="0" value="example.HelloQueue" />
    </bean>
    
    <bean id="myQueueMessageListener" class="com.huey.hello.activemq.MyQueueMessageListener" />
    
    <bean id="queueJmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="destination" ref="helloQueue" />
        <property name="messageListener" ref="myQueueMessageListener" />
    </bean>
    
</beans>

2. MyQueueMessageListener:

package com.huey.hello.activemq;

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

public class MyQueueMessageListener implements MessageListener {

    public void onMessage(Message message) {
        try {
            if (message == null) {
                System.out.println("There are not any messages.");
                return;
            }
            
            if (message instanceof TextMessage) {
                TextMessage textMessage = (TextMessage) message;
                System.out.println("Receive a text message: " + textMessage.getText());
            } else {
                System.out.println("Receive a non-text message.");
            }
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

 

Working with Spring's JmsTemplate

Spring supports a handy abstraction, JmsTemplate, which allows you to hide some of the lower level JMS details when sending messages etc.

One thing to bear in mind with JmsTemplate is that by default it will create a new connection, session, producer for each message sent - then close them all down again. This is very inefficient! It is done like this to work in EJB containers which tend to use a special ConnectionFactory which does pooling.

If you are not using a JCA container to manage your JMS connections, we recommend you use our pooling JMS connection provider, (org.apache.activemq.pool.PooledConnectionFactory) from the activemq-pool library, which will pool the JMS resources to work efficiently with Spring's JmsTemplate or with EJBs.

e.g.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:component-scan base-package="com.huey.hello" />

    <bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://10.1.242.146:61616" />
    </bean>

    <bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
        <property name="connectionFactory" ref="connectionFactory" />
    </bean>    

    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="jmsFactory" />
        <property name="defaultDestination" ref="helloQueue" />
    </bean>

</beans>

The PooledConnectionFactory supports the pooling of Connection, Session and MessageProducer instances so it can be used with tools like Camel and Spring's JmsTemplate and MessagListenerContainer . Connections, sessions and producers are returned to a pool after use so that they can be reused later without having to undergo the cost of creating them again.

Note: while the PooledConnectionFactory does allow the creation of a collection of active consumers, it does not 'pool' consumers. Pooling makes sense for connections, sessions and producers, which can be seldom-used resources, are expensive to create and can remain idle a minimal cost. Consumers, on the other hand, are usually just created at startup and left going, handling incoming messages as they come. When a consumer is complete, it's preferred to shut down it down rather than leave it idle and return it to a pool for later reuse: this is because, even if the consumer is idle, ActiveMQ will keep delivering messages to the consumer's prefetch buffer, where they'll get held up until the consumer is active again.

If you are creating a collection of consumers (for example, for multi-threaded message consumption), you should consider keeping a low prefetch value (e.g. 10 or 20), to ensure that all messages don't end up going to just one of the consumers.

Spring's MessagListenerContainer should be used for message consumption. This provides all the power of MDBs - efficient JMS consumption and pooling of the message listeners - but without requiring a full EJB container.

You can use the activemq-pool org.apache.activemq.pool.PooledConnectionFactory for efficient pooling of the connections and sessions for your collection of consumers, or you can use the Spring JMS org.springframework.jms.connection.CachingConnectionFactory to achieve the same effect.

 

转载于:https://www.cnblogs.com/huey/p/5132827.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值