在没有JMS之前,很多应用系统存在缺陷
像下图中A和B直接进行点对点通信,client端的一次调用只能发送给某一个单独的服务对象,无法一对多,而且client 和 server 的生命周期耦合太高,client进程和server服务进程都必须可用,如果server出现问题或者网络故障,那么client端会收到异常,client端发起调用后,必须等待server处理完成并返回结果后才能继续执行
MOM就是面向消息中间件(Message-oriented middleware),是用于以分布式应用或系统中的异步、松耦合、可靠、可扩展和安全通信的一类软件。MOM的总体思想是它作为消息发送器和西消息接收器之间的消息中介,这种中介提供了一个全新水平的松耦合
JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。JMS是一组消息服务的api即接口规范(ActiveMQ即是对JMS的实现还有阿里的 RocketMQ )。简单来说就是MOM是中间件,JMS是对中间件定义的规范,而ActiveMQ就是JMS的一种实现
ActiveMQ
activeMQ是Apache推出的,一款开源的,完全支持JMS1.1和J2EE1.4规范的JMS Provider实现的中间件(MOM)
官网地址:http://activemq.apache.org/,分为Linux版和windows版,这里以windows为例
下载号之后解压,目录如下图
bin下面存放的是ActiveMQ的启动脚本activemq.bat,注意分32、64位
conf里面是配置文件,重点关注的是activemq.xml、jetty.xml、jetty-realm.properties。在登录ActiveMQ Web控制台需要用户名、密码信息;在JMS CLIENT和ActiveMQ进行何种协议的连接、端口是什么等这些信息都在上面的配置文件中可以体现。
data目录下是ActiveMQ进行消息持久化存放的地方,默认采用的是kahadb,当然我们可以采用leveldb,或者采用JDBC存储到MySQL,或者干脆不使用持久化机制。
webapps,注意ActiveMQ自带Jetty提供Web管控台
lib中ActiveMQ为我们提供了分功能的JAR包,当然也提供了activemq-all-5.14.4.jar
bin目录下的activemq.bat启动mq,在jetty-realm.properties中可以设置用户名密码,activemq.xml中设置常用配制(端口号等)
在JDK安装没有问题的情况下,直接activemq.bat启动它,并访问Web控制台!
ActiveMQjetty-realm.properties
术语
Provider/MessageProvider:生产者
Consumer/MessageConsumer:消费者
PTP:Point To Point,点对点通信消息模型
Pub/Sub:Publish/Subscribe,发布订阅消息模型
Queue:队列,目标类型之一,和PTP结合
Topic:主题,目标类型之一,和Pub/Sub结合
ConnectionFactory:连接工厂,JMS用它创建连接
Connnection:JMS Client到JMS Provider的连接
Destination:消息目的地,由Session创建
Session:会话,由Connection创建,实质上就是发送、接受消息的一个线程,因此生产者、消费者都是Session创建的
hello world
public class Sender {
public static void main(String[] args) throws Exception{
//1、建立ConnectionFactory,需要填入用户名、密码以及连接的地址,均使用默认即可,默认为"tcp:localhost:61616"
ConnectionFactory connectfactory = new ActiveMQConnectionFactory(
ActiveMQConnectionFactory.DEFAULT_USER,
ActiveMQConnectionFactory.DEFAULT_PASSWORD,
"tcp://localhost:61616");
//2、通过connectionfactory创建一个connection,并且调用connection的start方法开启连接,连接默认是关闭的
Connection connection = connectfactory.createConnection();
connection.start();
//3、通过connection创建一个session会话(上下文环境),用于接收消息,
//3.1 参数1为是否开启事务
//3.2 参数2为签收模式,一般设置为自动签收
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//4、 Destination :消息的目的地;消息发送给谁.在PTP模式中,被称为Queue,在发布订阅模式中被称为Topic
// 获取session注意参数值my-queue是Query的名字
Destination destination = session.createQueue("my-queue");
//5、通过session创建消息的发送者和接受者MessageProducer和MessageCustomer
MessageProducer producter = session.createProducer(destination);
for(int i=0;i<5;i++){
TextMessage message = session.createTextMessage("message--"+i);
producter.send(message);
}
if(connection!=null)
connection.close();//会自动关闭session等
}
}
运行发送者代码,可以看到
有五条消息放入了中间件
Messages Enqueued:表示生产了多少条消息,记做P
Messages Dequeued:表示消费了多少条消息,记做C
Number Of Consumers:表示在该队列上还有多少消费者在等待接受消息
Number Of Pending Messages:表示还有多少条消息没有被消费,实际上是表示消息的积压程度,就是P-C
public static void main(String[] args) throws Exception{
//1、建立ConnectionFactory,需要填入用户名、密码以及连接的地址,均使用默认即可,默认为"tcp:localhost:61616"
ConnectionFactory connectfactory = new ActiveMQConnectionFactory(
ActiveMQConnectionFactory.DEFAULT_USER,
ActiveMQConnectionFactory.DEFAULT_PASSWORD,
"tcp://localhost:61616");
//2、通过connectionfactory创建一个connection,并且调用connection的start方法开启连接,连接默认是关闭的
Connection connection = connectfactory.createConnection();
connection.start();
//3、通过connection创建一个session会话(上下文环境),用于接收消息,
//3.1 参数1为是否开启事务
//3.2 参数2为签收模式,一般设置为自动签收
Session session = connection.createSession(Boolean.FALSE, Session.AUTO_ACKNOWLEDGE);
//4、 Destination :消息的目的地;消息发送给谁.在PTP模式中,被称为Queue,在发布订阅模式中被称为Topic
// 获取session注意参数值my-queue是Query的名字
Destination destination = session.createQueue("my-queue");
//5、通过session创建消息的发送者和接受者MessageProducer和MessageCustomer
MessageConsumer consumer = session.createConsumer(destination);
while(true) {
TextMessage msg = (TextMessage)consumer.receive();
if(msg==null)
break;
System.out.println(msg.getText());
}
if(connection!=null)
connection.close();//会自动关闭session等
}
运行代码之后可以看到