Spring结合嵌入式ActiveMQ使用消息队列

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xmlns:amq="http://activemq.apache.org/schema/core"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
		http://www.springframework.org/schema/data/jpa
    	http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
		http://www.springframework.org/schema/jms
		http://www.springframework.org/schema/jms/spring-jms-3.0.xsd
		http://activemq.apache.org/schema/core
  		http://activemq.apache.org/schema/core/activemq-core-5.1.0.xsd">
......
	<!-- Embedded ActiveMQ Broker -->
	<amq:broker id="broker" useJmx="false" persistent="false">
		<amq:transportConnectors>
			<amq:transportConnector uri="tcp://localhost:61617" />
		</amq:transportConnectors>
	</amq:broker>
	<import resource="classpath:activemq-properties.xml" />
	<import resource="classpath:activemq-jms.xml" />
</beans>
这里引入了activemq-properties.xml

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

  <bean id="jmsProperties"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
        name="jmsProperties">
    <property name="order" value="99999" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="properties">
      <value>

        <!-- JMS -->
        JMS.BROKER.URL=tcp://localhost:61617
        JMS.QUEUE.NAME1=IN_QUEUE1
        JMS.QUEUE.NAME2=IN_QUEUE2


      </value>
    </property>
  </bean>

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

  <!-- ActiveMQ connection factory -->
  <bean id="amqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <constructor-arg index="0" value="${JMS.BROKER.URL}" />
  </bean>

  <!-- ConnectionFactory Definition -->
  <bean id="connectionFactory1"
        class="org.springframework.jms.connection.CachingConnectionFactory">
    <constructor-arg ref="amqConnectionFactory" />
    <property name="sessionCacheSize" value="10"></property>
  </bean>
  <bean id="connectionFactory2"
        class="org.springframework.jms.connection.CachingConnectionFactory">
    <constructor-arg ref="amqConnectionFactory" />
    <property name="sessionCacheSize" value="10"></property>
  </bean>

  <!-- Destination Queue -->
  <bean id="destinationQueue1" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg index="0" value="${JMS.QUEUE.NAME1}" />
  </bean>
  <bean id="destinationQueue2" class="org.apache.activemq.command.ActiveMQQueue">
    <constructor-arg index="0" value="${JMS.QUEUE.NAME2}" />
  </bean>

  <!-- Message converter -->
  <bean id="messageConv" class="com.sap.c4c.wechat.jms.MessageConverter"><!--自定义的消息转换器-->

  </bean>

  <!-- JmsTemplate Definition -->
  <!--<bean id="jmsTemplate1" class="com.sap.c4c.wechat.jms.MessageJmsTemplate">--><!--自定义的消息JMS模板,但其实没有必要,可以像下面两个那样-->
    <!--<property name="connectionFactory" ref="connectionFactory1" />-->
    <!--<property name="defaultDestination" ref="destinationQueue1" />-->
    <!--<property name="messageConverter" ref="messageConv"></property>-->
  <!--</bean>-->
  <bean id="jmsTemplate1" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="connectionFactory1" />
    <property name="defaultDestination" ref="destinationQueue1" />
    <property name="messageConverter" ref="messageConv"></property>
  </bean>
  <bean id="jmsTemplate1_b" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="connectionFactory1" />
    <property name="defaultDestination" ref="destinationQueue1" />
    <property name="messageConverter" ref="messageConv"></property>
  </bean>
  <bean id="jmsTemplate2" class="com.sap.c4c.wechat.jms.MessageJmsTemplate">
    <property name="connectionFactory" ref="connectionFactory2" />
    <property name="defaultDestination" ref="destinationQueue2" />
    <property name="messageConverter" ref="messageConv"></property>
  </bean>

  <!-- Message Producer -->
  <bean id="messageProducer1" class="com.sap.c4c.wechat.jms.MessageProducer1" ><!--第一种消息生产者-->
    <!--<property name="jmsTemplate">--><!--这里不定义,在类中定义-->
      <!--<list>-->
        <!--<ref bean="jmsTemplate_1" />-->
        <!--<ref bean="jmsTemplate_2" />-->
      <!--</list>-->
    <!--</property>-->
  </bean>
  <bean id="messageProducer2" class="com.sap.c4c.wechat.jms.MessageProducer2" /><!--第二种消息生产者-->

  <!-- Message Consumer -->
  <bean id="messageConsumer1" class="com.sap.c4c.wechat.jms.MessageConsumer1" /><!--第一种消息消费者-->
  <bean id="messageConsumer2" class="com.sap.c4c.wechat.jms.MessageConsumer2" /><!--第二种消息消费者-->

  <!-- Message Consumer Container -->
  <bean id="container1"
          class="org.springframework.jms.listener.DefaultMessageListenerContainer"><!--第一套消息传送-->
    <property name="connectionFactory" ref="connectionFactory1" />
    <property name="destinationName" value="${JMS.QUEUE.NAME1}" />
    <property name="messageListener" ref="messageConsumer1" />
  </bean>
  <bean id="container2"
        class="org.springframework.jms.listener.DefaultMessageListenerContainer"><!--第二套消息传送,这里允许多个第二种消费者-->
    <property name="connectionFactory" ref="connectionFactory2" />
    <property name="destinationName" value="${JMS.QUEUE.NAME2}" />
    <property name="messageListener" ref="messageConsumer2" />
    <!-- 配置多个消费者,可以是具体数值,也可以是数值区间,根据消息的规模来确定消费者的多少 -->
    <property name="concurrency" value="4-8"></property>
  </bean>

</beans>
它们都放在src/main/resources下

pom.xml相关部分

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jms</artifactId>
			<version>${org.springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.activemq</groupId>
			<artifactId>activemq-all</artifactId>
			<version>5.9.0</version>
			<!--<scope>test</scope>-->
		</dependency>
		<dependency>
			<groupId>org.apache.xbean</groupId>
			<artifactId>xbean-spring</artifactId>
			<version>3.7</version>
		</dependency>

MessageJmsTemplate

public class MessageJmsTemplate extends org.springframework.jms.core.JmsTemplate{

}

MessageConverter

import org.springframework.jms.support.converter.MessageConversionException;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import java.io.Serializable;

public class MessageConverter implements org.springframework.jms.support.converter.MessageConverter{

    @Override
    public Message toMessage(Object o, Session session) throws JMSException, MessageConversionException {
        Message message=session.createObjectMessage((Serializable) o);
        int group=Integer.parseInt(((com.sap.c4c.wechat.model.Message)o).getContent());
        message.setStringProperty("JMSXGroupID","group"+group);
//        message.setIntProperty("JMSXGroupSeq", -1);
        return message;
    }

    @Override
    public Object fromMessage(Message message) throws JMSException, MessageConversionException {
        ObjectMessage objMessage = (ObjectMessage) message;
        return objMessage.getObject();
    }
}

MessageProducer1

import com.sap.c4c.wechat.model.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;

import java.util.logging.Logger;

public class MessageProducer1 {
    private static final Logger logger = Logger.getLogger(MessageProducer1.class.getName());
    @Autowired
    private JmsTemplate jmsTemplate1;
    @Autowired
    private JmsTemplate jmsTemplate1_b;

    public void sendMessageToDefaultDestination(Message message) {
        logger.info("producer1: "+message.getContent());
        if(Integer.parseInt(message.getContent())%3==0) {
            message.setContent(message.getContent() + "_b");
            jmsTemplate1_b.convertAndSend(message);
        }else
        {
            jmsTemplate1.convertAndSend(message);
        }
    }

}

MessageProducer2

import com.sap.c4c.wechat.model.Message;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.logging.Logger;

public class MessageProducer2 {
    private static final Logger logger = Logger.getLogger(MessageProducer2.class.getName());
    @Autowired
    private MessageJmsTemplate jmsTemplate2;

    public void sendMessageToDefaultDestination(Message message) {
        logger.info("producer2: "+message.getContent());
        jmsTemplate2.convertAndSend(message);
    }

}

MessageConsumer1

import com.sap.c4c.wechat.model.Message;
import com.sap.c4c.wechat.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import java.util.logging.Logger;

public class MessageConsumer1 implements MessageListener {
    private static final Logger logger = Logger.getLogger(MessageConsumer1.class.getName());
    @Autowired
    MessageService messageService;

    @Override
    public void onMessage(javax.jms.Message message) {
            try {
                ObjectMessage objMessage=(ObjectMessage) message;
                Object obj = objMessage.getObject();
                Message wechatMessage = (Message) obj;
                //TODO
                logger.info("consumer1: "+wechatMessage.getContent()+" thread-"+Thread.currentThread().getName());

            } catch (JMSException ex) {
                throw new RuntimeException(ex);
            }
    }

}

MessageConsumer2

import com.sap.c4c.wechat.model.Message;
import com.sap.c4c.wechat.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.jms.JMSException;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import java.util.logging.Logger;

public class MessageConsumer2 implements MessageListener {
    private static final Logger logger = Logger.getLogger(MessageConsumer2.class.getName());
    @Autowired
    MessageService messageService;

    @Override
    public void onMessage(javax.jms.Message message) {
            try {
                ObjectMessage objMessage=(ObjectMessage) message;
                Object obj = objMessage.getObject();
                Message wechatMessage = (Message) obj;
                //TODO
                logger.info("consumer2: "+wechatMessage.getContent()+" thread-"+Thread.currentThread().getName());

            } catch (JMSException ex) {
                throw new RuntimeException(ex);
            }
    }

}

MessageController

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;

import io.swagger.annotations.Api;

import org.apache.commons.io.IOUtils;
import org.apdplat.word.WordSegmenter;
import org.apdplat.word.segmentation.Word;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;

@RestController("ControllerV1")
@RequestMapping("/v1/message")
@Api(value="Message")
public class MessageController extends GenericController<MessageDTO, Message> {//这里的Message是一个Model,有String类型的content成员
	private static final Logger logger = LoggerFactory.getLogger(MessageController.class.getName());

	@Autowired
	private MessageProducer1 messageProducer1;
	@Autowired
	private MessageProducer2 messageProducer2;

	@RequestMapping(value = "/{id}",method = RequestMethod.GET)
	public void test(@PathVariable int id) throws Exception
	{
		Message message=new Message();
		message.setContent(id+"");
		if(id%2!=0)//odd
			messageProducer1.sendMessageToDefaultDestination(message);
		else//even
			messageProducer2.sendMessageToDefaultDestination(message);
	}
}
这样模拟实现了多个queue,多个consumer的ActiveMQ
MessageConverter使用了消息的分组,运行发现JMSGroupID相同的总是在同一个线程(同一个Consumer2)中处理。


参考链接:

http://www.jeejava.com/embedded-activemq-and-spring-jms-integration/

http://activemq.apache.org/features.html

http://activemq.apache.org/message-groups.html

http://activemq.apache.org/spring-support.html

http://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection.html

http://elim.iteye.com/blog/1900937

http://isoftyh.iteye.com/blog/1774015

https://stackoverflow.com/questions/18802982/no-declaration-can-be-found-for-element-contextannotation-config

http://coderbase64.iteye.com/blog/2065528

https://codedependents.com/2009/10/16/efficient-lightweight-jms-with-spring-and-activemq/

http://www.blogjava.net/ldd600/archive/2010/11/02/336755.html

https://stackoverflow.com/questions/30183907/activemq-how-to-programmatically-monitor-embedded-broker

http://blog.csdn.net/u010248330/article/details/62429001

http://www.360doc.com/content/16/0406/18/203871_548376577.shtml

http://www.bubuko.com/infodetail-2065759.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值