异步消息
消息是通过网络从一个系统异步传送给另一个系统的,发送者不需要等待接收者接收或者处理该消息,因此消息传送机制能够实现组件之间的高度解耦,即:发送者-消息服务器-接受者。
JMS
JMS全称Java消息服务(Java Message Servicer),是一套java消息API,使用时需要提供者提供实现,常用的实现:ActiveMQ、RabbitMQ等。各个厂商实现消息机制的方案各不相同,导致了使用消息机制在不同的厂商之间切换的复杂性,为了统一消息API,Sun合作各消息提供者厂商统一出通用的消息接口,即 JMS API。
ActiveMQ安装:http://blog.csdn.net/u010845141/article/details/51778999
消息传送模型
点对点模型(P2P) one-to-one
消息发送者发送一条Message到Queue中,消息接收者从队列中接收一条消息,当有多个消息接收者时,该Message仅仅被接收一次,多消息接收者可使用负载均衡处理。
发布/订阅模型(Pub/Sub) one-to-many
发布者发布一条Message到相应的Topic,订阅了该主题的订阅者都将收到该Message的一个副本。
JMS API
下面的例子使用了ActiveMQ作为消息提供者,请参考ActiveMQ安装和使用:
ActiveMQ jar包
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>5.13.3</version>
</dependency>
- 公共API:
/**
* 使用公共API发送消息,先启动ActiveMQ服务器后执行
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//获取ActiveMQ连接工厂
ConnectionFactory connFactory = new ActiveMQConnectionFactory();
//获取到JMS提供者服务器连接
Connection conn = connFactory.createConnection();
//创建Session
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建目的地,使用Queue
Destination dest = session.createQueue("SampleQueue");
//创建生产者
MessageProducer prod = session.createProducer(dest);
//创建消息实体
Message msg = session.createTextMessage("Simples Assim");
//启动Connection,可以收发消息
conn.start();
//发送消息
prod.send(msg);
conn.close();
}
/**
* 消息接收者,启动后如果没有消息接收,则阻塞;接收到消息后打印退出
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception{
ConnectionFactory factory = new ActiveMQConnectionFactory();
Connection conn = factory.createConnection();
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination dest = session.createQueue("SampleQueue");
MessageConsumer consumer = session.createConsumer(dest);
conn.start();
TextMessage msg = (TextMessage)consumer.receive();
System.out.println(msg.getText());
conn.close();
}
- 点对点API
/**
* 使用两个队列request1,request2,request1发送消息,request2接收处理结果
* 发送 d1 = 1.0 ,d2 = 2.0,消息接收者求和,并发送消息返回
* @author TT
*
*/
public class One2OneSender {
public static void main(String[] args)throws Exception {
QueueConnectionFactory qFactory = new ActiveMQConnectionFactory();
QueueConnection qConnect = qFactory.createQueueConnection();
QueueSession qSession = qConnect.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
Queue requestQ = qSession.createQueue("request1");
Queue responseQ = qSession.createQueue("response2");
qConnect.start();
MapMessage msg = qSession.createMapMessage();
msg.setDouble("d1", 1.0);
msg.setDouble("d2", 2.0);
//设置消息接收队列
msg.setJMSReplyTo(responseQ);
QueueSender qSender = qSession.createSender(requestQ);
qSender.send(msg);
QueueReceiver qReceiver = qSession.createReceiver(responseQ);
TextMessage tmsg = (TextMessage)qReceiver.receive(30000);
if(tmsg == null) {
System.out.println("One2OneReceiver not responding.");
}else {
System.out.println("One2OneReceiver response was " + tmsg.getText());
}
}
}
/**
* 该类实现消息监听器接口,注册为request1队列的消息接收者
* 监听器处理类计算接收到的值并求和,发送接收到指定的队列request2
* @author TT
*
*/
public class One2OneReceiver implements MessageListener{
private QueueConnection qConnect = null;
private QueueSession qSession = null;
private Queue requestQ = null;
public One2OneReceiver(){
try {
QueueConnectionFactory connFactory = new ActiveMQConnectionFactory();
qConnect = connFactory.createQueueConnection();
qSession = qConnect.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
requestQ = qSession.createQueue("request1");
qConnect.start();
QueueReceiver receiver = qSession.createReceiver(requestQ);
receiver.setMessageListener(this);
System.out.println("Waiting for receive message...");
}catch(JMSException jmse) {
jmse.printStackTrace();
System.exit(1);
}
}
public void onMessage(Message message) {
MapMessage msg = (MapMessage)message;
try {
double d1 = msg.getDouble("d1");
double d2 = msg.getDouble("d2");
System.out.println("Sum : " + (d1 + d2));
TextMessage tmsg = qSession.createTextMessage();
tmsg.setText("" +(d1 + d2));
tmsg.setJMSCorrelationID(message.getJMSMessageID());
QueueSender sender = qSession.createSender((Queue)message.getJMSReplyTo());
sender.send(tmsg);
} catch (JMSException e) {
e.printStackTrace();
}
}
private void exit() {
try {
qConnect.close();
}catch(JMSException e) {
e.printStackTrace();
}
System.exit(0);
}
public static void main(String[] args) {
One2OneReceiver receiver = new One2OneReceiver();
try {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Press enter to quit application.");
stdin.readLine();
receiver.exit();
}catch(IOException e) {
e.printStackTrace();
}
}
}
- 发布/订阅API
/**
* 执行一次该程序,启动一个Chat,任意一个Chat发送的消息,其他Chat都可以接收到
* 同时,该Chat也是该Topic的订阅者
*
* 注:执行时,先启动ActiveMQ服务器
*/
public class TopicChat implements MessageListener{
private TopicConnection connection;
private TopicSession pubSession;
private TopicPublisher publisher;
private String username;
public TopicChat(String username) throws Exception{
TopicConnectionFactory connfactory = new ActiveMQConnectionFactory();
TopicConnection connection = connfactory.createTopicConnection();
//发布者Session和订阅者Session
TopicSession pubSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
TopicSession subSession = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
//订阅主题
Topic chatTopic = pubSession.createTopic("topic1");
//发布者
TopicPublisher publisher = pubSession.createPublisher(chatTopic);
//订阅者,第三个参数标识自己不接受自己发送的消息
TopicSubscriber subscriber = subSession.createSubscriber(chatTopic,null,true);
//注册自己为订阅者监听器
subscriber.setMessageListener(this);
this.connection = connection;
this.publisher = publisher;
this.pubSession = pubSession;
this.username = username;
connection.start();
}
//接收消息处理事件
public void onMessage(Message message) {
try {
TextMessage textMessage = (TextMessage)message;
System.out.println(username + ": " + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
protected void writeMessage(String text)throws JMSException {
TextMessage msg = pubSession.createTextMessage();
msg.setText(text);
publisher.publish(msg);
}
public void close()throws JMSException{
connection.close();
}
public static void main(String[] args) {
String username = "INI_USERNAME";
try {
if(args.length > 0) {
username = args[0];
}
TopicChat chat = new TopicChat(username);
BufferedReader commandLine = new BufferedReader(new InputStreamReader(System.in));
while(true){
String s = commandLine.readLine();
if(s.equalsIgnoreCase("exit")) {
chat.close();
System.exit(0);
}else{
chat.writeMessage(s);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}