activemq 的p2p和Publish/Subscribe 两种模式

springboot 整合 activemq

  • 这个demo纯粹是一个小demo 因为为了学习dubbo,在这个demo是实现了发布订阅和点对点两种模式
    别的不多说,直接上代码: 结尾我会把代码贴上去
首先引入依赖
        <!-- 整合消息队列ActiveMQ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <!-- 配置线程池 -->
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-pool</artifactId>
        </dependency>
SpringBoot+ActiveMQ实战之点对点模式(p2p)
 activemq:
    broker-url: tcp://127.0.0.1:61616  #地址
    user: admin
    password: admin
    pool:
      enabled: true
      max-connections: 100  #线程池
启动类添加@EnableJms注解,开启支持jms

在这里插入图片描述

  • 在springboot启动类添加一个 queue对象,并交给spring进行管理
    @Bean
    public Queue queue() {
        return new ActiveMQQueue("message.queue");
    }

- 定义消息的生产者和消费者

import com.itcorey.service.ProducerService;
import org.apache.activemq.command.ActiveMQQueue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @Classname MessageController
 * @Description 定义消息的生产者和消费者
 * @Date 2020/5/19 14:44
 * @Created by corey
 */
@RestController
@RequestMapping("/api/message")
public class MessageController {
    @Resource
    private ProducerService producerService;
    @GetMapping("/send")
    public String sendMsg(String message) {
        new Thread(new Runnable() {
            @Override
            public void run() {
            for (int i = 0;i<=10;i++){
                // 目的地
                ActiveMQQueue desination = new ActiveMQQueue("message.queue");
                // 发送消息
                producerService.sendMessage(message, desination);
            }
            }
        }).start();
        return "success!!";
    }
}

- ProducerService.java

package com.itcorey.service;
import javax.jms.Destination;

/**
 * @Classname ProducerService
 * @Description 消息生产者
 * @Date 2020/5/19 14:47
 * @Created by corey
 */
public interface ProducerService {

    void sendMessage(final String msg);

    void sendMessage(final String msg, Destination destination);

    void publish(final String msg);
}

ProducerServiceImpl.java

@Service
public class ProducerServiceImpl implements ProducerService {
  @Autowired
  private Queue queue;// 默认消息队列
  @Autowired
  private JmsMessagingTemplate JmsTemplate; // 用来发送消息到broker的对象

  //发送消息
  @Override
  public void sendMessage(String msg) {
    JmsTemplate.convertAndSend(this.queue, msg);
  }

  //发送消息
  @Override
  public void sendMessage(String msg, Destination destination) {
    JmsTemplate.convertAndSend(destination, msg);
  }
}

MessageConsumer.java:

@Component
public class MessageConsumer {
  @JmsListener(destination = "message.queue")
  public void receiveMessage(String txt) {
    System.out.println("MessageConsumer接收到的信息:" + txt);
  }
}

模拟请求
请求地址:http://localhost:8080/api/message/send?message=hello
在这里插入图片描述

结果

在这里插入图片描述
二、SpringBoot+ActiveMQ实战之发布订阅模式(pub/sub)
需要加入配置文件,支持发布订阅模型,默认只支持点对点
#default point to point
spring.jms.pub-sub-domain=true
在这里插入图片描述
添加topic对象

@EnableJms
@SpringBootApplication
public class ActivemqWebApplication {
  @Bean
  public Topic topic() {
    return new ActiveMQTopic("news.topic");
  }

  @Bean
  ConnectionFactory connectionFactory() {
    return new ActiveMQConnectionFactory();
  }

  @Bean
  JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {
    JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
    jmsTemplate.setPriority(999);
    return jmsTemplate;
  }

  @Bean(value = "jmsMessagingTemplate")
  JmsMessagingTemplate jmsMessagingTemplate(JmsTemplate jmsTemplate) {
    JmsMessagingTemplate messagingTemplate = new JmsMessagingTemplate(jmsTemplate);
    return messagingTemplate;
  }

  public static void main(String[] args) {
    SpringApplication.run(ActivemqWebApplication.class, args);
  }
}

定义消息的发布者和订阅者
NewsController.java

package com.itcorey.controller;

import com.itcorey.service.ProducerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @Classname NewsController
 * @Description TODO
 * @Date 2020/5/19 15:47
 * @Created by corey
 */
@RequestMapping("/api/news")
@RestController
public class NewsController {
    @Autowired
    private ProducerService producerService;
    @GetMapping("/publish")
    public String publish(String news) {
        // 发布信息
        producerService.publish(news);
        return "success!!!";
    }
}

ProducerService
在这里插入图片描述
ProducerServiceImpl实现

@Service
public class ProducerServiceImpl implements ProducerService {
  private Topic topic; // 默认主题
  @Autowired
  private JmsMessagingTemplate JmsTemplate; // 用来发送消息到broker的对象

  /**
   * 功能描述:发布消息
   */
  @Override
  public void publish(String msg) {
    JmsTemplate.convertAndSend(this.topic, msg);
  }
}

NewsSub.java

@Component
public class NewsSub {
  @JmsListener(destination = "news.topic")
  public void receive1(String text) {
    System.out.println("news.topic 消费者:receive1=" + text);
  }

  @JmsListener(destination = "news.topic")
  public void receive2(String text) {
    System.out.println("news.topic 消费者:receive2=" + text);
  }

  @JmsListener(destination = "news.topic")
  public void receive3(String text) {
    System.out.println("news.topic 消费者:receive3=" + text);
  }
}

模拟测试
请求地址:http://localhost:8080/api/news/publish?news=topic
在这里插入图片描述
注意,如果相同时兼容两种情况,P2P和pub/sub两种.
@JmsListener如果不指定独立的containerFactory的话是只能消费queue消息,需要修改订阅者container:containerFactory=“jmsListenerContainerTopic”

@Component
public class NewsSub {
  @JmsListener(destination = "news.topic", containerFactory = "jmsListenerContainerTopic")
  public void receive1(String text) {
    System.out.println("news.topic 消费者:receive1=" + text);
  }

  @JmsListener(destination = "news.topic", containerFactory = "jmsListenerContainerTopic")
  public void receive2(String text) {
    System.out.println("news.topic 消费者:receive2=" + text);
  }

  @JmsListener(destination = "news.topic", containerFactory = "jmsListenerContainerTopic")
  public void receive3(String text) {
    System.out.println("news.topic 消费者:receive3=" + text);
  }
}

需要在启动类给topic定义独立的JmsListenerContainer

@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) {
    DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
    bean.setPubSubDomain(true);
    bean.setConnectionFactory(activeMQConnectionFactory);
    
    return bean;
}

在配置文件里面,注释掉 #spring.jms.pub-sub-domain=true

写在最后:

1.什么是JMS
JMS是java消息服务(java Message service) 应用接口,是一个java平台中关于面向消息中间件(MOM)的API,用于两个程序之间,或分布式系统中发送消息进行异步通信.Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持(百度百科给出的概述)。我们可以简单的理解:两个应用程序之间需要进行通信,我们使用一个JMS服务,进行中间的转发,通过JMS 的使用,我们可以解除两个程序之间的耦合。

2. JMS的优势

  1. Asynchronous(异步)
    JMS 原本就是一个异步的消息服务,客户端获取消息的时候,不需要主动发送请求,消息会自动发送给可用的客户端。
    2. Reliable(可靠)
    JMS保证消息只会递送一次。大家都遇到过重复创建消息问题,而JMS能帮你避免该问题。
    3 JMS的消息模式
    点对点通信模型(Point-to-Point)在点对点通信模式中,应用程序由消息队列,发送方,接收方组成。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。
    在这里插入图片描述
    特点:
  • 每个消息只要一个消费者
  • 发送者接受者在时间上没有时间约束,也就是说发送者在发送完消息之后,不管接收者有没有接受消息,都不会影响发送方发送消息到消息队列中。
  • 发送方不管是否在发送消息,接收方都可以从消息队列中取到消息,(The receiver can fetch message whether it is running or not when the sender sends the message)。
  • 接收方在接收完消息之后,需要向消息队列应答成功。
  1. 发布/订阅通信模型(Publish/Subscribe Messaging Domain)
    在发布/订阅消息模型中,发布者发布一个消息,该消息通过topic传递给所有的客户端,该模式下,发布者与订阅者都是匿名的,即发布者与订阅者都不知道对方是谁。并且可以动态的发布与订阅Topic。Topic主要用于保存和传递消息,且会一直保存消息直到消息被传递给客户端。
    在这里插入图片描述
    特点
  • 一个消息可以传递个多个订阅者(即:一个消息可以有多个接受方)。
  • 发布者与订阅者具有时间约束,针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运行的状态。
  • 为了缓和这样严格的时间相关性,JMS允许订阅者创建一个可持久化的订阅。这样,即使订阅者没有被激活(运行),它也能接收到发布者的消息。
JMS的编程模型
  1. ConnectionFactory:连接工厂,JMS用它创建连接
  2. Connnection:连接对象,JMS Client到JMS Provider的连接
  3. Destination:消息目的地,由Session创建
  4. Session:会话,由Connection创建,实质上就是发送、接受消息的一个线程,因此生产者、消费者都是Session创建的
  5. Provider/MessageProvider:消息生产者
  6. Consumer/MessageConsumer:消息消费者
  7. Message Listeners:消息监听者
    在这里插入图片描述
    源码地址:https://github.com/coreyxuy/springboot-email.git
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值