Weblogic Jms簡單使用
目錄
<a href="#_Toc433442170">1 基本用法</a>
<a href="#_Toc433442171">1.1 Jms服務端</a>
<a href="#_Toc433442172">1.1.1 配置Jms伺服器</a>
<a href="#_Toc433442173">1.1.2 配置Jms子產品</a>
<a href="#_Toc433442174">1.2 Jms用戶端</a>
<a href="#_Toc433442175">1.2.1 Jar包導入</a>
<a href="#_Toc433442176">1.2.2 程式開發</a>
<a href="#_Toc433442177">2 整合Spring</a>
<a href="#_Toc433442178">3 參考文檔</a>
對于Weblogic Jms的使用可以分為兩部分,一部分是Weblogic作為服務端釋出對應的Jms服務為用戶端程式提供服務,一部分是我們的應用程式作為用戶端釋出消息到Jms服務端或從Jms服務端擷取消息進行消費。
Weblogic作為Jms服務端提供Jms服務需要在Weblogic的控制台進行一些配置,主要是Jms伺服器和Jms子產品。Jms伺服器作為Jms服務的核心提供Jms服務,也可以說是作為Jms子產品的一個管理容器;Jms子產品下可以進行ConnectionFactory、Topic、Queue等資源的定義,Weblogic允許我們通過JNDI對它們進行通路。
首先我們需要配置一個Jms伺服器。在控制台左邊的域結構下面找到對應的域,進入到服務->消息傳送->Jms伺服器,如下圖所示。

然後在右邊出現的清單點選“建立”按鈕進入建立Jms伺服器的導航頁面,之後根據提示一步一步操作即可。
配置好Jms伺服器後我們需要配置對應的Jms子產品,Jms子產品用來分子產品管理一組資源,一個Jms子產品下可包括ConnectionFactory、Topic、Queue等資源。在控制台左邊的域結構下面,進入到服務->消息傳送->Jms子產品,如下圖所示。
然後在右邊出現的清單中點選“建立”按鈕進入建立Jms子產品的導航界面,之後就根據提示進行操作即可。建立好Jms子產品後,我們可以在Jms子產品清單點選對應Jms子產品的連結到對應Jms子產品下的資源清單頁面,在對應的資源清單頁面,我們點選“建立”按鈕建立對應的資源。
在進行用戶端開發的時候我們首先需要導入對應的jar包。按照Weblogic官網文檔的說明,我們在開發Weblogic Jms用戶端的時候隻需要把wlclient.jar和wljmsclient.jar加入classpath即可。這兩個jar包在Weblogic安裝目錄(WL_HOME)下的server/lib目錄下,如:/home/weblogic/Oracle/Middleware/Oracle_Home/wlserver/server/lib。但是我在開發的時候隻導入這兩個jar包,用戶端程式跑不起來,錯誤資訊是“Root exception is org.omg.CORBA.COMM_FAILURE: vmcid: SUN minor code: 203 completed: No”。而加上wlfullclient.jar則通路正常。wlfullclient.jar預設不在WL_HOME/server/lib目錄下,需要我們在WL_HOME/server/lib目錄下通過運作“java –jar wljarbuilder.jar”來生成,生成後的wljarbuilder.jar非常大,有60多M,可以将裡面一些與工程現有jar包有沖突的類删除。
用戶端程式的開發的時候擷取如ConnectionFactory、Topic、Queue等這些在服務端配置的資源時都需要通過JNDI從服務端擷取。是以我們首先得構造一個擷取JNDI對象的Context。在構造Context時我們需要提供兩個參數,Context.PROVIDER_URL和Context.INITIAL_CONTEXT_FACTORY,這兩個參數都由Weblogic提供,第一個參數表示提供JNDI對象的服務位址,這裡對應的值是“t3://host:port”,host是Weblogic服務主機的IP位址,port是對應的端口;第二個參數是用于擷取InitialContext的InitialContextFactory接口的實作類名稱,對于Weblogic而言,它應當是“weblogic.jndi.WLInitialContextFactory”。這裡我針對它提供了一個工具類,這個工具類的主要作用是把Context封裝起來了,然後提供了對應的根據JNDI名稱擷取對應對象的方法,還封裝了一個ConnectionFactory,提供了擷取Connection的方法。
import java.io.IOException;
import java.util.Hashtable;
import java.util.Properties;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.log4j.Logger;
public class JmsUtil {
private static Context context;
private static final Properties props = new Properties();
private static final ConnectionFactory connectionFactory;
private static final String CONNECTION_FACTORY_JNDI = "weblogic.jms.XAConnectionFactory";
private static final Logger logger = Logger.getLogger(JmsUtil.class);
static {
try {
props.load(JmsUtil.class.getResourceAsStream("jms.properties"));
} catch (IOException e1) {
logger.error("讀取jms.properties配置檔案出錯", e1);
}
Hashtable<String, String> environment = new Hashtable<>();
//指定對應JNDI提供者的位址
environment.put(Context.PROVIDER_URL, props.getProperty(Context.PROVIDER_URL));
//指定擷取InitialContext的InitialContextFactory類
environment.put(Context.INITIAL_CONTEXT_FACTORY, props.getProperty(Context.INITIAL_CONTEXT_FACTORY));
//構造一個擷取JNDI對象的Context
context = new InitialContext(environment);
} catch (NamingException e) {
logger.error("初始化InitialContext失敗", e);
connectionFactory = JmsUtil.lookup(CONNECTION_FACTORY_JNDI);
}
/**
* 擷取Jms連接配接
* @return
*/
public static Connection getConnection() {
returnconnectionFactory.createConnection();
} catch (JMSException e) {
logger.error("建立Connection失敗", e);
returnnull;
* 擷取指定名稱的JNDI對象
* @param name
public static <T> T lookup(String name) {
return (T) context.lookup(name);
logger.error("對應的資源不存在", e);
}
上述所使用到的jms.properties檔案的内容如下。
java.naming.provider.url=t3://10.10.10.3:7001
java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory
具體程式開發的步驟如下。
1、擷取ConnectionFactory
擷取ConnectionFactory的時候可以擷取我們自己定義好的ConnectionFactory,也可以直接擷取Weblogic預先為我們定義好的兩個ConnectionFactory,它們對應的JNDI名稱如下。
· <code>weblogic.jms.ConnectionFactory</code>
· <code>weblogic.jms.XAConnectionFactory</code>
這兩個内置的ConnectionFactory的差別是第二個支援JTA事務,而第一個不支援,隻支援本地事務。
//根據JNDI名稱擷取對應的ConnectionFactory
ConnectionFactory connectionFactory = JmsUtil.lookup("weblogic.jms.XAConnectionFactory");
這裡擷取的ConnectionFactory是一個Weblogic提供的JMSConnectionFactory對象或JMSXAConnectionFactory對象,你可以根據需要将它們強轉為一個QueueConnectionFactory對象或TopicConnectionFactory對象,QueueConnectionFactory和TopicConnectionFactory是Weblogic提供的專門針對為Queue服務和為Topic服務的兩個接口。在下文的步驟中都不會将它們進行類型強轉,而是基于标準的Jms接口進行開發。有興趣的朋友可以檢視Weblogic的Jms文檔或對應的API文檔了解更多内容。
2、擷取Connection
Connection是通過ConnectionFactory進行擷取的。
//通過ConnectionFactory擷取一個Connection
Connection conn = connectionFactory.createConnection();
3、建立一個Session
//第一個參數表示是否需要事務支援,第二個參數表示消息的應答方式
Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
4、擷取目的地
無論我們的程式是作為生産者還是作為消費者,它都需要一個目的地,這個目的地可以是一個Topic,也可以是一個Queue。
//擷取一個目的地,這裡暫時不區分是Topic還是Queue
Destination dest = JmsUtil.lookup("dest_queue");
5、生成者模式
(1)如果我們的用戶端是作為生産者進行消息的生産,那麼我們就需要建立一個對應的生産者。生産者是通過Session進行建立的。
//建立指定目的地的生産者
MessageProducer producer = session.createProducer(dest);
(2)有了生産者之後我們還需要建立對應的需要進行發送的Message,Message是通過Session進行發送的,Message有很多種類型,以下隻是簡單的文本類型的Message。
//建立一個消息
Message message = session.createTextMessage("Hello");
(3)有了Message後我們就可以把它交給生産者進行發送了。
//發送消息
producer.send(message);
6、消費者模式
(1)如果我們的用戶端程式是作為消費者進行消費的,那麼我們首先應該建立一個消費指定目的地Message的消費者。
//建立消費者
MessageConsumer consumer = session.createConsumer(dest);
(2)建立了消費者後就是對消息的消費了,MessageConsumer中定義了好幾個接收消息的方法,不過它們都是一次消費,也就是說調用一次最多隻會消費一條Message,也有不消費的,方法名是以receive打頭的,這裡就不說了有興趣的朋友可以去看一下API文檔。這裡準備介紹的是通過MessageListener進行消費的情形,即給MessageConsumer指定一個MessageListener,這樣一旦有對應的可以進行消費的消息過來後就會自動的回調MessageListener的onMessage方法。
//指定消息監聽器
consumer.setMessageListener(new MessageListener() {
@Override
publicvoid onMessage(Message msg) {
logger.info("收到一條消息: " + msg);
}
});
7、啟動Connection
當我們的用戶端程式是作為消費者時最後需要調用Connection的start方法,這樣我們的Consumer才能接收到對應的資訊,如果什麼時候希望暫停接收資訊,則可以調用對應Connection的stop方法,等到想再次接收Message的時候可以再次調用Connection的start方法。當我們的程式是作為生産者時可以不用調用Connection的start方法。
到此我們的Weblogic Jms用戶端程式開發已經基本完成了,Jms開發的大體思路也都是這樣的。上述内容隻是比較簡單的描述了下服務端的配置和用戶端的開發過程。如果希望進行更深入的了解可以參考Weblogic的官方文檔和Jms相關的API文檔。
Spring整合Jms的文章之前寫過,是基于ActiceMQ寫的,這裡關于Spring整合Jms的内容就不詳細說了,隻是簡單的說一下基于Weblogic的Jms整合Spring時一些不一樣的地方。Weblogic的Jms資源都是通過JNDI擷取的,是以在整合Spring時這些資源也還是需要通過JNDI進行擷取。Spring為我們提供了一個JndiTemplate類,其中封裝了擷取InitialContext的方法,通過它我們可以擷取到指定InitialContext下指定JNDI名稱的對象。Spring還為我們提供了一個JndiObjectFactoryBean類,它實作了FactoryBean接口,通過給它指定一個jndiTemplate和一個jndiName可以讓它傳回指定jndiName在JndiTemplate中對應的對象。是以在整合Spring的時候我們可以通過它們來擷取Weblogic提供的那些Jms對象,其它的就喝Spring整合标準的Jms是一樣的用法了,具體可以參考我之前寫的關于Spring整合JMS的文章。以下是Weblogic Jms整合Spring的一段示例配置。
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${java.naming.factory.initial}</prop>
<prop key="java.naming.provider.url">${java.naming.provider.url}</prop>
</props>
</property>
</bean>
<!-- 提供Jms服務的ConnectionFactory -->
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"
p:jndiTemplate-ref="jndiTemplate" p:jndiName="${jms.jndi.example.connection.factory}" />
<!-- Spring封裝的Jms ConnectionFactory,需要注入一個真正提供Jms服務的ConnectionFactory -->
<bean id="springJmsConnectionFactory"
class="org.springframework.jms.connection.SingleConnectionFactory"
p:targetConnectionFactory-ref="jmsConnectionFactory" />
<bean id="statusQueue" class="org.springframework.jndi.JndiObjectFactoryBean"
p:jndiTemplate-ref="jndiTemplate" p:jndiName="${jms.jndi.example.status.queue}" />
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="springJmsConnectionFactory" />
<!-- Spring提供的消息監聽容器,用以綁定ConnectionFactory、Destination和MessageListener,為指定ConnectionFactory的Destination指定MessageListener -->
<bean id="statusQueueListenerContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer"
p:connectionFactory-ref="springJmsConnectionFactory"
p:destination-ref="statusQueue" p:messageListener-ref="statusMessageListener" />
<!-- 消息監聽器 -->
<bean id="statusMessageListener" class="com.xxx.StatusMessageListener"/>
<a href="/blog/1893038">Spring整合JMS(一)——基于ActiveMQ實作</a>
(注:本文是基于Weblogic12.1.3.0.0和Spring3.0.6所寫)