简介
为了适应当前分布式系统的发展,系统与系统之间的通信尤为重要。而JMS就是为了将系统之间解耦,以消息中间件的形式连接系统。以下是ActiveMQ的简单介绍和入门实例
下载安装ActiveMQ
- 进入下载地址,下载适应版本。
- 解压后进入bin目录点击activemq.bat(windows下)启动即可。
- 启动失败请依次检查jdk版本和端口61616是否被占用。
通信方式
- 点对点/P2P
- 发布者&订阅者
以上两种通信方式就是最基础的消息通信方式,还可以根据它们衍生出消息回执的通信方式
点对点通信
点对点通信就像通话一样,一个生产者发出的消息只有一个消费者接收到并进行处理。
package com.paditang.activemq.p2p;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Producer {
private ConnectionFactory factory;
private Connection connection;
private Session session;
private MessageProducer producer;
private Destination destination;
public Producer(String queueName) throws JMSException{
factory = new ActiveMQConnectionFactory();
connection = factory.createConnection();
connection.start();
try{
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
} catch(JMSException e){
connection.close();
throw e;
}
destination = session.createQueue(queueName);
producer = session.createProducer(destination);
}
public void sendMsg(String content) throws JMSException{
TextMessage msg = session.createTextMessage(content);
producer.send(msg);
}
public void close() throws JMSException{
connection.close();
}
public static void main(String []args) throws JMSException{
Producer p = new Producer("test_queue");
p.sendMsg("listener msg");
p.close();
}
}
package com.paditang.activemq.p2p;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
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.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
import com.paditang.activemq.base.MsgListener;
public class Consumer {
private ConnectionFactory factory;
private Connection connection;
private Session session;
private Destination destination;
private MessageConsumer consumer;
public Consumer(String queueName) throws JMSException{
factory = new ActiveMQConnectionFactory();
connection = factory.createConnection();
connection.start();
try{
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
} catch(JMSException e){
connection.close();
throw e;
}
destination = session.createQueue(queueName);
consumer = session.createConsumer(destination);
}
//通过receive方法接收消息
public void receiveMessage() throws JMSException{
while(true){
Message msg = consumer.receive();
if(msg instanceof TextMessage){
String str = ((TextMessage)msg).getText();
System.out.println(str);
}
}
}
//通过设置监听器收消息
public void receiveByListener() throws JMSException{
consumer.setMessageListener(new MsgListener());
}
public void close() throws JMSException{
connection.close();
}
public static void main(String []args) throws JMSException{
Runnable r = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try{
Consumer consumer = new Consumer("test_queue");
//consumer.receiveMessage();
consumer.receiveByListener();
//consumer.close();
}catch(JMSException e){
e.printStackTrace();
}
}
};
Executor e = Executors.newFixedThreadPool(10);
for(int i =0; i < 10; i++){
e.execute(r);
}
}
}
package com.paditang.activemq.base;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
public class MsgListener implements MessageListener{
@Override
public void onMessage(Message message) {
if(message instanceof TextMessage){
try{
System.out.println("get msg:"+((TextMessage)message).getText());
} catch(JMSException e){
e.printStackTrace();
}
}
}
}
console:
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
get msg:listener msg
如上一个生产者生产消息,十个消费者消费消息的模型下。当发出一条消息,只有一个消费者接收到消息。可以证明点对点通信方式的通信逻辑。
发布者&订阅者
发布者&订阅者模式更类似于订阅报纸。每当报社有新报纸发布后,都将通知并配送到订阅人手里。而这种模式类似,当发布者发布消息到Topic上,会将消息发送到到活跃的订阅者中。
package com.paditang.activemq.topic;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Publisher {
private ConnectionFactory connectionFactory;
private Connection connection;
private Session session;
private MessageProducer producer;
private Destination destination;
public Publisher(String topicName) throws JMSException{
connectionFactory = new ActiveMQConnectionFactory();
connection = connectionFactory.createConnection();
try{
connection.start();
}catch(JMSException e){
connection.close();
throw e;
}
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createTopic(topicName);
producer = session.createProducer(destination);
}
public void sendMessage(String message) throws JMSException{
Message msg = session.createTextMessage(message);
producer.send(msg);
}
public void close() throws JMSException{
if(connection != null){
connection.close();
}
}
public static void main(String []args) throws JMSException{
Publisher p = new Publisher("test_topic");
p.sendMessage("first msg");
p.close();
}
}
package com.paditang.activemq.topic;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
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.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Listener {
private ConnectionFactory factory;
private Connection connection;
private Session session;
private Destination destination;
private MessageConsumer consumer;
public Listener(String topicName) throws JMSException{
factory = new ActiveMQConnectionFactory();
connection = factory.createConnection();
connection.start();
try{
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
} catch(JMSException e){
connection.close();
throw e;
}
destination = session.createTopic(topicName);
consumer = session.createConsumer(destination);
}
public void receiveMessage() throws JMSException{
while(true){
Message msg = consumer.receive();
if(msg instanceof TextMessage){
String str = ((TextMessage)msg).getText();
System.out.println(str);
}
}
}
public void close() throws JMSException{
connection.close();
}
public static void main(String []args) throws JMSException{
Runnable r = new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try{
Listener consumer = new Listener("test_topic");
consumer.receiveMessage();
consumer.close();
}catch(JMSException e){
e.printStackTrace();
}
}
};
Executor e = Executors.newFixedThreadPool(10);
for(int i =0; i < 10; i++){
e.execute(r);
}
}
}
listener-console:
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
INFO | Successfully connected to tcp://localhost:61616
first msg
first msg
first msg
first msg
first msg
first msg
first msg
first msg
first msg
first msg
从输出上来看,当生成十个订阅者订阅目标topic时,当发布者发布一条消息,所有订阅者都能收到这条消息。
这就是和P2P的不同之处。
收到消息回复模式
可以通过一些方式使得生产者得到消费者收到消息后的回执,这就是这种模式的意义
package com.paditang.activemq.reply;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
import com.paditang.activemq.base.MsgListener;
public class Client {
private static String USER_NAME = ActiveMQConnectionFactory.DEFAULT_USER;
private static String PASSWORD = ActiveMQConnectionFactory.DEFAULT_PASSWORD;
private static String BROKE_URL = ActiveMQConnectionFactory.DEFAULT_BROKER_URL;
private ConnectionFactory factory;
private Connection connection;
private Session session;
private Destination destination;
private MessageProducer producer;
public Client(String queueName) throws JMSException{
factory = new ActiveMQConnectionFactory(USER_NAME, PASSWORD, BROKE_URL);
connection = factory.createConnection();
try{
connection.start();
} catch(JMSException e){
connection.close();
throw e;
}
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(queueName);
producer = session.createProducer(destination);
}
public void sendMessage(String content) throws JMSException{
Destination tmpDestination = session.createTemporaryQueue();
MessageConsumer retConsumer = session.createConsumer(tmpDestination);
retConsumer.setMessageListener(new MsgListener());
TextMessage msg = session.createTextMessage(content);
msg.setJMSReplyTo(tmpDestination);
String uuid = generateRandomTag();
msg.setJMSCorrelationID(uuid);
producer.send(msg);
System.out.println("send msg:"+msg);
}
public String generateRandomTag(){
return String.valueOf(System.currentTimeMillis());
}
public static void main(String []args) throws JMSException{
Client client = new Client("server_queue");
client.sendMessage("info");
}
}
package com.paditang.activemq.reply;
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.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
public class Server {
private static String USER_NAME = ActiveMQConnectionFactory.DEFAULT_USER;
private static String PASSWORD = ActiveMQConnectionFactory.DEFAULT_PASSWORD;
private static String BROKE_URL = ActiveMQConnectionFactory.DEFAULT_BROKER_URL;
private ConnectionFactory factory;
private Connection connection;
private Session session;
private Destination destination;
private MessageConsumer consumer;
public Server(String queueName) throws JMSException{
factory = new ActiveMQConnectionFactory(USER_NAME, PASSWORD, BROKE_URL);
connection = factory.createConnection();
try{
connection.start();
} catch(JMSException e){
connection.close();
throw e;
}
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
destination = session.createQueue(queueName);
consumer = session.createConsumer(destination);
}
public void receiveMessage() throws JMSException{
while(true){
Message msg = consumer.receive();
String retStr = "initial ret";
if(msg instanceof TextMessage){
System.out.println("get msg:"+((TextMessage)msg).getText());
retStr = ((TextMessage)msg).getText();
}
MessageProducer retProducer = session.createProducer(null);
TextMessage retMsg = session.createTextMessage(retStr);
retMsg.setJMSCorrelationID(msg.getJMSCorrelationID());
retProducer.send(msg.getJMSReplyTo(),retMsg);
System.out.println("ret msg:"+retStr);
}
}
public static void main(String []args) throws JMSException{
Server server = new Server("server_queue");
server.receiveMessage();
}
}