JMS入门学习
来源:互联网 发布:淘宝退假货会怎么样 编辑:程序博客网 时间:2024/06/05 15:49
JMS学习笔记
Java MessageService java消息服务
JMS入门
JMS概要
JMS是SUN公司开发的一套访问MOM(Message-Oriented-Middleware)消息服务中间件的标准API
MON提供消息接收和转发的服务,对消息进行缓存和持久操作,保证消息的安全性,JMS让开发都无须了解远程过程调用的细节和网络通信协议的细节就可以通过JMS向MOM发送消息,借助消息我们可以松散耦合的方式集成不同的应用
JMS异步通信
JMS支持异步消息机制,消息生产者发送消息到MOM,消息消费者甚至可以不在线,MOM会暂存消息,当消息消费者上后,MOM会将消息发给消息消费者,消息生产者不必等消息消费者,这种异步消息机制在很多系统中是非常重要的
引用TaskExecuter 实现消息异常传输
JMS的两种消息类型
PTP (Point toPoint) 点对点
Pub/Sub(Publish/Subscribe) 发布/订阅
PTP
PTP生产的消息会放在一个队列中,消费者从队列中取走消息,消息一旦被取走,就会从队列中删除,多个观察都观察一个队列,但一个消息只能被一个消费都取走
Pub/Sub
用称为主题(Topic)的内容分层结构代替了PTP模型中的唯一的目的地,一个发布者可以将消息发布到某个主题下面,订阅了该主题的订阅者就可以收到这个消息.
JMS受管理的对象
在JMS之前,各MOM产品都提供了专有的API访问其产品,JMS通过MOM产品为Java程序提供了一个发送消息接受消息的标准,便利的方法,用JMS写的应用可以在任何实现JMS标准的MOM产品上运行.
各MOM产品实现技术和机制存在很大的差别,为保持JMS客户端的可移植性,实现了JMS接口的对象必须与MOM产品的专胡技术进行隔离,完成这项工作的机制是管理对象.
这些JMS接口的对象由提供者消息系统管理员创建,并放置在JNDI的空间中,然后由JMS检索这些对象,通过JMS接口访问这些对象,JMS提供者必须提供创建管理对象的方法,受管对象存放于JNDI
两个重要的受管对象
ConnectionFacory 用于创建到提供者底层消息系统的连接
Destination 用于指定JMS客户端发送消息的目的地或接收消息的来源
JMS程序只要知道受管对象的JNDI名称和JMS接口类型就可以了
JMS的一些重要接口
JMS定义了一系列的封装消息的高级接口,这些接口又分两个消息域
PTP 和 Pub/Sub javax.jms 包下的接口
ConnectionFactory
Connection
Destination
Session 发送消息或接收消息的单线程环境
MessageProducer
MessageConsumer
JMS的两个版本JMS1.1 JMS1.02
区别:JMS1.1将两种消息统一进行处理,透明地操作两种消息域
JMS1.02区别对待两种消息域,针对每种消息域提供了高级接口的子接口
高级接口 PTP域子接口 Pub/Sub域子接口
ConnectionFactory QueueConnectionFactory TopicConnectionFactory
Connection QueueConnection TopicConnection
Destination Queue Topic
Session QueueSession TopicSession
MessageProducer QueueSender TopicPublisher
MessageConsumer QueueReceiverQueueBrowser TopicSubscriber
JSM程序需要基本步骤
1. 通过JNDI查找ConnectionFactory
2. 通过ConnectionFactory创建一个Connection
3. 用Connection 创建一个或者多个Session
4. 通过JNDI查询一个或多个Destination
5. 用Session和Destination创建对应的MessageProducer 或MessageConsumer
6. 启动Conneciton
7. 发送或接收消息
JMS消息的结构
Header Properties Body 三部分
Header 消息头部
JMSMessageID String
JMSDestination destination
JMSDeliveryMode int 消息持久化设置 Persistent
JMSTimestamp long
JMSExpiration long
JMSPriority int
JMSCorrelationID int
JMSReplyTo String
JMSType Destination 请求程序用它来指定回复消息就发送的地方,由
发送消息的JMS程序设置
JMSRedelivered String
Message 接口提供了访问Header的API
Properties 消息属性
JMSX开头的是JMS专用的,JSM_开头的是提供者专用的
Body 消息内容
JMS有一种消息类型,通过五个接口来实现
TextMessage 字符串
ObjectMessage 实现了Seralizable 接口的对象
MapMessage 是一个Map
BytesMessage 消息是一个二进制数组
StreamMessage 消息是一组原始数据类型,这此数据按标准进行操作,按顺序进行填充或读取
消息的收发机制
JMS事务
JMS使用Session控制事务,如何需要事务可以在创建Session时标注需要事务
消息确认
消息确认是收到消息发送一个回执确认收到消息
三种确认方式
Session.ATUO_ACKNOWLEDGE 接收到消息自动发送这一个确认
Session.CLIENT_ACKNOWLEDGE 调用Meeage#acknowledge()方法,显示发送确认
Session.DUPS_OK_ACKNOWLEDGE 延时发送消息,但可能有重复接收消息的问题
消息选择 (消息过滤)
选择条件可以通过Header和Properties 进行匹配度设置
MessageConsumerconsumer=session.createConsumer(destination,”JMSType=’car’”);
JMSType 和color weigh属性
“JMSType=’car’AND color=’blue’ AND weigh>2500”
JMSCorrelationID=’12312312’ AND phone LIKE ‘12%e3’”;
Phone IS NOT NULL ANDage>23
发送消息
MessageSender.java 消息发送器
package cn.com.snt.jms;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.springframework.context.ApplicationContext;
importorg.springframework.context.support.FileSystemXmlApplicationContext;
public class MessageSender extendsApplicationContextWare{
privateConnectionFactory factory=null;
privateDestination dest=null;
publicvoid setFactory(ConnectionFactory factory) {
this.factory= factory;
}
publicvoid setDest(Destination dest) {
this.dest= dest;
}
publicvoid send(String msgText){
Connectionconnection=null;
try{
// ApplicationContextctx = new FileSystemXmlApplicationContext("src/cn/com/snt/jms/applicationContext.xml");
// ConnectionFactoryfactory=(ConnectionFactory) ctx.getBean("connectionFactory");
// Destinationdest=(Destination)ctx.getBean("dest");
System.out.println(factory+""+dest);
// Contextctx=new InitialContext();
// ConnectionFactoryfactory=(ConnectionFactory)ctx.lookup("jndi/jmsConn");
// Destinationdest=(Destination)ctx.lookup("jndi/dest");
// ctx.close();
//创建一个到MOM的连接
connection=factory.createConnection();
connection.start();
//创建一个会话实例,不使用事务,采用自动确认消息的机制
Sessionsession=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建一个指向特定目标地址的消息发送者
MessageProducersender=session.createProducer(dest);
TextMessagemessage=session.createTextMessage(msgText);
sender.send(message);
System.out.println("sendersuccess!");
}catch(JMSException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
}
publicstatic void main(String[] args) {
((MessageSender)(getApplicationContext().getBean("messageSender"))).send("name:lilp;gender:male");
}
}
ApplicationContextWare.java 为了使用消息发送者和接收者同用一个IoC容器
package cn.com.snt.jms;
import org.springframework.context.ApplicationContext;
importorg.springframework.context.support.FileSystemXmlApplicationContext;
public class ApplicationContextWare {
privatestatic ApplicationContext ctx;
static{
ctx= newFileSystemXmlApplicationContext("src/cn/com/snt/jms/applicationContext.xml");
}
publicstatic ApplicationContext getApplicationContext(){
returnctx;
}
}
MessageReceiver.java
package cn.com.snt.jms;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.springframework.context.ApplicationContext;
importorg.springframework.context.support.FileSystemXmlApplicationContext;
public class MessageReceiver extendsApplicationContextWare implements MessageListener {
privateConnectionFactory factory=null;
privateDestination dest=null;
publicvoid setFactory(ConnectionFactory factory) {
this.factory= factory;
}
publicvoid setDest(Destination dest) {
this.dest= dest;
}
publicvoid reveive(){
Connectionconnection=null;
try{
// Contextctx=new InitialContext();
// //从JNDI中获取ConnectionFactory
// ConnectionFactoryfactory=(ConnectionFactory)ctx.lookup("jndi/jmsConn");
// //从JNDI中获取消息发送目标地
// Destinationdest=(Destination)ctx.lookup("jndi/dest");
// ctx.close();
// ApplicationContextctx = newFileSystemXmlApplicationContext("src/cn/com/snt/jms/applicationContext.xml");
// ConnectionFactoryfactory=(ConnectionFactory) ctx.getBean("connectionFactory");
// Destinationdest=(Destination)ctx.getBean("dest");
System.out.println(factory+""+dest);
//创建一个到MOM的连接
connection=factory.createConnection();
connection.start();
//创建一个会话实例,该会话不使用事务,采用自动确认消息的机制
Sessionsession=connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
//创建一个指向一个特定目标地址的消息消费者
MessageConsumerreceiver=session.createConsumer(dest);
receiver.setMessageListener(this);
}catch(JMSException e) {
e.printStackTrace();
}
}
publicvoid onMessage(Message message) {
try{
TextMessagetextMsg=(TextMessage)message;
System.out.println("MESSAGE:"+textMsg.getText());
}catch (JMSException e) {
e.printStackTrace();
}
}
publicstatic void main(String[] args) {
((MessageReceiver)(getApplicationContext().getBean("messageReceiver"))).reveive();
}
}
两个受管对象可以从JNDI服务器中获取也可以在IoC容器中获取,上面使用的Spring的IoC容器
applicationContext.xml 文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:amq="http://activemq.org/config/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://activemq.org/config/1.0http://people.apache.org/repository/org.apache.activemq/xsds/activemq-core-4.1-incubator-SNAPSHOT.xsd">
<bean id="connectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory"
destroy-method="stop">
<property name="connectionFactory" >
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://127.0.0.1:61616"/>
</bean>
</property>
</bean>
<bean id="dest" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="TOOL.DEFAULT"/>
</bean>
<bean id="messageReceiver" class="cn.com.snt.jms.MessageReceiver">
<property name="factory" ref="connectionFactory"/>
<property name="dest" ref="dest"/>
</bean>
<bean id="messageSender" class="cn.com.snt.jms.MessageSender">
<property name="factory" ref="connectionFactory"/>
<property name="dest" ref="dest"/>
</bean>
</beans>
上面采用的PTP消息域类型,也可以采用Pub/Sub模式,发送什么类型的消息由Destination决定的
如果是JMS1.02需要区别对待PTP域和Pub/Sub域的消息,使用QueueSender 发送PTP消息,并且目标地址为Queue,使用TopicPublisher发送Pub/Sub域消息,目标地址必须是Topic对象
使用QueueReceiver 接收PTP域消息,地址通过Queue指定,使用TopicSubscriber 接收Pub/Sub域的消息,地址通过Topic指定
JMS接收消息的两种方式
同步接收与异步接收消息
使用消息接收器的receive()方法接收方式是同步接收的方式,当receiver()方法接收不到消息时,一直会阻塞.可能receiver(long )指定等待多长时间,接收不到消息就返回null,0永不超时,也可以使用receiverNoWait()不等待
在实际的应用,异常消息接收更有意义,可以通过 注册MessageListener监听器,实现消息异常接收,上面的例子就是采用异步接收消息的方式实现的.
JMS的提供者 ActiveMQ 默认工作在61616商品上
JBOSS Mesaging
- JMS入门学习
- JMS入门学习
- JMS入门学习
- jms入门学习总结
- JMS学习笔记二--入门学习
- JMS入门
- JMS入门
- JMS入门
- JMS入门
- JMS 入门
- JMS入门
- JMS入门
- JMS 入门
- JMS 入门
- jms入门
- jms入门
- JMS学习
- JMS 学习
- http://bbs.redlegend.org/forumdisplay.php?fid=8&page=1 delphi学习论坛
- 让ubuntu安装build-essential时不从光盘安装
- 浅谈ACM-ICPC的题目风格和近几年题目的发展[转]
- 关于f:setPropertyActionListener标签的问题
- ubuntu Flash 中文乱码解决
- JMS入门学习
- 《JAVA编程思想》第四版学习 需要我记住的something --初始化和清除 (二)
- 技术开发团队的管理
- 我来玩吧-欢迎体验二维码-欢迎体验12580
- Django报错UnicodeEncodeError: 'ascii' codec can't encode... 的解决方法
- PKU2676 Sudoku 数独
- 我的VIM配置文件
- 日语初学者会话
- 日记090523