消息队列 activeMQ+spring(测试dome)

消息队列 activeMQ+spring(测试dome)

使用maven创建项目

    mvn archetype:generate

背景

    base-db--->kettle--->warehouse-db(X),warehouse-db<--(mq)<--server-->base-db;

方案

使用消息队列技术将数据同步到仓库中,并在指定时间进行数据修复,达到数据的实时查询.技术难点是消息队列的实现.

实现

环境
    jdk1.8+activemq(docker)+spring+maven
环境搭建
    idea(社区版)搭建spring+maven环境
pom.xml(非完整)
     <properties>
        <sb.version>5.1.5.RELEASE</sb.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13-beta-3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${sb.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${sb.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jms</artifactId>
            <version>${sb.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${sb.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${sb.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-core</artifactId>
            <version>5.5.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-pool</artifactId>
            <version>5.7.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.xbean/xbean-spring -->
        <dependency>
            <groupId>org.apache.xbean</groupId>
            <artifactId>xbean-spring</artifactId>
            <version>4.14</version>
        </dependency>
    </dependencies>

创建一个消息实体类

消息需要进行序列化操作
	package com.mq.core.now;

	import java.io.Serializable;

	public class Spittle implements Serializable{


    private String name;

    private String age;

    public Spittle(String name, String age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "name:"+name+",age:"+age;
    }
}

创建接口

只提供简单的发送消息以及接收消息,本文实现的是点对点消息队列操作,对于主题订阅广播读者自行尝试
   package com.mq.core.now;

public interface AlertService {
   /**
    *
    * @param spittle
    */
   void sendSpittleAlert(Spittle spittle,String spittleName);

   void sendSpittleAlert(Spittle spittle);

   public Spittle receiveSpittleAlert();

   public Spittle receiveSpittleAlert(String spittleName);

}

接口实现类

   package com.mq.core.now;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsOperations;
import org.springframework.jms.support.JmsUtils;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.Session;


public class AlertServiceImpl implements AlertService {

   /**
    * 注入jms模板
    * @param jmsOperations
    */
   @Autowired
   private JmsOperations jmsOperations;



   /**
    * 发送消息
    * @param spittle
    */
   @Override
   public void sendSpittleAlert(final Spittle spittle) {
       /**
        * 地址,创建消息
        */
       jmsOperations.send((Session session) -> {
           return session.createObjectMessage(spittle);
       });
   }

   /**
    * 发送消息(以指定的消息名称)
    * @param spittle
    */
   @Override
   public void sendSpittleAlert(final Spittle spittle,String spittleName) {
       /**
        * 地址,创建消息
        */
       jmsOperations.send(spittleName,(Session session) -> session.createObjectMessage(spittle));
   }

   /**
    * 接收消息(同步的,需要等待消息的到来)
    * @return
    */
   @Override
   public Spittle receiveSpittleAlert() {
       try {
           ObjectMessage receiveMessage = (ObjectMessage) jmsOperations.receive();
           return (Spittle) receiveMessage.getObject();
       } catch (JMSException e) {
           //抛出异常
          throw JmsUtils.convertJmsAccessException(e);
       }
   }

   /**
   * 获取指定队列名称的消息
   */
   @Override
   public Spittle receiveSpittleAlert(String spittleName) {
       try {
           ObjectMessage receiveMessage = (ObjectMessage) jmsOperations.receive(spittleName);
           return (Spittle) receiveMessage.getObject();
       } catch (JMSException e) {
           //抛出异常
           throw JmsUtils.convertJmsAccessException(e);
       }
   }
}

spring-config.xml

<?xml version="1.0" encoding="utf-8" ?>
<!-- xmlns:c="http://www.springframework.org/schema/c"
      xmlns:p="http://www.springframework.org/schema/p"-->
<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:jms="http://www.springframework.org/schema/jms"
      xmlns:c="http://www.springframework.org/schema/c"
      xmlns:p="http://www.springframework.org/schema/p"
      xmlns:amq="http://activemq.apache.org/schema/core"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://activemq.apache.org/schema/core
      http://activemq.apache.org/schema/core/activemq-core.xsd
      http://www.springframework.org/schema/jms
      http://www.springframework.org/schema/jms/spring-jms.xsd">
   <!--    <bean id="connectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory"-->
   <!--    p:brokerURL="tcp://localhost:61616"/>-->
   
   <amq:connectionFactory id="connectionFactory" brokerURL="tcp://localhost:61626"/>

   <bean id="alterService" class="com.mq.core.now.AlertServiceImpl"/>
   
   <bean id="spittleHandler" class="com.mq.core.now.SpittleAlertHandler"/>
   <!-- 消息监听器 -->
   <jms:listener-container connection-factory="connectionFactory" >
       <jms:listener destination="spittle.alter.queue" ref="spittleHandler" method="handlerSpittleAlter"/>
   </jms:listener-container>
   
   
   <bean id="messageConverter"  class="org.springframework.jms.support.converter.MappingJackson2MessageConverter"/>

   <bean id="jmsTemplate"  class="org.springframework.jms.core.JmsTemplate"
         c:_-ref="connectionFactory"
         p:defaultDestinationName="spittle.alter.queue"
         p:messageConverter-ref="messageConverter"/>
</beans>

测试

	package com.mq;

import com.mq.core.now.AlertService;
import com.mq.core.now.Spittle;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring-config.xml"})
public class TestActiveMQ {
   @Autowired
   private AlertService alertService;

   @Test
   public void test01(){
       for (int i = 0; i < 3 ; i++) {
           System.out.printf("----发送消息----");
           Spittle xuzz = new Spittle("xuzz", "23"+i);
           alertService.sendSpittleAlert(xuzz);
           System.out.println("消息发送结束");

       }
   }

   @Test
   public void testPOP(){
       System.out.printf("----接收消息消息----");
       Spittle spittle = alertService.receiveSpittleAlert();
       System.err.println(spittle.toString());
   }

   @Test
   public void testPOP1(){
       while(true){
           System.err.println(alertService.receiveSpittleAlert("yb-push").toString());
           new Thread(()-> {
               try {
                   Thread.sleep(1000L);
                   System.out.println("------------"+Thread.currentThread().getId());
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }).start();
       }

   }
   @Test
   public void testPOP2(){
               while(true){
                   System.err.println(alertService.receiveSpittleAlert("yb-push").toString());
                   new Thread(()-> {
                       try {
                           Thread.sleep(1000L);
                           System.out.println("------------"+Thread.currentThread().getId());
                       } catch (InterruptedException e) {
                           e.printStackTrace();
                       }
                   }).start();
               }
   }
}

在接收信息时候,消费者可能需要等到消息到来之后才能完成动作,否则需要一直等待消息的到来.一直占用资源,此时可以使用消息监听器来实现消息的异步接收.

	package com.mq.core.now;


import org.springframework.beans.factory.annotation.Autowired;

/**
* spring MDP 异步接收消息和处理消息
*/
public class SpittleAlertHandler {

   @Autowired
   private AlertService alertService;

   /**
    * 异步处理数据处理消息
    * @param spittle
    */
   public void handlerSpittleAlter(Spittle spittle){
         //...这里可以编写自定义的代码
       //重新发送给我们想要的消费者,
       alertService.sendSpittleAlert(spittle,"yb-push");
   }
}

文章写的比较简单,很多地方没有讲到.后续的文章或者本文章会继续完善

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值