? WebLogic JMSҎ(gu)?/strong>
1. 消息通信模型
JMS 支持两种消息通信模型Q点到点Qpoint-to-pointQ(PTPQ模型和发布/订阅QPub/SubQ模型。除了下列不同之外,q两U消息通信模型非常地相|(x)
PTP 模型规定了一个消息只能有一个接收?Pub/Sub 模型允许一个消息可以有多个接收者?br />
2. 消息l成
消息传递系l的中心?yu)是消息?br />
一?Message 分ؓ(f)三个l成部分Q?
· _(d)headerQ是个标准字D集Q客h和供应商都用它来标识和\由消息?br />
· 属性(propertyQ支持把可选头字段d到消息。如果?zhn)的应用程序需要不使用标准头字D对消息~目和分c,(zhn)就可以d一个属性到消息以实现这个编目和分类。提?set<Type>Property(...) ?get<Type>Property(...) Ҏ(gu)以设|和获取各种 Java cd的属性,包括 Object。JMS 定义了一个供应商选择提供的标准属性集?br />
· 消息的主体(bodyQ包含要发送给接收应用E序的内宏V每个消息接口特定于它所支持的内容类型?
JMS Z同类型的内容提供了它们各自的消息cdQ但是所有消息都z?Message 接口?br />
· StreamMessageQ包?Java 基本数值流Q用标准操作来序的填充和d?br />
· MapMessageQ包含一l名/值对Q名UCؓ(f) string cdQ而gؓ(f) Java 的基本类型?br />
· TextMessageQ包含一?String?br />
· ObjectMessageQ包含一?Serializable Java 对象Q能使用 JDK 的集合类?br />
· BytesMessageQ包含未解释字节? ~码M以匹配现存的消息格式?br />
· XMLMessage: 包含XML内容。扩展TextMessage,XMLMessage cd的用,使得消息qo(h)非常便利?br />
3. 消息认模式
非事务性会(x)话中Q应用程序创建的?x)话? U确认模?而在事务性会(x)话中Q确认模式被忽略?br />
五种认模式说明:
· AUTO_ACKNOWLEDGEQ自动确认模式。一旦接收方应用E序的方法调用从处理消息处返回,?x)话对象׃?x)认消息的接收?br />
· CLIENT_ACKNOWLEDGEQ客L(fng)认模式。会(x)话对象依赖于应用E序对被接收的消息调用一个acknowledge()Ҏ(gu)。一旦这个方法被调用Q会(x)话会(x)认最后一ơ确认之后所有接收到的消息。这U模式允许应用程序以一个调用来接收Q处理ƈ认一Ҏ(gu)息。注意:(x)在管理控制台中,如果q接工厂的Acknowledge PolicyQ确认方针)属性被讄?Previous"Q提前)Q但是你希望Z个给定的?x)话认所有接收到的消息,那么q最后一条消息来调用acknowledge()Ҏ(gu)?br />
· DUPS_OK_ACKNOWLEDGEQ允许副本的认模式。一旦接收方应用E序的方法调用从处理消息处返回,?x)话对象׃?x)认消息的接Ӟ而且允许重复认。在需要考虑资源使用Ӟq种模式非常有效。注意:(x)如果你的应用E序无法处理重复的消息的话,你应该避免用这U模式。如果发送消息的初始化尝试失败,那么重复的消息可以被重新发送?br />
· NO_ACKNOWLEDGEQ不认模式。不认收到的消息是需要的。消息发送给一个NO_ACKNOWLEDGE ?x)话后,它们会(x)被WebLogic 服务器立卛_除。在q种模式下,无法重新获得已接收的消息,而且可能D下面的结果:(x)1. 消息可能丢失Q和Q或者)另一U情况:(x)2. 如果发送消息的初始化尝试失败,?x)出现重复消息被发送的情况?br />
· MULTICAST_NO_ACKNOWLEDGEQIPl播下的不确认模式,同样无需认。发送给一个MULTICAST_NO_ACKNOWLEDGE?x)话的消息??x)共享之前所q的NO_ACKNOWLEDGE 认模式一L(fng)特征。这U模式支持希望通过IP l播方式q行消息通信的应用程序,而且无需依赖?x)话认提供的服务质量。注意:(x)如果你的应用E序无法处理消息的丢失或者重复,那么你应该避免用这U模式。如果发送消息的初始化尝试失败的话,重复的消息可能会(x)被再ơ发送?br />
注:(x)在上表的5 U确认模式中QAUTO_ACKNOWLEDGE QDUPS_OK_ACKNOWLEDGE ?br />
CLIENT_ACKNOWLEDGE 是JMS 规范定义的,NO_ACKNOWLEDGE 和MULTICAST_NO_ACKNOWLEDGE是WebLogic JMS 提供的?br />
? 配置JMS
1. 创徏q接工厂
(1) 启动WebLogic Server8.1,d控制?选中JMS Connection Factories节点,点击双? Configure a new JMS Connection Factory...";

(2) 填写q接工厂的名USendJMSFactory和JNDI名称SendJMSFactory,点击"Create";

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

2. 定义后备存储
(1) 选中JMS Stores节点,点击双? Configure a new JMS Connection Factory...";

(2) 填写文g后备存储的名USendFileStore和目录Directionary E:\BEA\user_projects\domains\mydomain\sendfilestore,点击"Create".

3. 创徏JMS服务?br />
(1) 选中JMS Servers节点,点击双? Configure a new JMSServer...";

(2) 填写JMS服务器的名称SendJMSServer和Paging Store设ؓ(f)" SendFileStore",点击"Create";

(3) Target选中"myserver",SendJMSServer应用到myserver.

4. 创徏消息队列
(1) 展开"SendJMSServer"节点,点击" Configure a new JMS Queue...";

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

? JMS应用E序
一?JMS 应用E序׃列元素组成:(x)
· JMS 客户机??JMS API 发送和接收消息?Java E序?br />
· ?JMSQNon-JMSQ客h?认识到这一点很重要 - 旧的E序l常成ؓ(f)整个 JMS 应用E序的一部分Q而且它们的包含应该在设计旉先考虑?br />
· 消息??JMS 和非 JMS 客户Z间交换的消息的格式和内容?JMS 应用E序设计所必须考虑的部分?br />
· JMS 供应商。供应商必须提供特定于其 MOM 产品的具体的实现?br />
· 受管对象?消息传递系l供应商的管理员创徏了一个对象,它独立于供应商专有的技术。包括连接工厂ConnectionFactory和目的Destination?br />
一U典型的 JMS E序需要经q下列步骤才能开始消息生和使用:
· 通过 JNDI 查找 ConnectionFactory?br />
· 通过 JNDI 查找一个或多个 Destination?
· ?ConnectionFactory 创徏一?Connection?
· ?Connection 创徏一个或多个 Session?
· ?Session ?Destination 创徏所需?MessageProducer ?MessageConsumer?
· 启动 Connection?
下面利用上面配置的JMS资源演示点对Ҏ(gu)息发送和接收的过E?br />
? 设计消息发送端
1. 使用的JMS资源
服务器URL: t3://localhost:80
q接工厂: 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 创徏MessageProducer
qsender = qsession.createSender(queue);
· 启动 Connection?br />
qcon.start();
· 发送消?br />
msg = qsession.createTextMessage();
msg.setText(message);
qsender.send(msg);
3. 源代?br />
package jmssample;
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/** This example shows how to establish a connection
* and send messages 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 messages. The class is used to send messages to the queue.
*
* @author Copyright (c) 1999-2003 by BEA Systems, Inc. All Rights Reserved.
*/
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;
/**
* Creates all the necessary objects for sending
* messages to a JMS queue.
*
* @param ctx JNDI initial context
* @param queueName name of queue
* @exception NamingException if operation cannot be performed
* @exception JMSException if JMS fails to initialize due to internal error
*/
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();
}
/**
* Sends a message to a JMS queue.
*
* @param message message to be sent
* @exception JMSException if JMS fails to send message due to internal error
*/
public void send(String message) throws JMSException {
msg.setText(message);
qsender.send(msg);
}
/**
* Closes JMS objects.
* @exception JMSException if JMS fails to close objects due to internal error
*/
public void close() throws JMSException {
qsender.close();
qsession.close();
qcon.close();
}
/** main() method.
*
* @param args WebLogic Server URL
* @exception Exception if operation fails
*/
public static void main(String[] args) throws Exception {
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.print("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);
}
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);
}
}
? 设计消息接收?br />
1. 使用的JMS资源
服务器URL: t3://localhost:80
q接工厂: 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. 源代?br />
package jmssample;
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* This example shows how to establish a connection to
* and receive messages from a 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 messages. This class is used to receive and remove messages
* from the queue.
*
* @author Copyright (c) 1999-2003 by BEA Systems, Inc. All Rights Reserved.
*/
public class QueueReceive implements MessageListener
{
// 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 QueueReceiver qreceiver;
private Queue queue;
private boolean quit = false;
/**
* Message listener interface.
* @param msg message
*/
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(); // Notify main thread to quit
}
}
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}
/**
* Creates all the necessary objects for receiving
* messages from a JMS queue.
*
* @param ctx JNDI initial context
* @param queueName name of queue
* @exception NamingException if operation cannot be performed
* @exception JMSException if JMS fails to initialize due to internal error
*/
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.
* @exception JMSException if JMS fails to close objects due to internal error
*/
public void close()throws JMSException
{
qreceiver.close();
qsession.close();
qcon.close();
}
/**
* main() method.
*
* @param args WebLogic Server URL
* @exception Exception if execution fails
*/
public static void main(String[] args) throws Exception {
InitialContext ic = getInitialContext();
QueueReceive qr = new QueueReceive();
qr.init(ic, QUEUE);
System.out.println("JMS Ready To Receive Messages (To quit, send a \"quit\" message).");
// Wait until a "quit" message has been received.
synchronized(qr) {
while (! qr.quit) {
try {
qr.wait();
} catch (InterruptedException ie) {}
}
}
qr.close();
}
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. 讄WebLogic Classpath;
2. 转到发送接收程序目录编译文?

3. 执行接受E序;
4. 打开另一H口,执行发送程?

5. 输入发送消?quit",接收E序l束.

ȝ
本文先简要介l了JMS的一些基本概?l而引入了WebLogic JMS Server的体pȝ构和相关Ҏ(gu)。在此基之上,图文q茂地讲qCJMS在WebLogic Server 8.1上的配置。最后在解剖JMS应用E序框架的同?以点对点Z演示了JMS的发送接收消息流E?nbsp;