最近通过网上查询各中资料,简单学习了下JMS。对于原理,现在处于学习阶段,未完全融会贯通,本期先只提供简单实例源码和weblogic部署方法。希望能通过简单实例来完成JMS学习的入门。
环境:eclipse + weblogic 816
简介:部署发送端和接收端两个服务应用,发送端部署web应用并搭建JMS环境,JMS的相关jndi信息与代码中的一致。接收端应用,通过监听来自动接收发送端的消息。
注意:接收端服务必须在发送端服务启动之后才能正常使用。如果发送端重启了,服务端也必须重启。
一、JMS发送端
1、发送端应用工程搭建
(1)、发送端class编写:QueueSend类(主要参考网上相关源码)
package inspur.tax.wlkp.jms;
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;
/**
* 一种典型的 JMS 程序需要经过下列步骤才能开始消息产生和使用:
· 通过 JNDI 查找 ConnectionFactory。
· 通过 JNDI 查找一个或多个 Destination。
· 用 ConnectionFactory 创建一个 Connection。
· 用 Connection 创建一个或多个 Session。
· 用 Session 和 Destination 创建所需的 MessageProducer 和 MessageConsumer。
· 启动 Connection。
*/
public class QueueSend {
/**
* 定义JNDI上下文构造器
*/
public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";
/**
* 服务URL(weblogic部署的地址)
*/
public final static String PROVIDER_URL = "t3://127.0.0.1:20001";
/**
* 定义JMS上下文构造器(weblogic中部署时录入)
*/
public final static String JMS_FACTORY = "HanJMSFactory";
/**
* 定义消息列队(weblogic中部署时录入)
*/
public final static String QUEUE = "HanJMSQueue";
//声明队列连接构造器
private QueueConnectionFactory qconFactory;
//声明队列连接
private QueueConnection qcon;
// 声明队列会话
private QueueSession qsession;
// 声明队列发送
private QueueSender qsender;
//声明队列
private Queue queue;
//声明发送对象
/**
JMS 为不同类型的内容提供了它们各自的消息类型,但是所有消息都派生自 Message 接口
* StreamMessage:包含 Java 基本数值流,用标准流操作来顺序的填充和读取。
* MapMessage:包含一组名/值对;名称为 string 类型,而值为 Java 的基本类型。
* TextMessage:包含一个 String。
* ObjectMessage:包含一个 Serializable Java 对象;能使用 JDK 的集合类。
* BytesMessage:包含未解释字节流: 编码主体以匹配现存的消息格式。
* XMLMessage: 包含XML内容。扩展TextMessage,XMLMessage 类型的使用,使得消息过滤非常便利。
*/
private TextMessage msg;//本事例使用TextMessage
/**
* JMS消息的产生和使用
* @param mes 消息内容
*/
public void sendJmsQueue(String mes) throws Exception
{
InitialContext ic = getInitialContext();
QueueSend qs = new QueueSend();
qs.init(ic);
qs.send(mes);
qs.close();
}
/**
* 1、
* 通过 JNDI 查找 ConnectionFactory。
* 通过 JNDI 查找一个或多个 Destination。
*/
private 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);
}
/**
* 2、
* 用 ConnectionFactory 创建一个 Connection。
* 用 Connection 创建一个或多个 Session。
*· 用 Session 和 Destination 创建所需的 MessageProducer 和 MessageConsumer。
*· 启动 Connection。
*/
public void init(Context ctx) throws NamingException,JMSException {
qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);
qcon = qconFactory.createQueueConnection();
qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queue = (Queue) ctx.lookup(QUEUE);
qsender = qsession.createSender(queue);
msg = qsession.createTextMessage();
qcon.start();
}
/**
* 3、
* 消息发送
*/
public void send(String message) throws JMSException {
System.out.println("发送消息内容:"+message);
msg.setText(message);
qsender.send(msg);
}
/**
* 4、消息对象关闭
*/
public void close() throws JMSException {
qsender.close();
qsession.close();
qcon.close();
}
}
(2)、编写servlet:JmsSendServlet,来获取消息来源并调用发送消息方法sendJmsQueue()
package inspur.tax.wlkp.jms;
import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 通过Servlet访问的形式测试JMS消息发送
*/
public class JmsSendServlet extends HttpServlet {
private static final long serialVersionUID = -2497039803446390738L;
/**
*
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
OutputStreamWriter wr = null;
String mes = request.getParameter("msg")==null?"JMS测试默认信息":request.getParameter("msg").toString();
try {
wr = new OutputStreamWriter(response.getOutputStream());//
QueueSend qs = new QueueSend();//创建自定义的消息发送对象
qs.sendJmsQueue(mes);//消息发送
wr.write("ok");//消息发送成功
wr.flush();
wr.close();
} catch (Exception e) {
wr.write("error");//消息发送失败
wr.flush();
wr.close();
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doGet(req, resp);
}
}
(3)、在Web.xml中对JmsSendServlet进行配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置JMS servlet -->
<servlet>
<servlet-name>JmsSendServlet</servlet-name>
<servlet-class>inspur.tax.wlkp.jms.JmsSendServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JmsSendServlet</servlet-name>
<url-pattern>/jmsSend.do</url-pattern>
</servlet-mapping>
</web-app>
2、发送端应用工程部署
(1)、weblogic建域。端口设置为20001,与代码中URL一致。(略)
(2)、单击“Web Application Modules”,进行应用部署。默认对应的应用部署完成是myserver。
(3)、部署完成应用后,进行JMS配置。
1 创建连接工厂
1.1 单击JMS Connection Factories,如下图
1.2 进入以下界面后,单击" Configure anew JMS Connection Factory...";
1.3 进入以下界面后,填写连接工厂的名称HanJMSFactory(可以自定义)和JNDI名称“HanJMSFactory”,(JNDI名称必须与QueueSend代码中JNDI_FACTORY值一致)点击"Create";
1.4 勾上"myserver",将HanJMSFactory应用到myserver,单击Apply;
2 定义后备存储
2.1单击Store
2.2单击“ Configure a new JMS File Store..."”
2.3填写文件后备存储的名称HanFileStore和目录DirectionaryE:\BEA\user_projects\domains\mydomain\sendfilestore,点击"Create".(此目录在domain相应路径下自定义创建一个即可)
3. 创建JMS服务器
3.1 单击servers
3.2单击 Configure a new JMSServer...
3.3填写JMS服务器的名称HanJMSServer(可自定义)和Paging Store设为"HanFileStore",点击"Create";
3.4Target选中"myserver",将HanJMSServer应用到myserver.单击apply.
4. 创建消息队列
4.1 单击下图左边目录中的Destinations,进入下图。单击“Configure a new JMS Queue....”
4.2 录入队列name和JNDI Name:"HanJMSQueue,单击create
3、发送端应用测试
重启服务。IE访问http://127.0.0.1:20001/jmsSend/jmsSend.do?msg=Kaven198782
发送端后台信息输出:“发送消息内容:Kaven19870802”
二、JMS接收端
1、接收端应用工程搭建。(接收端测试,通过设置监听的形式,自动接收发送端消息。)
消息接收class:QueueReceive代码
package inspur.tax.wlkp.jms;
import java.util.Hashtable;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* JMS消息接收
*/
public class QueueReceive implements MessageListener {
public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";//与发送端应用配置一致
public final static String PROVIDER_URL="t3://127.0.0.1:20001";//发送端URL
public final static String JMS_FACTORY="HanJMSFactory";//与发送端应用配置一致
public final static String QUEUE="HanJMSQueue";//与发送端应用配置一致
private QueueConnectionFactory qconFactory;
private QueueConnection qcon;
private QueueSession qsession;
private QueueReceiver qreceiver;
private Queue queue;
// private boolean quit = false;
/**
* 入口方法
*/
public static void receiveMsg() throws Exception {
InitialContext ic = getInitialContext();
QueueReceive qr = new QueueReceive();
qr.init(ic, QUEUE);
// // 当收到"quit"信息后,停止接收
// synchronized(qr) {
// while (! qr.quit) {
// try {
// qr.wait();
// } catch (InterruptedException ie){
//
// }
// }
// }
// qr.close();
}
/**
* 1、
* 通过 JNDI 查找 ConnectionFactory。
* 通过 JNDI 查找一个或多个 Destination。
*/
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);
}
/**
* 2、
* 用 ConnectionFactory 创建一个 Connection。
* 用 Connection 创建一个或多个 Session。
*· 用 Session 和 Destination 创建所需的 MessageProducer 和 MessageConsumer。
*· 启动 Connection。
*/
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();
}
/**
·* 消息接收
* 可附加相应的业务处理
·*/
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 );
// // 当收到"quit"信息后,停止接收
// if (msgText.equalsIgnoreCase("quit")) {
// synchronized(this) {
// quit = true;
// this.notifyAll();
// }
// }
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}
/**
* 4、消息对象关闭
*/
public void close()throws JMSException {
qreceiver.close();
qsession.close();
qcon.close();
}
}
监听代码:
package inspur.tax.wlkp.jms;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* 使用监听自动接收JMS消息
*/
public class ContextListener implements ServletContextListener {
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("====接收JMS信息程序关闭=====");
}
//监听执行
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("====接收JMS信息程序启动=====");
try {
QueueReceive.receiveMsg();
} catch (Exception e) {
e.printStackTrace();
}
}
}
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置监听,自动接收JMS消息 -->
<listener>
<listener-class>inspur.tax.wlkp.jms.ContextListener</listener-class>
</listener>
</web-app>
2、接收端应用部署
按照普通web应用部署的方法,部署接收端应用。
注意:接收端应用的服务名,不能同发送端服务名相同。比如,发送端服务为myserver,接收端服务名不能是myserver。具体原因,可查验网上相关资料。
3、消息接收测试。
重启服务,后台自动接收到发送端发送的消息。自动接收刚才服务端发送的Kaven19870802。完成测试。
此文作为交流学习之需,如有不妥敬请指点,共习之。