一、订阅杂志
我们很多人都订过杂志,其过程很简单。只要告诉邮局我们所要订的杂志名、投递的地址,付了钱就OK。出版社定期会将出版的杂志交给邮局,邮局会根据订阅的列表,将杂志送达消费者手中。这样我们就可以看到每一期精彩的杂志了。

仔细思考一下订杂志的过程,我们会发现这样几个特点:
1、消费者订杂志不需要直接找出版社;
2、出版社只需要把杂志交给邮局;
3、邮局将杂志送达消费者。
邮局在整个过程中扮演了非常重要的中转作用,在出版社和消费者相互不需要知道对方的情况下,邮局完成了杂志的投递。

二、 发布-订阅消息模式
刚刚讲了订阅杂志,下面我们会讲传统调用模式演化到发布-订阅消息模式。

有些网站在注册用户成功后发一封激活邮件,用户收到邮件后点击激活链接后才能使用该网站。一般的做法是在注册用户业务逻辑中调用发送邮件的逻辑。这样用户业务就依赖于邮件业务。如果以后改为短信激活,注册用户业务逻辑就必须修改为调用发送短信的逻辑。如果要注册后给用户加点积分,再加一段逻辑。经过多次修改,我们发现很简单的注册用户业务已经越来越复杂,越来越难以维护。相信很多开发者都会有类似痛苦的经历。

即使用户业务实现中对其他业务是接口依赖,也避免不了业务变化带来的依赖影响。怎么办?解耦!将注册用户业务逻辑中注册成功后的处理剥离出来。

再回头看看“订阅杂志”,如果没有邮局,出版社就必须自己将杂志送达所有消费者。这种情形就和现在的注册用户业务一样。我们发现问题了,在用户业务和其他业务之间缺少了邮局所扮角色。

我们把邮局抽象成一个管理消息的地方,叫“消息管理器”。注册用户成功后发送一个消息给消息管理器,由消息管理器转发该消息给需要处理的业务。现在,用户业务只依赖于消息管理器了,它再也不会为了注册用户成功后的其他处理而烦恼。

注册用户的改造就是借鉴了“订阅杂志”这样原始的模式。我们再进一步抽象,用户业务就是消息的“生产者”,它将消息发布到消息管理器。邮件业务就是消息的“消费者”,它将收到的消息进行处理。邮局可以订阅很多种杂志,杂志都是通过某种编号来区分;消息管理器也可以管理多种消息,每种消息都会有一个“主题”来区分,消费者都是通过主题来订阅的。

发布-订阅消息模式已经呈现在我们面前,在这里,对于发布者来说,它和所有的订阅者就构成了一个1对多的关系。这种关系如下图所示:

示例:
1、Publish.java:消息发布者

package com.ljq.durian.test.activemq;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; public class Publish {
private ConnectionFactory factory;
private Connection connection;
private Session session;
private MessageProducer producer; public Publish() {
try {
factory = new ActiveMQConnectionFactory("ljq", "ljq", "failover:(tcp://localhost:61616)?Randomize=false");
connection = factory.createConnection();
connection.start();
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(null);
} catch (Exception e) {
e.printStackTrace();
}
} public void sendMessage() throws Exception {
Destination destination = session.createTopic("Topic001");
TextMessage msg = session.createTextMessage("我是消息内容...");
producer.send(destination, msg); if(connection != null){
connection.close();
}
} public static void main(String[] args) throws Exception {
Publish publish= new Publish();
publish.sendMessage();
}
}

2、Subscriber1.java:消息订阅者

package com.ljq.durian.test.activemq;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; public class Subscriber1 {
private ConnectionFactory factory;
private Connection connection;
private Session session; public Subscriber1() {
try {
factory = new ActiveMQConnectionFactory("ljq", "ljq", "failover:(tcp://localhost:61616)?Randomize=false");
connection = factory.createConnection();
connection.start();
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
} catch (Exception e) {
e.printStackTrace();
}
} public void receive() throws Exception {
Destination topic = session.createTopic("Topic001") ;
MessageConsumer consumer = session.createConsumer(topic);
consumer.setMessageListener(new Listener());
} class Listener implements MessageListener {
@Override
public void onMessage(Message message) {
try {
TextMessage tm = (TextMessage) message;
System.out.println("Subscriber1 Received message: " + tm.getText());
} catch (JMSException e) {
e.printStackTrace();
}
} } public static void main(String[] args) throws Exception {
Subscriber1 subscriber = new Subscriber1();
subscriber.receive();
}
}

3、Subscriber2.java:消息订阅者

package com.ljq.durian.test.activemq;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage; import org.apache.activemq.ActiveMQConnectionFactory; public class Subscriber2 {
private ConnectionFactory factory;
private Connection connection;
private Session session; public Subscriber2() {
try {
factory =
new ActiveMQConnectionFactory("ljq", "ljq",
"failover:(tcp://192.168.1.101:61616)?Randomize=false");
connection = factory.createConnection();
connection.start();
session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
} catch (Exception e) {
e.printStackTrace();
}
} public void receive() throws Exception {
Destination topic = session.createTopic("Topic001") ;
MessageConsumer consumer = session.createConsumer(topic);
consumer.setMessageListener(new Listener());
} class Listener implements MessageListener {
public void onMessage(Message message) {
System.out.println(message);
try {
TextMessage tm = (TextMessage) message;
System.out.println("Subscriber2 Received message: " + tm.getText());
} catch (JMSException e) {
e.printStackTrace();
}
} } public static void main(String[] args) throws Exception {
Subscriber2 subscriber = new Subscriber2();
subscriber.receive();
}
}

ActiveMQ发布-订阅消息模式的更多相关文章

  1. ActiveMQ发布-订阅消息模式(同点对点模式的区别)

    点对点与发布订阅最初是由JMS定义的.这两种模式主要区别或解决的问题就是发送到队列的消息能否重复消费(多订阅) 点对点: 消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费 ...

  2. (三)ActiveMQ之发布- 订阅消息模式实现

    一.概念 发布者/订阅者模型支持向一个特定的消息主题发布消息.0或多个订阅者可能对接收来自特定消息主题的消息感兴趣.在这种模型下,发布者和订阅者彼此不知道对方.这种模式好比是匿名公告板.这种模式被概括 ...

  3. “一切都是消息”--MSF(消息服务框架)之【发布-订阅】模式

    在上一篇,“一切都是消息”--MSF(消息服务框架)之[请求-响应]模式 ,我们演示了MSF实现简单的请求-响应模式的示例,今天来看看如何实现[发布-订阅]模式.简单来说,该模式的工作过程是: 客户端 ...

  4. “一切都是消息”--iMSF(即时消息服务框架)之【发布-订阅】模式

    MSF的名字是 Message Service Framework 的简称,由于目前框架主要功能在于处理即时(immediately)消息,所以iMSF就是 immediately Message S ...

  5. JMS发布/订阅消息传送例子

    前言 基于上篇文章"基于Tomcat + JNDI + ActiveMQ实现JMS的点对点消息传送"很容易就可以编写一个发布/订阅消息传送例子,相关环境准备与该篇文章基本类似,主要 ...

  6. Kafka是分布式发布-订阅消息系统

    Kafka是分布式发布-订阅消息系统 https://www.biaodianfu.com/kafka.html Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apa ...

  7. 分布式发布订阅消息系统 Kafka 架构设计[转]

    分布式发布订阅消息系统 Kafka 架构设计 转自:http://www.oschina.net/translate/kafka-design 我们为什么要搭建该系统 Kafka是一个消息系统,原本开 ...

  8. 发布-订阅消息系统Kafka简介

    转载请注明出处:http://www.cnblogs.com/BYRans/ Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写.Kafka是一种高吞吐量的分布式 ...

  9. Kafka(分布式发布-订阅消息系统)工作流程说明

    Kafka系统架构Apache Kafka是分布式发布-订阅消息系统.它最初由LinkedIn公司开发,之后成为Apache项目的一部分.Kafka是一种快速.可扩展的.设计内在就是分布式的,分区的和 ...

随机推荐

  1. (线段树)敌兵布阵--hdu--1166 (入门)

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1166 自己第一次在没有看题解AC出来的线段树,写的可能不是太好,再贴个学长的代码,学习一下 发现自己的U ...

  2. Qt .pro文件 详解

    1. TEMPLATE变量TEMPLATE描述了为建立目标文件而采用何种模板,即生成何种形式的Makefile文件.Qmake工具定义了5种模板:1. 应用程序App,为建立一个Qt应用程序创建Mak ...

  3. springmvc 孔浩 hibernate

    以上为项目文件 用到的jar包:http://pan.baidu.com/s/1kT1Rsqj 1. model-User 2. beans.xml-去哪些包中找annotation:查找相应的实体类 ...

  4. express4.X 笔记

    express是node的web框架,更新频繁,3.X到4.X有了很大的改变.网上的例子,各种版本的都有,为了以后方便,现在重新认真看一遍4.X的API,统一以后的使用方法.在J2EE上落后了,在ex ...

  5. spring案列——annotation配置

    一.需要的jar包 spring.jar commons-loggin.jar commons-loggin.jar commons-annotation.jar 二.项目结构 三.entity pa ...

  6. (原创)hibernate 一对多建表实例详解 附上各个注释的含义

    这个是hibernate的一对多建表实例:一的一端是部门(Department),对的一端是员工(Employee),下面贴上成员源代码:其中@mappedBy是加在@OneToMany一端,并且它的 ...

  7. 获取Oracle EBS数据库跟踪文件方法

    http://www.orapub.cn/posts/1624.html 一.以下在Oracle APP中执行: 1) Set the Profile Option: ‘Initialization ...

  8. 截图-----Selenium快速入门(十二)

    在自动化测试过程中,截图是常见的操作,因为有时候单靠程序无法判断是否已得到期望的结果,所以需要截图判断.又或者截图是作为判断的存证.Selenium的截图操作也是非常简单,而且自带了一个文件操作类Fi ...

  9. C# RS232串口使用

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  10. C# 一些代码小结--使用文件记录日志

    C# 一些代码小结--使用文件记录日志 public class FaceLog { public static void AppendInfoLog(string errMsg) { try { s ...