springboot與ActiveMQ整合

前言

   不少項目, 都不是一個系統就作完了. 而是好多個系統, 相互協做來完成功能. 那, 系統與系統之間, 不可能徹底獨立吧?html

  如: 在學校所用的管理系統中, 有學生系統, 資產系統, 宿舍系統等等. 當學期結束以後, 是否須要對已經結束的期次進行歸檔操做. 假如歸檔功能在學生系統中, 那點擊歸檔以後, 學生是否是還要關心宿舍那邊是否已結束, 學生所領資產是否全都歸還? spring

  顯然, 這並非一個好的方式, 系統之間的耦合性作的太強了, 很不利於系統擴展, 並且, 一步操做, 可能要等好久好久, 才能完成. 用戶可願意等?apache

  既然同步歸檔不可能了, 那是否有辦法實現異步歸檔? 異步歸檔怎麼實現呢?centos

     咱們其實能夠經過消息隊列來實現異步歸檔. 學生這邊點擊歸檔後, 發個消息到隊列中, 其餘系統自行去讀取, 而後完成各自系統應該完成的工做.瀏覽器

 

ActiveMQ下載安裝

    下載地址: http://activemq.apache.org/download.htmlspringboot

  安裝過程比較簡單, 在centos中, 解壓出來, 就算是安裝好了app

  運行方法: 異步

 

  運行起來後, 能夠經過 ip:8161 來查看是否成功. tcp

  

點擊紅框中的連接, 會出現登陸彈框, 帳號密碼默認都是admin.spring-boot

 

 

springboot整合activemq

 一. 目錄結構

producer : 消息生產者

consumer-a : 消息消費者

consumer-b : 消息消費者

pom文件:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>

 

若是使用pool的話, 就須要在pom中加入如下依賴:

<dependency>
     <groupId>org.apache.activemq</groupId>
     <artifactId>activemq-pool</artifactId>
     <version>5.14.5</version>
</dependency>

 

 二. producer

1. 目錄結構

 

2. yml文件:

server:
  port: 8080
  context-path: /pro
spring:
  activemq:
    user: admin
    password: admin
    broker-url: tcp://192.168.153.129:61616
    pool:
      enabled: true
      max-connections: 10

queueName: publish.queue
topicName: publish.topic

這裏我開啓了鏈接池, 默認是不開的.

這裏要注意端口, 不是以前的8161.

 

2. 配置文件  ActiveMQConfig 

/**
 * @author: elvin
 */
@Configuration
public class ActiveMQConfig {
    @Value("${queueName}")
    private String queueName;

    @Value("${topicName}")
    private String topicName;

    @Value("${spring.activemq.user}")
    private String usrName;

    @Value("${spring.activemq.password}")
    private  String password;

    @Value("${spring.activemq.broker-url}")
    private  String brokerUrl;

    @Bean
    public Queue queue(){
        return new ActiveMQQueue(queueName);
    }

    @Bean
    public Topic topic(){
        return new ActiveMQTopic(topicName);
    }

    @Bean
    public ActiveMQConnectionFactory connectionFactory() {
        return new ActiveMQConnectionFactory(usrName, password, brokerUrl);
    }

    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ActiveMQConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setConnectionFactory(connectionFactory);
        return bean;
    }

    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ActiveMQConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
//設置爲發佈訂閱方式, 默認狀況下使用的生產消費者方式 bean.setPubSubDomain(
true); bean.setConnectionFactory(connectionFactory); return bean; } }

這裏原本不須要配置這麼多的, 可是在consumer中也會用到, 因此就暫時弄一份同樣的, 拷貝一下完事.

 

3. PublishController

/**
 * @author: elvin
 */
@RestController
@RequestMapping("/publish")
public class PublishController {

    @Autowired
    private JmsMessagingTemplate jms;

    @Autowired
    private Queue queue;

    @Autowired
    private Topic topic;

    @RequestMapping("/queue")
    public String queue(){

        for (int i = 0; i < 10 ; i++){
            jms.convertAndSend(queue, "queue"+i);
        }

        return "queue 發送成功";
    }

    @JmsListener(destination = "out.queue")
    public void consumerMsg(String msg){
        System.out.println(msg);
    }

    @RequestMapping("/topic")
    public String topic(){

        for (int i = 0; i < 10 ; i++){
            jms.convertAndSend(topic, "topic"+i);
        }

        return "topic 發送成功";
    }
}

 

 三. consumer 

1. 目錄結構

a,b是同樣的, 只是顯示的信息不一樣.

 

2. 配置文件

yml配置文件是同樣的, 只是修改了端口和context-path.

ActiveMQConfig文件內容是同樣的.

 

3. listener

/**
 * @author: elvin
 */
@Component
public class QueueListener {

    @JmsListener(destination = "publish.queue", containerFactory = "jmsListenerContainerQueue")
    @SendTo("out.queue")
    public String receive(String text){
        System.out.println("QueueListener: consumer-a 收到一條信息: " + text);
        return "consumer-a received : " + text;
    }
}

SendTo 會將此方法返回的數據, 寫入到 queue : out.queue 中去.

/**
 * @author: elvin
 */
@Component
public class TopicListener {

    @JmsListener(destination = "publish.topic", containerFactory = "jmsListenerContainerTopic")
    public void receive(String text){
        System.out.println("TopicListener: consumer-a 收到一條信息: " + text);
    }
}

這裏經過傳入不一樣的factory, 來實現發送不一樣類型的信息.

 

四. 測試

 1. queue測試

瀏覽器中訪問: http://localhost:8080/pro/publish/queue

而後看一下, 控制檯, 那些用戶接收到了信息.

從上兩幅圖看的出來, a, b並不能同時接收數據. 這是queue的方式, 點對點.

那我想點對面, 怎麼辦?

 

2. topic測試

瀏覽器訪問頁面: http://localhost:8080/pro/publish/topic

a用戶徹底接收到信息了. 再看看b用戶

沒毛病, 也都接收到數據了.

topic默認狀況下, 是不會保存數據的, 也就是說, consumer是接收不到以前未接收到的信息.

而queue倒是能夠的. 

可是, topic並非不能實現那個功能, 只要配置一下, 仍是能夠的.

相關文章
相關標籤/搜索