ActiveMQ实战(六)--Spring整合ActiveMQ实现队列和主题发布订阅通信

来源:互联网 发布:java运行环境变量配置 编辑:程序博客网 时间:2024/04/29 01:36

一、新建Maven项目


工具使用的是IDEA,具体操作如下,New-->Project










创建的项目如下所示




然后在main下新建java目录、创建好之后、在java目录上右键转换为source




完整的项目结构如下:




二、添加依赖


POM.XML文件如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  <modelVersion>4.0.0</modelVersion>  <groupId>com.fendo.activemq</groupId>  <artifactId>activemq_demo</artifactId>  <packaging>war</packaging>  <version>1.0-SNAPSHOT</version>  <name>activemq_demo Maven Webapp</name>  <url>http://maven.apache.org</url>  <developers>    <developer>      <id>fendo</id>      <name>fendo</name>      <email>fendo@qq.com</email>    </developer>  </developers>  <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>    <fastjson.vesrion>1.2.35</fastjson.vesrion>    <activemq.version>5.13.2</activemq.version>    <activemq-pool.version>5.15.0</activemq-pool.version>    <spring.version>4.1.9.RELEASE</spring.version>    <junit.version>4.12</junit.version>  </properties>  <dependencies>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-core</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-oxm</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-tx</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-jdbc</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-aop</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-context-support</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-expression</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-orm</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-web</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-webmvc</artifactId>      <version>${spring.version}</version>    </dependency>    <dependency>      <groupId>org.apache.xbean</groupId>      <artifactId>xbean-spring</artifactId>      <version>4.4</version>    </dependency>    <dependency>      <groupId>commons-logging</groupId>      <artifactId>commons-logging</artifactId>      <version>1.2</version>    </dependency>    <dependency>      <groupId>com.alibaba</groupId>      <artifactId>fastjson</artifactId>      <version>${fastjson.vesrion}</version>    </dependency>    <!-- Active MQ -->    <dependency>      <groupId>org.apache.activemq</groupId>      <artifactId>activemq-all</artifactId>      <version>${activemq.version}</version>    </dependency>    <dependency>      <groupId>org.apache.activemq</groupId>      <artifactId>activemq-pool</artifactId>      <version>${activemq-pool.version}</version>    </dependency>    <!-- spring-jms -->    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-jms</artifactId>      <version>${spring.version}</version>    </dependency>    <!-- spring -->    <!--单元测试-->    <dependency>      <groupId>org.springframework</groupId>      <artifactId>spring-test</artifactId>      <version>${spring.version}</version>      <scope>test</scope>    </dependency>    <dependency>      <groupId>junit</groupId>      <artifactId>junit</artifactId>      <version>${junit.version}</version>      <scope>test</scope>    </dependency>  </dependencies>  <build>    <finalName>activemq_demo</finalName>  </build></project>


三、添加配置文件


web.xml

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">  <display-name>Archetype Created Web Application</display-name>  <!-- Log4J Start -->  <context-param>    <param-name>log4jConfigLocation</param-name>    <param-value>classpath:log4j.properties</param-value>  </context-param>  <context-param>    <param-name>log4jRefreshInterval</param-name>    <param-value>6000</param-value>  </context-param>  <context-param>    <param-name>log4jExposeWebAppRoot</param-name>    <param-value>false</param-value>  </context-param>  <!-- Spring Log4J config -->  <!-- Spring 编码过滤器 start -->  <filter>    <filter-name>encodingFilter</filter-name>    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>    <init-param>      <param-name>encoding</param-name>      <param-value>UTF-8</param-value>    </init-param>    <init-param>      <param-name>forceEncoding</param-name>      <param-value>true</param-value>    </init-param>  </filter>  <filter-mapping>    <filter-name>encodingFilter</filter-name>    <url-pattern>/*</url-pattern>  </filter-mapping>  <!-- Spring 编码过滤器 End -->  <!-- Spring Application Context Listener Start -->  <context-param>    <param-name>contextConfigLocation</param-name>    <param-value>classpath*:/spring-context*.xml</param-value>  </context-param>  <listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  </listener>  <!-- Spring Application Context Listener End -->  <!-- Spring MVC Config Start -->  <servlet>    <servlet-name>SpringMVC</servlet-name>    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    <init-param>      <param-name>contextConfigLocation</param-name>      <param-value>classpath:spring-mvc.xml</param-value>    </init-param>    <load-on-startup>1</load-on-startup>  </servlet>  <servlet-mapping>    <servlet-name>SpringMVC</servlet-name>    <url-pattern>/*</url-pattern>  </servlet-mapping>  <!-- Spring MVC Config End --></web-app>

spring-context.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:context="http://www.springframework.org/schema/context"       xmlns:mvc="http://www.springframework.org/schema/mvc"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd       http://www.springframework.org/schema/context       http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">    <mvc:annotation-driven />    <!-- 使用Annotation自动注册Bean,解决事物失效问题:在主容器中不扫描@Controller注解,在SpringMvc中只扫描@Controller注解。  -->    <context:component-scan base-package="com.fendo.activemq"><!-- base-package 如果多个,用“,”分隔 -->        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>    </context:component-scan></beans>

spring-mvc.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:mvc="http://www.springframework.org/schema/mvc"       xmlns:context="http://www.springframework.org/schema/context"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">    <mvc:annotation-driven />    <mvc:default-servlet-handler/>    <!-- 使用Annotation自动注册Bean,只扫描@Controller -->    <context:component-scan base-package="com.fendo.activemq" use-default-filters="false"><!-- base-package 如果多个,用“,”分隔 -->        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>    </context:component-scan>    <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">        <property name="viewClass"                  value="org.springframework.web.servlet.view.JstlView" />        <property name="prefix" value="/WEB-INF/" />        <property name="suffix" value=".jsp" />    </bean></beans>

spring-contexe-activemq.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:amq="http://activemq.apache.org/schema/core"       xmlns:jms="http://www.springframework.org/schema/jms"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:mvc="http://www.springframework.org/schema/mvc"       xsi:schemaLocation="        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd        http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context-4.1.xsd        http://www.springframework.org/schema/mvc        http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd        http://www.springframework.org/schema/jms        http://www.springframework.org/schema/jms/spring-jms-4.1.xsd        http://activemq.apache.org/schema/core        http://activemq.apache.org/schema/core/activemq-core-5.13.2.xsd       ">    <!-- ActiveMQ 连接工厂 -->    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->    <!-- 如果连接网络:tcp://ip:61616;未连接网络:tcp://localhost:61616 以及用户名,密码-->    <amq:connectionFactory id="amqConnectionFactory"                           brokerURL="tcp://127.0.0.1:61616" userName="admin" password="admin"  />    <!-- Spring Caching连接工厂 -->    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->    <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">        <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->        <property name="targetConnectionFactory" ref="amqConnectionFactory"></property>        <!-- 同上,同理 -->        <!-- <constructor-arg ref="amqConnectionFactory" /> -->        <!-- Session缓存数量 -->        <property name="sessionCacheSize" value="100" />    </bean>    <!-- Spring JMS Template -->    <!-- 消息生产者 -->    <!-- Queue类型 -->    <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">        <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->        <constructor-arg ref="connectionFactory"></constructor-arg>        <!-- 非pub/sub模型(发布/订阅),即队列模式 -->        <property name="pubSubDomain" value="false" />    </bean>    <!-- 定义JmsTemplate的Topic类型 -->    <bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">        <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->        <constructor-arg ref="connectionFactory" />        <!-- pub/sub模型(发布/订阅) -->        <property name="pubSubDomain" value="true" />    </bean>    <!--Spring JmsTemplate 的消息生产者 end -->    <!-- 消息监听器 -->    <!--队列-->    <bean id="QueueConsumer_1"          class="com.fendo.activemq.service.consumer.QueueConsumer_1"></bean>    <bean id="QueueConsumer_2"          class="com.fendo.activemq.service.consumer.QueueConsumer_2"></bean>    <!--主题-->    <bean id="TopicConsumer_1"          class="com.fendo.activemq.service.consumer.TopicConsumer_1"></bean>    <bean id="TopicConsumer_2"          class="com.fendo.activemq.service.consumer.TopicConsumer_2"></bean>    <!-- 消息消费者 start -->    <!-- 定义Queue监听器容器 -->    <jms:listener-container destination-type="queue"                            container-type="default" connection-factory="connectionFactory"                            acknowledge="auto">        <jms:listener destination="queue" ref="QueueConsumer_1" />        <jms:listener destination="queue" ref="QueueConsumer_2" />    </jms:listener-container>    <!-- 定义Topic监听器容器 -->    <jms:listener-container destination-type="topic"                            container-type="default" connection-factory="connectionFactory"                            acknowledge="auto">        <jms:listener destination="topic" ref="TopicConsumer_1" />        <jms:listener destination="topic" ref="TopicConsumer_2" />    </jms:listener-container>    <!-- 消息消费者 end -->    <!-- 定义队列目的地 ,点对点 -->    <bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">        <constructor-arg>            <value>queue</value>        </constructor-arg>    </bean>    <!-- 定义主题目的地 -->    <bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">        <constructor-arg>            <value>topic</value>        </constructor-arg>    </bean></beans>

log4j.properties

### direct log messages to stdout and logFile###log4j.rootCategory=INFO, stdout,logFile# OpenSymphony Stufflog4j.logger.com.opensymphony=INFOlog4j.logger.org.apache.commons=INFO # Spring Stufflog4j.logger.org.springframework=INFOlog4j.logger.org.springframework.oxm=INFOlog4j.appender.stdout=org.apache.log4j.ConsoleAppenderlog4j.appender.stdout.layout=org.apache.log4j.PatternLayoutlog4j.appender.stdout.layout.ConversionPattern=[\u65F6\u95F4\:%d{yyyy-MM-dd hh\:mm\:ss}] [\u7EA7\u522B\:%p] [\u7C7B\:%c]  [\u6D88\u606F\:%m] %n log4j.appender.logFile=org.apache.log4j.RollingFileAppenderlog4j.appender.logFile.File=D\:\\demo.loglog4j.appender.logFile.layout=org.apache.log4j.PatternLayoutlog4j.appender.logFile.layout.ConversionPattern=[\u65F6\u95F4\:%d{yyyy-MM-dd hh\:mm\:ss}] [\u7EA7\u522B\:%p] [\u7C7B\:%c]  [\u6D88\u606F\:%m] %n log4j.appender.logFile.MaxFileSize = 5MBlog4j.appender.logFile.MaxBackupIndex =3


四、添加生产者消费者


4.1、Queue队列通信


新建消息生产者:

package com.fendo.activemq.service.producer;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.Service;/** * @version V1.0 * @Author fendo * @ClassName ProducerService * @PackageName com.fendo.activemq.service * @Description 队列-消息生产者 Service * @Data 2017-09-21 10:47 **/@Servicepublic class QueueProducerService {    @Autowired    private JmsTemplate jmsQueueTemplate;    //发送消息    public void sendMessage(Destination destination,final String message) {        System.out.println("QueueProducerService发送消息:"+message);        jmsQueueTemplate.send(destination, new MessageCreator() {            @Override            public Message createMessage(Session session) throws JMSException {                return session.createTextMessage(message);            }        });    }}

然后创建多个消息消费者


消费者1:

package com.fendo.activemq.service.consumer;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;/** * @version V1.0 * @Author fendo * @ClassName QueueConsumer_1 * @PackageName com.fendo.activemq.listener * @Description 队列消费者1 * @Data 2017-09-21 10:47 **/public class QueueConsumer_1 implements MessageListener {    //当收到消息后,自动调用该方法    @Override    public void onMessage(Message message) {        TextMessage tm = (TextMessage) message;        try {            System.out.println("QueueConsumer_1接收到消息内容是:" + tm.getText());        } catch (JMSException e) {            e.printStackTrace();        }    }}


消费者2:
package com.fendo.activemq.service.consumer;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;/** * @version V1.0 * @Author fendo * @ClassName QueueConsumer_2 * @PackageName com.fendo.activemq.listener * @Description 队列消费者2 * @Data 2017-09-21 10:47 **/public class QueueConsumer_2 implements MessageListener {    //当收到消息后,自动调用该方法    @Override    public void onMessage(Message message) {        TextMessage tm = (TextMessage) message;        try {            System.out.println("QueueConsumer_2接收到消息内容是:" + tm.getText());        } catch (JMSException e) {            e.printStackTrace();        }    }}


4.2、Topic通信


创建Topic生产者:

package com.fendo.activemq.service.producer;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jms.core.JmsTemplate;import org.springframework.jms.core.MessageCreator;import org.springframework.stereotype.Service;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.Session;/** * @version V1.0 * @Author fendo * @ClassName TopicConsumerService * @PackageName com.fendo.activemq.service * @Description 主题-生产者 Service * @Data 2017-09-21 10:47 **/@Servicepublic class TopicProducerService {    @Autowired    private JmsTemplate jmsTopicTemplate;    //发送消息    public void sendMessage(Destination destination, final String message) {        System.out.println("向主题" + destination.toString() + "发送了消息------------" + message);        jmsTopicTemplate.send(destination, new MessageCreator() {            @Override            public Message createMessage(Session session) throws JMSException {                return session.createTextMessage(message);            }        });    }}

然后创建多个Topic消费者:

package com.fendo.activemq.service.consumer;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;/** * @version V1.0 * @Author fendo * @ClassName TopicConsumer_1 * @PackageName com.fendo.activemq.service * @Description 主题-消息消费者1 * @Data 2017-09-21 10:47 **/public class TopicConsumer_1 implements MessageListener {    @Override    public void onMessage(Message message) {        TextMessage textMessage = (TextMessage) message;        try {            System.out.println("TopicConsumer_1接收到消息内容是:" + textMessage.getText());        } catch (JMSException e) {            e.printStackTrace();        }    }}

package com.fendo.activemq.service.consumer;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;/** * @version V1.0 * @Author fendo * @ClassName TopicConsumer_2 * @PackageName com.fendo.activemq.service * @Description 主题-消息消费者2 * @Data 2017-09-21 10:47 **/public class TopicConsumer_2 implements MessageListener {    @Override    public void onMessage(Message message) {        TextMessage textMessage = (TextMessage) message;        try {            System.out.println("TopicConsumer_2接收到消息内容是:" + textMessage.getText());        } catch (JMSException e) {            e.printStackTrace();        }    }}


Controller类:

package com.fendo.activemq.controller;import com.fendo.activemq.service.producer.QueueProducerService;import com.fendo.activemq.service.producer.TopicProducerService;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.servlet.ModelAndView;import javax.annotation.Resource;import javax.jms.Destination;/** * @version V1.0 * @Author fendo * @ClassName ActivemqController * @PackageName com.fendo.activemq.controller * @Description Activemq Controller * @Data 2017-09-21 10:47 **/@Controllerpublic class ActivemqController {    private Logger logger = LoggerFactory.getLogger(ActivemqController.class);    @Autowired    private QueueProducerService queueProducerService;    @Autowired    private TopicProducerService topicProducerService;    @Resource    @Qualifier("queueDestination")    private Destination queueDestination;    @Resource    @Qualifier("topicDestination")    private Destination topicDestination;    @RequestMapping("")    public ModelAndView activemq(){        ModelAndView mv = new ModelAndView();        mv.setViewName("index");        return mv;    }    /**     * 去发消息页面     * @return     */    @RequestMapping(value="/producer",method= RequestMethod.GET)    public ModelAndView producer(){        ModelAndView mv = new ModelAndView();        mv.setViewName("producer");        return mv;    }    /**     * 发送消息     * @param message     * @return     */    @RequestMapping(value="/onsend",method=RequestMethod.POST)    public ModelAndView producer(@RequestParam("message") String message,@RequestParam("sendflag") String sendflag) {        System.out.println("------------send to jms------------");        ModelAndView mv = new ModelAndView();        //1 主题  2 队列        if("1".equals(sendflag)){            System.out.println("topic生产者产生消息:" + message);            topicProducerService.sendMessage(topicDestination, "topic生产者产生消息:" + message);        }else {            System.out.println("队列生产者产生消息:" + message);            queueProducerService.sendMessage(queueDestination, "队列生产者产生消息:"  + message);        }        mv.setViewName("index");        return mv;    }}


五、测试项目


然后创建消息生产者页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>生产者</title></head><body>    <h1>生产者</h1>    <h2>去队列发消息</h2>    <form action="${pageContext.request.contextPath}/onsend" method="post">        发送的内容:<textarea name="message" ></textarea>        <input type="text" style="display: none" name="sendflag" value="2" />        <input type="submit" value="提交" />    </form>    <h2>去主题发消息</h2>    <form action="${pageContext.request.contextPath}/onsend" method="post">        发送的内容:<textarea name="message" ></textarea>        <input type="text" style="display: none" name="sendflag" value="1" />        <input type="submit" value="提交" />    </form>    <h2><a href="${pageContext.request.contextPath}/">返回主页</a></h2></body></html>

效果如下:




可以分别发送队列和主题,发送的效果如下:





从接收的消息可以看出出队列模型和Topic模型的区别,Queue只能由一个消费者接收,其他Queue中的成员无法接受到被已消费的信息,而Topic则可以,只要是订阅了Topic的消费者,全部可以获取到生产者发布的信息。


完整项目如下:http://download.csdn.net/download/u011781521/10151680

阅读全文
0 0
原创粉丝点击