JMS (1)
開發任何JMS應用之前,首先要做的事是在應用服務器中配置JMS被管對象:連接工廠和目的地。它們最好不要以編程的方式實現,因為其背后的技術有多種不同的API實現,可能無法移植。以下是glassfish中的配置:
在配置--java消息服務里創建兩個物理目的地
名稱:myQueue
類型:javax.jms.Queue
名稱:myTopic
類型:javax.jms.Topic
在資源--jms資源里創建連接工廠
JNIDI名:jms/ConnectionFactory
資源類型:javax.jms.ConnectionFactory
在資源--jms資源里創建兩個目的地資源
JNIDI名:jms/Queue
資源類型:javax.jms.Queue
JNIDI名:jms/Topic
資源類型:javax.jms.Topic
這一次創建一個最簡單的同步隊列消息應用,創建一個EJB模塊,我們先創建發送消息的會話bean,首先定義遠程接口:






遠程接口向遠程客戶端公開了一個發送消息的方法,然后是一個無狀態會話bean實現遠程接口:
1
@Stateless
2
public class JMSSendBean implements JMSSendRemote {
3
@Resource(name = "jms/Queue")
4
private Queue queue;
5
@Resource(name = "jms/ConnectionFactory")
6
private ConnectionFactory connectionFactory;
7
8
private Message createJMSMessageForjmsQueue(Session session, Object messageData) throws JMSException {
9
TextMessage message = session.createTextMessage();
10
message.setText(messageData.toString());
11
return message;
12
}
13
14
private void sendJMSMessageToQueue(Object messageData) throws JMSException {
15
Connection connection = null;
16
Session session = null;
17
try {
18
connection = connectionFactory.createConnection();
19
session = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
20
MessageProducer messageProducer = session.createProducer(queue);
21
messageProducer.send(createJMSMessageForjmsQueue(session, messageData));
22
} finally {
23
if (session != null) {
24
session.close();
25
}
26
if (connection != null) {
27
connection.close();
28
}
29
}
30
}
31
32
public void sendMessage(Object messageData) {
33
try {
34
sendJMSMessageToQueue(messageData);
35
} catch (JMSException ex) {
36
Logger.getLogger(JMSSendBean.class.getName()).log(Level.SEVERE, null, ex);
37
}
38
}
39
40
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

前6行聲明了連接工廠和隊列,并將被管對象注入其中。SessionFactory用來在消息客戶端和消息服務器之間創建一個連接;Queue是一個目的地,另一個是Topic,都是Destination(目的地)的子類,消息生成者將消息發送到目的地而消息使用者在目的地上獲取消息。15-16行聲明了Connection和Session兩個對象,Connection在消息客戶端和消息服務器相關端口上建立TCP/IP套接字,用來創建一個或多個Session;Session是一個單線程的上下文,用來生成和使用消息。18行創建一個Connection對象,19行創建一個一個Session對象,第一個參數表明Session未被事務化,第二個參數表明會話能夠在成功接收到消息時自動進行確認。MessageProducer是消息生成者,需要指定一個目的地。9行的TextMessage代表消息本身,Message有6個子類,TextMessage只是其中一種。10行設置了消息的正文,21行消息生成者將消息發送到目的地,最后在23-28行將Connection關閉,關閉連接會自動關閉會話和消息生成者,至此整個發送流程結束。
接下來創建接收消息的會話bean,還是先創建遠程接口:






向遠程客戶端公開了一個接收方法,我們看會話bean如何實現:
1
@Stateless
2
public class JMSReceiveBean implements JMSReceiveRemote {
3
@Resource(name = "jms/Queue")
4
private Queue queue;
5
@Resource(name = "jms/ConnectionFactory")
6
private ConnectionFactory queueFactory;
7
8
private String receiveJMSMessageFromQueue() throws JMSException {
9
Connection connection = null;
10
Session session = null;
11
try {
12
connection = queueFactory.createConnection();
13
session = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE);
14
MessageConsumer consumer = session.createConsumer(queue);
15
connection.start();
16
TextMessage msg = (TextMessage)consumer.receive();
17
return msg.getText();
18
} finally {
19
if (session != null) {
20
session.close();
21
}
22
if (connection != null) {
23
connection.close();
24
}
25
}
26
}
27
28
public String receiveMessage() {
29
try {
30
return receiveJMSMessageFromQueue();
31
} catch (JMSException ex) {
32
Logger.getLogger(JMSReceiveBean.class.getName()).log(Level.SEVERE, null, ex);
33
}
34
return null;
35
}
36
37
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

很多重復的地方不解釋了,14行創建了一個MessageConsumer對象,代表一個消息使用者。在接收消息前始終要打開一個連接,15行正是這個意思。16行consumer.receive()方法從目的地接收消息,receive方法用于執行一個同步接收過程,若不指定參數或參數為0,則在某個消息到來之前方法會一直阻塞,大于0的值代表設定阻塞時長毫秒數。17行從消息中獲取正文,19-23行關閉連接,關閉Connection對象將自動關閉會話和消息使用者,至此整個接收流程結束,打包部署EJB模塊。
最后創建遠程客戶端來進行測試:















