JMS学习笔记二--入门学习

一. JMS简介

1. JMS基本概念

JMS(Java Message Service)是访问企业消息系统的标准API,它便于消息系
统中的Java应用程序进行消息交换,并且通过提供标准的产生、发送、接收消息的接口简化企业应用的开发。

2. JMS基本功能

JMS是用于和面向消息的中间件相互通信的应用程序接口。它既支持点对点(point-to-point)的域,又支持发布/订阅(publish/subscribe)类型的域,并且提供对下列类型的支持:经认可的消息传递,事务型消息的传递,一致性消息和具有持久性的订阅者支持。JMS还提供了另一种方式来对您的应用与旧的后台系统相集成。
3. WebLogic JMS Server介绍
WebLogic Server8.1符合JAVA规范,并通过Sun Microsystems J2EE 1.3认

证.作为WebLogic的一部分,当然WebLogic JMS Server也完全遵从JMS规范,还支持集群,并可以应用于实际企业系统.下图是WebLogic JMS Server体系结构.图中可以看到WebLogic JMS Server主要组件有: WebLogic JMS servers(用于消息通信),Java客户端,JNDI(用于域名查找), 后备存储(用于持久消息存储,基于文件或者JDBC数据库).


二. WebLogic JMS特性

JMS 支持两种消息通信模型:点到点(point-to-point)(PTP)模型和发布/订阅(Pub/Sub)模型。除了下列不同之外,这两种消息通信模型非常地相似:
PTP 模型规定了一个消息只能有一个接收者;Pub/Sub 模型允许一个消息可以有多个接收者。

1.消息通信模型

JMS支持两种通信模型:点到点(point-to-point)(PTP)模型和发布/订阅(Pub/Sub)模型。除了下列不同之外,这两种通信模型非常地形似:

PTP模型规定了一个消息只能有一个接收者;Pub/Sub模型允许一个消息可以有多个接收者。

2.消息通信模型

消息传递系统的中心就是消息。

一条Message分为三个组成部分:

头(header)是个标准字段集,客户机和供应商都用它标识和路由消息。

属性(property)支持吧可选头字段添加到消息。如果您的应用程序需要不适用标准字段对消息编目和分类,您就可以添加一个属性到消息以实现这个编目和分类,提供 set<Type>Property(...) 和 get<Type>Property(...) 方法以设置和获取各种 Java 类型的属性,包括 Object。JMS定义了一个供应商选择提供的标准属性集。

消息的主体(body)包含要发送的消息给接收应用程序的内容。每个消息接口特定于它所支持的内容类型。

JMS 为不同类型的内容提供了它们各自的消息类型,但是所有消息都派生自 Message 接口。

StreamMessage:包含java基本数值流,用标准流操作来顺序的填充和读取。

MapMessage:包含一组名/值对;名称为string类型,而值为java的基本类型。

TextMessage:包含一个string.

ObjectMessage:包含一个Serializable Java对象;能使用JDK的集合类。

BytesMessage:包含未解释字节流;编码主题以匹配现存的消息格式。

XMLMessage:包含XML内容。扩展TextMessage,XMLMessage类型的使用,使得消息过滤非常的便利。

3.消息通信模型

非事务性绘画中,应用程序创建的绘画有5种确认模式,而在事务性会话中,确认模式被忽略。

五种确认模式说明:

AUTO_ACKNOWLEDGE:自动确认模式。一旦接受方应用程序的方法调用从处理消息出返回,绘画独享会确认消息的接收。

CLIENT_ACKNOWLEDAGE:客户端确认模式。会话对象依赖于应用程序对被接受的消息调用一个acknowledge()方法。一旦这个方法被调用,会话会确认最后一次确认之后所接收到的消息。这种模式允许应用程序以一个调用来接收,处理并确认一批消息。注意:在管理控制台中,如果连接工厂的Acknowledge Policy(确认方针)属性被设置为"Previous"(提前),但是你希望为一个给定的绘画确认所有接收到的消息,那么就用最后一条消息来调用acknowledge()方法。

DUPS_OK_ACKNOWLEDGE:允许副本的确认模式。一旦接收方应用程序的方法调用从处理消息处返回,会话对象就会确认消息的接收;而且允许重复确认。在需要考虑资源使用时,这种模式非常有效。注意:如果你的应用程序无法处理重复的消息的话,你应该使用这种模式。如果发送消息的初始化尝试失败,那么重复的消息可以不被重新发送。

NO_ACKNOWLEDGE:不确认模式。不确认收到的消息是需要的。消息发送给一个NO_ACKNOWLEDGE会话后,它们会被WebLogic服务器立即删除。在这种模式下,将无法重新获得已接收的消息,而且可能导致下面的接收:1.消息可能丢失;和(或者)另一种情况;2.如果发送消息的初始化尝试失败,那么重复的消息可以被重新发送。

MULTICAST_NO_ACKNOWLEDGE:IP组播下的不确认模式,同样无需确认。发送给一个MULTICAST_NO_ACKNOWLEDGE会话的消息,会共享之前所述的NO_ACKNOLEDGE确认模式一样的特征。这种模式支持希望通过IP组播方式进行消息通信的应用程序,而且无需依赖于会话确认提供的服务质量。注意:如果你的应用程序无法处理消息的丢失或者重复,那么你应该避免使用这种模式。如果发送消息的初始化尝试失败的话,重复的消息可能会被再次发送。

注:在上表的5种确认模式中,AUTO_ACKNOLEDGE,DUPS_OK_ACKNOWLEDGE和CLIENT_ACKNOWLEDGE是JMS规范定义的,NO_ACKNOWLEDGE和MULTICAST_NO_ACKNOWLEDGE是WebLogic JMS提供的。

二. WebLogic JMS特性

1.创建连接工厂

(1)启动Weblogical Server9.1,登陆控制台,选中JMS Connection Factories节点,点击右边的'"Configure a new JMS Connection Factory...";

(2)填写连接工厂的名称SendJMSFactory和JNDI名称SendJMSFactory,点击“Create”;

(3)勾上"myserver",将SendJMSFactory应用到myserver;

2.定义后背存储

(1)选中JMS Stores节点,点击右边的“Configure a new JMS Connection Factory...

(2)填写文件后备存储的名称SendFileStore和目录Directory E:\BEA\user_projects\domains\mydomain\sendfilestore,点击“Create”

3.创建JMS服务器

(1)选中JMS Server节点,点击右边的'"Configure a new JMSServer.."

(2)填写JMS服务器的名称SendJMSServer和Paging Store设为“SendFileStore”,点击“Create”;

(3)Target选中'"myserver“,将SendJMSServer应用到myserver

4.创建消息队列

(1) 展开"SendJMSServer"节点,点击" Configure a new JMS Queue...";

(2) 填写消息队列的名称SendJMSQueue和JNDI名称SendJMSQueue,点击"Create";


四. JMS应用程序

一个JMS应用程序由下列元素组成;

JMS客户机。用JMS API发送和接收消息的Java程序。

非JMS(Non-JMS)客户机。认识到这一点很重要-旧的程序经常成为整个JMS应用程序的一部分,而且它们的包含应该在设计时预先考虑。

JMS供应商。供应商必须提供特定于其MOM产品的具体的实现。

收管对象。消息传递系统供应商的管理员创建了一个对象,它独立于供应商专有的技术。包括连接工厂ConnectionFactory和目的Destination.


一种典型的JMS程序需要经过下列步骤才能开始消息产生和使用:

通过JNDI查找ConnectionFactory.

通过JNDI查找一个或多个Destination.

用ConnetionFactory创建一个Connection.

用Connection创建一个活多个Session.

用Session和Destination创建所需要的MessageProducer和MessageConsumer.

启动connection.


下面利用上面配置的JMS资源演示点对点消息发送和接收的过程。

五. 设计消息发送端

1.使用的JMS资源

服务器URL:t3://localhost:80

连接工厂:SendJMSFactory

队列:SendJMSQueue

2.设计步骤

//初始化JNDI Tree
Hashtable env = new Hashtable();
env.put(Context.INTIAL_CONTEXT_FACTORY,JNDI_FACTORY);
env.put(Context.PROVIDER_RUL,PROVIDER_RUL);
return new InitialContext();

//lookup ConnectionFactory
qconFactory = (QueueConnectionFactory)ctx.lookup(JMS_FACTORY);

//lookup Destination
queue = (Queue)ctx.lookup(queueName); 

//用ConnectionFactory创建Connection
qcon = qconFactory.createQueueConnection();

//用Connection 创建一个Session
qsession = qcon.createQueueSession(false,Session,AUTO_ACKNOWLEDGE);

//用Session和Destination创建MessageProducer
qsender = qsession.createSender(queue);

//启动Connection
qcon.start();

//发送消息 
msg = qsession.createTextMessage(); 
msg.setText(message); 
qsender.send(msg);

3.源码

package jmssample;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * this example shows how to establish a connection and send message to the JMS queue.
 * The classes in this package operate on the same JMS queue,Run the classes together
 * to witness messages being sent and received,and to browse the queue for message.
 * The class is used to send message to the queue
 * @author 我的账号
 *
 */
public class QueueSend {
	//Defines the JNDI context factory
	public final static String JNDI_FACTORY = "weblogic.jndi.WLinitialContextFactory";
	
	//Defines the JNDI provider url
	public final static String PROVIDER_URL ="t3://localhost:80";
	
	//Defines the JMS connection factory for the queue
	public final static String JMS_FACTORY = "SendJMSFactory";
	
	//Defines the queue
	public final static String QUEUE = "SendJMSQueue";
	
	private QueueConnectionFactory qconFactory;
	private QueueConnection qcon;
	private QueueSession qsession;
	private QueueSender qsender;
	private Queue queue;
	private TextMessage msg;
	
	/**
	 * Create all the necessary objects for sending
	 * message to a JMS queue
	 * 
	 * @param ctx JNDI initial context
	 * @param queueName name for queue
	 */
	public void init(Context ctx,String queueName) throws NamingException,JMSException{
		qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
		qcon = qconFactory.createQueueConnection();
		qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
		queue = (Queue) ctx.lookup(queueName);
		qsender = qsession.createSender(queue);
		msg = qsession.createTextMessage();
		qcon.start();
	}	
	
	/**
	 * send a message to a JMS queue
	 * @param message message to be sent
	 * @throws JMSException 
	 */
	public void send(String message) throws JMSException{
		msg.setText(message);
		qsender.send(msg);
		
	}
	
	/**
	 * Closes JMS object
	 * @throws JMSException
	 */
	public void close() throws JMSException{
		qsender.close();
		qsession.close();
		qcon.close();
		
	}
	
	/**
	 * main 
	 * @param args WebLogic Server URL
	 * @throws JMSException 
	 * @throws NamingException 
	 * @throws IOException 
	 */
	public static void main(String[] args) throws NamingException, JMSException, IOException {
		InitialContext ic = getInitialContext();
		QueueSend qs = new QueueSend();
		qs.init(ic, QUEUE);
		readAndSend(qs);
		qs.close();
	}
	
	private static void readAndSend(QueueSend qs) throws IOException,JMSException{
		BufferedReader msgStream = new BufferedReader(new InputStreamReader(System.in));
		
		String line = null;
		boolean quitNow = false;
		do{
			System.out.println("Enter message(\"quit to quit):");
			line = msgStream.readLine();
			if(line != null &&line.trim().length() != 0){
				qs.send(line);
				System.out.println("JMS Message sent:"+line+"\n");
				quitNow = line.equalsIgnoreCase("quit");
			}
		}while(!quitNow);
		
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static InitialContext getInitialContext() throws NamingException{
		Hashtable env = new Hashtable();
		env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
		env.put(Context.PROVIDER_URL, PROVIDER_URL);
		
		return new InitialContext(env);
		
	}
}


六. 设计消息接收端

1. 使用的JMS资源

服务器URL: t3://localhost:80
连接工厂: SendJMSFactory
队列: SendJMSQueue

2. 设计步骤

初始化JNDI Tree
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
env.put(Context.PROVIDER_URL, PROVIDER_URL);
return new InitialContext(env);
lookup ConnectionFactory
qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
lookup Destination
queue = (Queue) ctx.lookup(queueName);
用 ConnectionFactory 创建Connection
qcon = qconFactory.createQueueConnection();
用 Connection 创建一个Session
qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
用 Session 和 Destination 创建MessageConsumer
qreceiver = qsession.createReceiver(queue);
设置监听
qreceiver.setMessageListener(this);
启动 Connection
qcon.start();

3. 源代码

package jmssample;

import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * this example shows how to establish a connnetion to and receive messages from a 	JMS queue.
 * the classes in this package operator on  the same JMS queue.Run the classes together
 * to witness messages being sent and received,and to browse the queue form messages.
 * this class is used to receive and remove messages fromm the queue. 
 * @author 我的账号
 *
 */
public class QueueReceive implements MessageListener{
	
	//defines the JNDI context factory
	public final static String JNDI_FACTORY = "weblogic.jdni.WLInitialContextFactory";
	
	//defines the JNDI provider url
	public final static String PROVIDER_RUL = "t3://localhost:80";
	
	// Defines the JMS connection factory for the queue.
	public final static String JMS_FACTORY="SendJMSFactory"; 
	
	//defines the JMS connection factory for the queue
	public final static String QUEUE = "SendJMSQueue";
	
	private QueueConnectionFactory qconFactory;
	private QueueConnection qcon;
	private QueueSession qsession;
	private QueueReceiver qreceiver;
	private Queue queue;
	private boolean quit = false;
	
	@Override
	public void onMessage(Message msg) {
		try {
			String msgText;
			if(msg instanceof TextMessage){
				msgText = ((TextMessage)msg).getText();
				
			}else{
				msgText = msg.toString();
			}
			
			System.out.println("Message Received:"+ msgText);
			
			if(msgText.equalsIgnoreCase("quit")){
				synchronized(this){
					quit = true;
					this.notifyAll();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * create all the necessary objects for receiving messages from JMS queue
	 * @param ctx JNDI initial context
	 * @param queueName name of quue
	 * @throws NamingException 
	 * @throws JMSException 
	 */
	public void init(Context ctx,String queueName) throws NamingException, JMSException{
		qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
		qcon = qconFactory.createQueueConnection();
		qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
		queue = (Queue) ctx.lookup(queueName);
		qreceiver = qsession.createReceiver(queue);
		qreceiver.setMessageListener(this);
		qcon.start();
	}
	
	/**
	 * Closes JMS objects
	 */
	public void close() throws JMSException{
		qreceiver.close();
		qsession.close();
		qcon.close();
	}
	
	/**
	 * 
	 * @param args Weblogic Server URl
	 * @throws JMSException 
	 * @throws NamingException 
	 */
	public static void main(String[] args) throws JMSException, NamingException {
		InitialContext ic = getInitialContext();
		QueueReceive qr = new QueueReceive();
		qr.init(ic, QUEUE);
		
		System.out.println("JMS Ready To Receive Message(To quit,send a \"qui\" message)");
		
		
		//wait until a "quit" message has been received
		synchronized (qr) {
			while(! qr.quit){
				try {
					qr.wait();
				} catch (Exception e) {
					
				}finally{
					qr.close();
				}
			}
		}
	}
	
	@SuppressWarnings({"rawtypes","unchecked"})
	private static InitialContext getInitialContext() throws NamingException{
		
		Hashtable env = new Hashtable();
		env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
		env.put(Context.PROVIDER_URL, PROVIDER_RUL);
		
		return new InitialContext(env);
	}
}



七. 测试消息发送和接收

1. 设置WebLogic Classpath;


2. 转到发送接收程序目录编译文件;


3. 执行接受程序;

4. 打开另一窗口,执行发送程序;

5. 输入发送消息"quit",接收程序结束.




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值