JMS学习之路(一):整合activeMQ到SpringMVC

JMS的全称是Java Message Service,即Java消息服务。它主要用于在生产者和消费者之间进行消息传递,生产者负责产生消息,而消费者负责接收消息。把它应用到实际的业务需求中的话我们可以在特定的时候利用生产者生成一消息,并进行发送,对应的消费者在接收到对应的消息后去完成对应的业务逻辑。对于消息的传递有两种类型,一种是点对点的,即一个生产者和一个消费者一一对应;另一种是发布/订阅模式,即一个生产者产生消息并进行发送后,可以由多个消费者进行接收。

整合activeMQ到springmvc项目也很简单

只需要增加如下的maven依赖即可,初学者请直接添加all这个jar,否则如果jar包冲突会影响信心的

<dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
            <version>5.13.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>${spring.version}</version>
        </dependency>

开发步骤:

① 添加好maven依赖后,请到 http://activemq.apache.org/ 下载最新版的activeMQ, 我这里下载的是5.13.2,下载解压后执行bin中的activemq.bat进行启动

② 理解JMS工作原理

  1.首先配置链接信息

和操作数据库一样,我们要根据数据库地址和链接信息,来配置datasource一样,activemq类同,底层首先需要由activemq厂商提供的驱动,根据具体地址,封装一个ConnectionFactory, 这是最基本的配置, 同时由于是由Spring进行统一管理, 所以需要将ConnectionFactory注入到sping。jms中的ConnectionFactory。这样链接就配置好了。

<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
    <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" value="tcp://localhost:61616" />
    </bean>

    <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
    <bean id="connectionFactory"
        class="org.springframework.jms.connection.SingleConnectionFactory">
        <!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
        <property name="targetConnectionFactory" ref="targetConnectionFactory" />
    </bean>

同理 spring.jms 提供了 SingleConnectionFactory和CachingConnectionFactory,这里我们使用的SingleConnectionFactory,根据意思也知道得八九不离十了,

SingleConnectionFactory就是每次请求都返回同一个链接,从启动开始就一直打开,不会关闭。 而CachingConnectionFactory就和数据库的链接池一样,可以缓存很多信息,在用户很多的情况下,同等情况下会增加效率。

同时activeMQ也提供了PooledConnectionFactory,这样也可以缓存很多信息,减少资源的使用,配置如下

<!-- 使用pool进行链接 -->
    <!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<!--     <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> -->
<!--         <property name="brokerURL" value="tcp://localhost:61616"/> -->
<!--     </bean> -->

<!--     <bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"> -->
<!--         <property name="connectionFactory" ref="targetConnectionFactory"/> -->
<!--         <property name="maxConnections" value="10"/> -->
<!--     </bean> -->

<!--     <bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"> -->
<!--         <property name="targetConnectionFactory" ref="pooledConnectionFactory"/> -->
<!--     </bean> -->

2。配置好ConnectionFactory之后我们就需要配置生产者。生产者负责产生消息并发送到JMS服务器,这通常对应的是我们的一个业务逻辑服务实现类。但是我们的服务实现类是怎么进行消息的发送的呢?这通常是利用Spring为我们提供的JmsTemplate类来实现的,所以配置生产者其实最核心的就是配置进行消息发送的JmsTemplate。对于消息发送者而言,它在发送消息的时候要知道自己该往哪里发,为此,我们在定义JmsTemplate的时候需要往里面注入一个Spring提供的ConnectionFactory对象。

<!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
        <property name="connectionFactory" ref="connectionFactory" />
    </bean>

在发送消息的时候,除了知道activemq的地址外,还需要让发送者知道具体发给谁?

activemq提供了两种模式,一个是点对点的 ,一个是发送给多个订阅者这种订阅模式

    <!--这个是队列目的地 -->
    <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"/>
    </bean>

这样发送者相关配置就已经完成了。

③ 发送者发送消息的服务类: 很简单,调用上面配置好的jmsTemplate。send方法就好了

package xiaochangwei.zicp.net.jms;

import javax.annotation.Resource;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;

@Service
public class ProducerServiceImpl implements ProducerService {

    @Resource
    private JmsTemplate jmsTemplate;

    public void sendMessage(Destination destination, final String message) {
        jmsTemplate.send(destination, new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                return session.createTextMessage(message);
            }
        });
    }
}

至此发送者相关的都已经全部完成了,下面配置接受者

④  接收者配置,接收者和发送者的链接信息都是一样的,不然收不到信息是不, 除了链接信息,要知道什么时候有消息发送过来,接收者这边就要实现一个消息监听器,

当监听到消息后,进行相应的业务处理,每个目的地都有一个MessageListenerContainer,配置MessageListenerContainer需要链接信息,目的地信息,和接受者的消息监听器

<!-- 消息监听器 -->
    <bean id="consumerMessageListener"
        class="xiaochangwei.zicp.net.jms.ConsumerMessageListener" />
    <!-- 消息监听容器 -->
    <bean id="jmsContainer"
        class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="connectionFactory" />
        <property name="destination" ref="queueDestination" />
        <property name="messageListener" ref="consumerMessageListener" />
    </bean>

这里我们进行一个业务模拟

A系统通过activemq发送命令串给B系统, B系统收到命令后,根据约定的规则进行解析,并进行业务处理

A系统调用ProducerServiceImpl中的 sendMessage 进行消息发送,为减少传递量,均采用json发送,代码如下:

package xiaochangwei.zicp.net.web.controller;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.jms.Destination;

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.ResponseBody;

import xiaochangwei.zicp.net.common.tools.JsonUtil;
import xiaochangwei.zicp.net.entity.TestEntity;
import xiaochangwei.zicp.net.jms.ProducerService;

@Controller
@RequestMapping("jms")
public class JmsTestController {

    @Autowired
    private ProducerService producerService;
    @Autowired
    @Qualifier("queueDestination")
    private Destination destination;

    @RequestMapping("test")
    public @ResponseBody String testSend() throws Exception {

        //系统业务需要, 需要更新用户表中信息,根据id更新name
        List<TestEntity> list = new LinkedList<TestEntity>();

        TestEntity en = new TestEntity();
        en.setId(100);
        en.setName("name1");
        list.add(en);

        TestEntity en2 = new TestEntity();
        en2.setId(1002);
        en2.setName("name2");
        list.add(en2);

        Map<String,Object> mapEntity = new HashMap<String, Object>();
        mapEntity.put("user", list);

        Map<String,Object> map = new HashMap<String, Object>();
        map.put("update", mapEntity);

        System.out.println("发送方发送内容为:" + JsonUtil.object2String(map));
        //发送更新数据请求
        producerService.sendMessage(destination, JsonUtil.object2String(map));

        return "jms exute complete";
    }
}

接收者根据约定,知道收到的消息都是json字符串,所以直接按text处理

package xiaochangwei.zicp.net.jms;

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

public class ConsumerMessageListener implements MessageListener {

    public void onMessage(Message message) {
        TextMessage textMsg = (TextMessage) message;
        try {
            System.out.println("接收者受到消息:" + textMsg.getText());
            System.out.println("开始进行解析并调用service执行....");

        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

}

这里没有具体的去解析并执行具体操作,只是打印出来而已,只确认发送方发送的内容和接受方接收到的内容一致即可。

可以看到发送方和接收方内容一直

解释下这段json想表达的意思: 更新(update)用户信息(user),把id=100的用户 name更新为name1 ........

整合就讲到这里,后续会讲到消息监听器,转换器等进阶知识,感兴趣的朋友可以持续关注

时间: 2024-10-11 20:03:42

JMS学习之路(一):整合activeMQ到SpringMVC的相关文章

webService学习之路(三):springMVC集成CXF后调用已知的wsdl接口

webService学习之路一:讲解了通过传统方式怎么发布及调用webservice webService学习之路二:讲解了SpringMVC和CXF的集成及快速发布webservice 本篇文章将讲解SpringMVC+CXF环境下,怎么调用其他系统通过webService方式暴露出来的接口 ① 为避免怀疑同一个项目中调用本项目的接口,这里我新打开一个eclipse通过最原始的方式发布了一个webservice并启动保证可以被访问 打开浏览器确认可以被访问 ②进入CXF/bin 利用wsdl2

activeMQ入门+spring boot整合activeMQ

最近想要学习MOM(消息中间件:Message Oriented Middleware),就从比较基础的activeMQ学起,rabbitMQ.zeroMQ.rocketMQ.Kafka等后续再去学习. 上面说activeMQ是一种消息中间件,可是为什么要使用activeMQ? 在没有使用JMS的时候,很多应用会出现同步通信(客户端发起请求后需要等待服务端返回结果才能继续执行).客户端服务端耦合.单一点对点(P2P)通信的问题,JMS可以通过面向消息中间件的方式很好的解决了上面的问题. JMS规

LUA学习之路--初识LUA

LUA在葡萄牙语中是“月亮”的意思.1993年由巴西的Ponifical Catholic University开发.该语言是由一个来自计算机图形技术组织的团队开发,并作为自由软件发行.LUA开发小组的目标是开发一种小巧.高效并且能够很好的和C语言一起工作的编程语言.在脚本语言领域,LUA是最快.最高效的脚本语言之一. LUA和传统的脚本语言不同,它是一种易整合语言(glue language).一般的脚本语言用于控制执行重复的任务,而易整合语言可以让使用者把其他语言的功能整合在一起.这样就让脚

运维学习之路

网络:      路由               :静态路由,ospf,bgp 交换               :acs(802.1X) vlan间路由 VRRP 安全               :安全策略 QoS VPN(三种) 数据中心 系统工程师:系统基本维护 办公系统搭建维护    :邮箱 共享文件 SVN 中间件搭建维护      :WebLogic tomcat 监控系统搭建维护    :nagios cacti 负载均衡软件搭建维护:haproxy nginx lvs 网站搭

linux学习之路之目录结构

FHS的产生 我们知道目前linux的发行版本很多,如果每一个发行版本,它的目录层次结构都不相同的话,那么当管理员去管理其他的linux主机时,就会不知多措了.而且在开发过程中,如果每一个程序员都按照自己的想法去存放的数据的话,那么其他的程序员想去查找别人的数据文件时,这是问题就来了,因为文件系统中存放了那么多的数据,谁知道你把数据存放在哪儿了?因此,需要一个标准来规范,这样每个人都按照这种规范去存放.查找数据等操作,这样,当其他人如果需要去查找的话,就会简单多了. FHS:全称为文件系统目录标

Spring整合ActiveMQ

1.管理ActiveMQ 地址  http://localhost:8161/admin/ 默认用户和密码:admin=admin 运行发送者,eclipse控制台输出,如下图: 此时,我们先看一下ActiveMQ服务器,Queues内容如下: 我们可以看到创建了一个名称为HelloWorld的消息队列,队列中有10条消息未被消费,我们也可以通过Browse查看是哪些消息,如下图: 如果这些队列中的消息,被删除,消费者则无法消费. 我们继续运行一下消费者,eclipse控制台打印消息,如下: 

IOS 学习之路一 正其心

进入IT行业已经有5个年头,前3年做中间件(WAS) 数据库(ORACLE)的维护,后打算深入学习数据库,做DBA,于是跳槽到一家数据公司.没做多久的数据库,公司就安排做基于 WEB 的监控,独立开发了3个监控系统,发现这是个焦油坑--正如<人月神话>所说,萌生去意.现在回想起来,了解的技术 和用过的平台虽多,但都不精,无核心竞争力.鉴于互联网发展趋势,要么去做大数据,要么到移动互联网.大数据偏学术,而移动物联网更注重 互联网的核心--连接,于是重新上路. 技术爆破 每次技术爆破都小人物的机会

ssm整合ActiveMQ

环境:windows7 本次使用spring+springmvc+mybatis整合activemq 整合结果,项目能正常运行.并且使用postman进行接口测试,没有进行数据的持久化到数据库. 以下是整合内容 =============================================================================== 1,pom.xml文件下载activemq的jar包配置,仅贴出activemq的配置 <!--activemq  --> 

Spring整合ActiveMQ及多个Queue消息监听的配置

消息队列(MQ)越来越火,在java开发的项目也属于比较常见的技术,MQ的相关使用也成java开发人员必备的技能.笔者公司采用的MQ是ActiveMQ,且消息都是用的点对点的模式.本文记录了实现Spring整合ActivateMQ的全过程及如何使用MQ,便于后续查阅. 一.项目的搭建 采用maven构建项目,免去了copy jar包的麻烦.因此,我们创建了一个java类型的Maven Project (1)项目结构图 先把项目结构图看一下,便于对项目的理解. (2)pom.xml 我们需要加入以