ActiveMQ(artemis版) 基本安装与Spring JMS基本使用

引言

使用artemis版本MQ。Spring JMS 使用springframework-mvc架构,传统xml配置,部署到tomcat运行。如果采用springboot将更简单。有空将更新成springboot

ActiveMQ基本安装与使用

注: ActiveMQ下载的artemis版本,与之前的ActiveMQ版本有点区别,

下载ActiveMQ

下载地址 https://activemq.apache.org/index.html

在这里插入图片描述在这里插入图片描述## 安装ActiveMQ

  1. apache-artemis-2.11.0.bin.tar.gz解压该文件
  2. 进入cd apache-artemis-2.11.0/bin目录
  3. 运行一下脚本,创建一个实例,自动在software目录下生成一个myInstance目录,
./artemis create /Users/somnus/Documents/software/myInstance
# ./artemis create /Users/somnus/Documents/software/myInstance

在这里插入图片描述

  1. 运行activemq
cd ./artemis create /Users/somnus/Documents/software/myInstance/bin
./artemis run  #运行activemq

在这里插入图片描述5.通过浏览器访问activemq控制台
地址 http://localhost:8161/
在这里插入图片描述6. 进入控制台Management Console
路径:http://localhost:8161/console/login,记不住,直接http://localhost:8161通过点击进入

dfsdfds
在这里插入图片描述

Spring JMS项目

项目POM配置

 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>
        <!-- 用于消息转换 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        <!-- jms客户端-->
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>artemis-jms-client</artifactId>
            <version>2.11.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jms -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>5.2.4.RELEASE</version>
        </dependency>

    </dependencies>

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
<!--    <listener>-->
<!--        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>-->
<!--    </listener>-->
    <!-- 默认加载 /WEB-INF/applicationContext.xml-->
<!--    <context-param>-->
<!--        <param-name>contextConfigLocation</param-name>-->
<!--        <param-value>/WEB-INF/applicationContext.xml</param-value>-->
<!--    </context-param>-->
    <servlet>
        <servlet-name>app</servlet-name>
        <!-- 默认加载 namespace-servlet.xml配置文件 
        这里是app-servlet.xml -->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

springmvc配置

配置文件名:app-servlet.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/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
        <mvc:component-scan base-package="com.teachayu.activemq" />

        <!-- 链接工厂 -->
        <bean id="connectionFactory" class="org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory" />

        <!-- 缓存JMS工厂 -->
        <bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
                <property name="targetConnectionFactory" ref="connectionFactory"/>
        </bean>

        <!-- jms消息转换器 JmsTemplate发送与接收 -->
        <bean id="messageConverter" class="org.springframework.jms.support.converter.MappingJackson2MessageConverter" >
                <property name="typeIdPropertyName" value="test" />
                <property name="typeIdMappings" >
                        <map>
                                <entry key="test" value="com.teachayu.activemq.controller.UserEntity"/>
                        </map>
                </property>
        </bean>
        <!--点对点 文本消息发送模板 -->
        <bean id="pointJmsTemplate" class="org.springframework.jms.core.JmsTemplate" >
                <constructor-arg ref="connectionFactory"></constructor-arg>
                <!-- 定义默认队列-->
                <property name="defaultDestinationName" value="test"/>
                <property name="messageConverter"  ref="messageConverter"/>
                <!--pubSubDomain true: Publish/Subscribe  false: Point-to-Point-->
                <!-- 默认 Point-to-Point  -->
                <property name="pubSubDomain" value="false" />
        </bean>
        <!-- 文本消息监听器 接收文本消息 -->
        <bean id="receiveListener" class="com.teachayu.activemq.controller.TextReceiveListener"></bean>
        <!--接收文本消息 -->
        <bean id="defaultMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
                <property name="messageListener" ref="receiveListener"/>
                <property name="messageConverter" ref="messageConverter"/>
                <property name="destinationName" value="test"/>
                <property name="connectionFactory" ref="connectionFactory"/>
        </bean>

        <!-- 对象消息转换器 -->
        <bean id="pojoMessageConverter" class="com.teachayu.activemq.controller.PojoMessageConverter"/>
        <!--点对点 发送消息 使用另一个转换器,基于对象-->
        <bean id="pojoJmsTemplate" class="org.springframework.jms.core.JmsTemplate" >
                <constructor-arg ref="connectionFactory"></constructor-arg>
                <!-- 定义默认队列-->
                <property name="defaultDestinationName" value="test"/>
                <property name="messageConverter"  ref="pojoMessageConverter"/>
                <!--pubSubDomain true: Publish/Subscribe  false: Point-to-Point-->
                <!-- 默认 Point-to-Point  -->
                <property name="pubSubDomain" value="false" />
        </bean>
        <!-- 对象消息监听器 -->
        <bean class="com.teachayu.activemq.controller.Pojo1ReceiveListener" id="pojo1ReceiveListener"/>
        <!-- 接收对象消息 -->
        <!--把消息监听器注册到 -->
        <!-- SimpleMessageListenerContainer -->
        <bean class="org.springframework.jms.listener.SimpleMessageListenerContainer" >
                <property name="connectionFactory" ref="connectionFactory"/>
                <property name="destinationName" value="pojo1"/>
                <property name="messageConverter" ref="pojoMessageConverter"/>
                <property name="messageListener" ref="pojo1ReceiveListener"/>
        </bean>

        <!--发布与订阅 -->
        <bean id="pubJmsTemplate" class="org.springframework.jms.core.JmsTemplate" >
                <property name="connectionFactory" ref="cachingConnectionFactory"/>
                <!-- 定义默认队列-->
                <property name="defaultDestinationName" value="pub"/>
                <property name="messageConverter"  ref="pojoMessageConverter"/>
                <!--pubSubDomain true: Publish/Subscribe  false: Point-to-Point-->
                <!-- 默认 Point-to-Point  -->
                <property name="pubSubDomain" value="true" />
        </bean>
        <!-- 订阅消息 Subscribe1Listener -->
        <bean class="com.teachayu.activemq.controller.Subscribe1Listener" id="subscribe1Listener"/>
        <!-- 订阅消息 Subcribe2Listener -->
        <bean class="com.teachayu.activemq.controller.Subscribe2Listener" id="subscribe2Listener"/>
        <bean id="listenerContainer1" class="org.springframework.jms.listener.SimpleMessageListenerContainer">
                <!-- pubSubDomain true:发布订阅模式 -->
                <property name="pubSubDomain" value="true"/>
                <property name="destinationName" value="pub"/>
                <property name="messageListener" ref="subscribe1Listener"/>
                <property name="messageConverter" ref="pojoMessageConverter"/>
                <property name="connectionFactory" ref="cachingConnectionFactory"/>
        </bean>
        <bean id="listenerContainer2" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
                <!-- pubSubDomain true:发布订阅模式 -->
                <property name="pubSubDomain" value="true"/>
                <property name="messageListener" ref="subscribe2Listener"/>
                <property name="messageConverter" ref="pojoMessageConverter"/>
                <property name="destinationName" value="pub"/>
                <property name="connectionFactory" ref="cachingConnectionFactory"/>
        </bean>
        
        <!--http请求转json -->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
                <property name="messageConverters">
                        <list>
                                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                                        <property name="supportedMediaTypes">
                                                <list><value>text/html;charset=UTF-8</value>
                                                      <value>application/json;charset=UTF-8</value>
                                                </list>
                                        </property>
                                </bean>
                        </list>
                </property>
        </bean>

</beans>

消息转换器 与实体类

定义PojoMessageConverter消息转换器,将Object转成ObjectMessage消息,或将ObjectMessage消息转成Object。Object将实现Serializable接口

package com.teachayu.activemq.controller;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import java.io.Serializable;
public class PojoMessageConverter implements MessageConverter {
    @Override
    public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
        return session.createObjectMessage((Serializable) object);

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

实体类,用于测试

package com.teachayu.activemq.controller;
import java.io.Serializable;
public class UserEntity implements Serializable {
    private String name;
    private int age;
    private String address;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "UserEntity{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                '}';
    }
}

生产者

发送消息与发布消息,通过http://localhost:8080/activemq/send 完成简单消息推送

package com.teachayu.activemq.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;

/**
 * 使用Point-to-Point模式发送消息
 * 使用Publish/Subscribe 模式发布消息
 */
@RestController
public class ProducerController {
    /**
     * 发送文本消息模板 Point-to-Point
     * MappingJackson2MessageConverter转换器
     */
    private JmsTemplate jmsTemplate;

    /**
     * 发送对象消息 Point-to-Point
     * PojoMessageConverterz转换器
     */
    private JmsTemplate pojoJmsTemplate;

    /**
     * 发布对象消息  Publish/Subscribe
     * PojoMessageConverterz转换器
     */
    private JmsTemplate pubJmsTemplate;
    @RequestMapping("/send")
    public String send(){
        /**
         *  Point-to-Point 模式
         *  使用默认队列发送消息
         *  使用JmsTemplate同步接收
         */

        jmsTemplate.send(new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                //发送TextMessage消息
                return  session.createTextMessage("text队列发送消息(接收同步):"+System.currentTimeMillis());
            }
        });
        /**
         * Point-to-Point 模式
         * 使用默认队列发送消息
         * 异步接收 MessageListener
         */
        jmsTemplate.send("text1", new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                //发送TextMessage消息
                return  session.createTextMessage("text1队列发送消息(接收异步)"+System.currentTimeMillis());
            }
        });

        /**
         * Point-to-Point  模式
         * 使用定义的转换器
         *  org.springframework.jms.support.converter.MappingJackson2MessageConverter
         *  使用pojo队列发送消息
         *  使用JmsTemplate同步接收
         */
        UserEntity userEntity = new UserEntity();
        long l = System.currentTimeMillis();
        userEntity.setName("张三"+l);
        userEntity.setAddress("地址"+l);
        userEntity.setAge(1);
        jmsTemplate.convertAndSend("pojo",userEntity);

        /**
         * Point-to-Point 模式
         * 使用定义的转换器 com.teachayu.activemq.controller.PojoMessageConverter
         * 使用pojo队列发送消息
         * 异步接收 MessageListener
         */
        userEntity = new UserEntity();
        l = System.currentTimeMillis();
        userEntity.setName("张三"+l);
        userEntity.setAddress("地址"+l);
        userEntity.setAge(1);
        pojoJmsTemplate.convertAndSend("pojo1",userEntity);

        /**
         * Publish/Subscribe 模式
         * 发布消息
         * 默认队列 pub  ,配置文件中
         */
        userEntity = new UserEntity();
        l = System.currentTimeMillis();
        userEntity.setName("张三"+l);
        userEntity.setAddress("地址"+l);
        userEntity.setAge(1);
        pubJmsTemplate.convertAndSend("pub",userEntity);

        return "hello";
    }

    @Autowired
    @Qualifier("pointJmsTemplate")
    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    @Autowired
    @Qualifier("pojoJmsTemplate")
    public void setPojoJmsTemplate(JmsTemplate pojoJmsTemplate) {
        this.pojoJmsTemplate = pojoJmsTemplate;
    }

    @Autowired
    @Qualifier("pubJmsTemplate")
    public void setPubJmsTemplate(JmsTemplate pubJmsTemplate) {
        this.pubJmsTemplate = pubJmsTemplate;
    }
}


同步消费者

同步接收消息,是阻塞模式,通过http://localhost:8080/activemq/receive接收消息。
注意:一定要先执行send请求,完成消费发送,不是receive请求将阻塞

package com.teachayu.activemq.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.jms.JMSException;
import javax.jms.TextMessage;

/**
 * 阻塞模式接收消息
 */
@RestController
public class CustomerController {

    private JmsTemplate jmsTemplate;
    @RequestMapping("receive")
    public UserEntity receive() throws JMSException {
        //阻塞接收消息,默认队列,队列中无消息将阻塞
        TextMessage message = (TextMessage)jmsTemplate.receive();
        System.out.println("接收test队列:"+message.getText());
        //阻塞接收消息,pojo队列,队列中无消息将阻塞
        UserEntity userEntity = (UserEntity)jmsTemplate.receiveAndConvert("pojo");
        System.out.println("接收pojo队列消息"+ userEntity);
        return userEntity;

    }
    @Autowired
    @Qualifier("pointJmsTemplate")
    public void setJmsTemplate(JmsTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }
}

异步接收消息,监听模式

采用监听模式接收消息,有消息来将自动获取消息

文本消息接收

package com.teachayu.activemq.controller;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
/**
 * 监听接收消息
 */
public class TextReceiveListener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
            String text = ((TextMessage) message).getText();
            System.out.println("接收到test队列消息:"+text);
        } catch (JMSException e) {
            e.printStackTrace();
        }

    }
}

对象消息接收

package com.teachayu.activemq.controller;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
/**
 * 队列监听器 pojo1队列
 * PojoMessageConverter完成转换
 */
public class Pojo1ReceiveListener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
            UserEntity userEntity = (UserEntity)  ((ObjectMessage) message).getObject();
            System.out.println("接收pojo1队列消息:"+ message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

订阅消息 监听模式

Subscribe1Listener 订阅pub主题消息

package com.teachayu.activemq.controller;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
/**
 * 订阅消息
 */
public class Subscribe1Listener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        UserEntity userEntity = null;
        try {
            userEntity = (UserEntity) ((ObjectMessage) message).getObject();
        } catch (JMSException e) {
            e.printStackTrace();
        }
        System.out.println("Subscribe1Listener订阅pub队列消息:" + userEntity);
    }
}

Subscribe2Listener 订阅pub主题消息

package com.teachayu.activemq.controller;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
/**
 * 订阅消息
 */
public class Subscribe2Listener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        UserEntity userEntity = null;
        try {
            userEntity = (UserEntity) ((ObjectMessage) message).getObject();
        } catch (JMSException e) {
            e.printStackTrace();
        }
        System.out.println("Subscribe2Listener订阅pub队列消息:" + userEntity);
    }
}

测试

前提是运行activemq与springJMS项目,将可以进行以下测试。测试就不截图了。

发送消息

通过浏览器访问 http://localhost:8080/activemq/send 将完成所有消息发送。

接收消息

  1. 采用MessageListener方式在控制台自动打印接收到消息
  2. 通过访问http://localhost:8080/activemq/receive接收text与pojo队列消息

参考资料

https://docs.spring.io/spring/docs/5.2.5.RELEASE/spring-framework-reference/integration.html#remoting-jms

http://localhost:8161/user-manual/index.html #该地址是安装activemq之后访问可以看到。
或者通过以下官网地址查看文档
https://activemq.apache.org/components/artemis/documentation/

JMS工厂(JMS Connection Factory)是JMS规范中的概念,它是用来创建JMS Connection(即JMS连接)的工厂类。在使用JMS时,我们需要先创建一个JMS连接,然后使用这个连接来创建JMS会话(JMS Session),最后使用JMS会话来发送和接收JMS消息。 针对不同的JMS消息中间件,我们需要使用不同的JMS Connection Factory。在使用ActiveMQ时,我们可以使用ActiveMQ提供的ActiveMQConnectionFactory来创建JMS连接。 而在Spring JMS框架中,我们可以使用Spring提供的ConnectionFactory来创建JMS Connection Factory。Spring提供了多个ConnectionFactory的实现类,例如: - ActiveMQConnectionFactory:用于创建ActiveMQJMS Connection Factory。 - CachingConnectionFactory:用于创建基于缓存的JMS Connection Factory。 - SingleConnectionFactory:用于创建单例的JMS Connection Factory。 在Spring Boot中,我们可以通过配置文件来配置JMS Connection Factory,例如: ``` spring.activemq.broker-url=tcp://localhost:61616 spring.jms.pub-sub-domain=false spring.jms.template.default-destination=example.queue ``` 在上面的配置中,我们指定了ActiveMQ的地址和端口号,以及默认的JMS目的地(即消息队列或主题)。 总之,JMS Connection Factory是JMS规范中的概念,用于创建JMS连接。在使用ActiveMQ时,我们可以使用ActiveMQ提供的ActiveMQConnectionFactory来创建JMS Connection Factory。在Spring JMS框架中,我们可以使用Spring提供的ConnectionFactory来创建JMS Connection Factory,也可以使用其他第三方提供的JMS Connection Factory。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值