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

来源:互联网 发布:php 命名空间 大小写 编辑:程序博客网 时间:2024/05/21 17:12

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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.2.xsdhttp://www.springframework.org/schema/data/jpa    http://www.springframework.org/schema/data/jpa/spring-jpa.xsdhttp://www.springframework.org/schema/jmshttp://www.springframework.org/schema/jms/spring-jms-3.0.xsdhttp://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());@Autowiredprivate MessageProducer1 messageProducer1;@Autowiredprivate 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)//oddmessageProducer1.sendMessageToDefaultDestination(message);else//evenmessageProducer2.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


原创粉丝点击