)
一、JMS是个什么1、JMS即Java消息服务Java Message Service应用程序接口是一个Java平台中关于面向消息中间件MOM的API用于在两个应用程序之间或分布式系统中发送消息进行异步通信。Java消息服务是一个与具体平台无关的API绝大多数MOM提供商都对JMS提供支持。2、JMS是一组消息服务的api即接口规范即数据库的JDBC消息服务的JMS。二、为什么要学习使用JMS1、在JAVA中如果两个应用程序之间对各自都不了解甚至这两个程序可能部署在不同的大洲上那么它们之间如何发送消息呢举个例子一个应用程序A部署在印度另一个应用程序部署在美国然后每当A触发某件事后B想从A获取一些更新信息。当然也有可能不止一个B对A的更新信息感兴趣可能会有N个类似B的应用程序想从A中获取更新的信息。在这种情况下JAVA提供了最佳的解决方案-JMS完美解决了上面讨论的问题。JMS同样适用于基于事件的应用程序如聊天服务它需要一种发布事件机制向所有与服务器连接的客户端发送消息。JMS与RMI不同发送消息的时候接收者不需要在线。服务器发送了消息然后就不管了等到客户端上线的时候能保证接收到服务器发送的消息。这是一个很强大的解决方案能处理当今世界很多普遍问题。三、JMS有什么优势1、异步JMS天生就是异步的客户端获取消息的时候不需要主动发送请求消息会自动发送给可用的客户端。2、可靠JMS保证消息只会递送一次。大家都遇到过重复创建消息问题而JMS能帮你避免该问题只是避免而不是杜绝所以在一些糟糕的环境下还是有可能会出现重复。四、JMS消息传送模型在JMS API出现之前大部分产品使用“点对点”和“发布/订阅”中的任一方式来进行消息通讯。JMS定义了这两种消息发送模型的规范它们相互独立。任何JMS的提供者可以实现其中的一种或两种模型这是它们自己的选择。JMS规范提供了通用接口保证我们基于JMS API编写的程序适用于任何一种模型。让我们更加详细的看下这两种消息传送模型;1、点对点消息传送模型P2P在点对点消息传送模型中应用程序由消息队列发送者接收者组成。每一个消息发送给一个特殊的消息队列该队列保存了所有发送给它的消息(除了被接收者消费掉的和过期的消息)。点对点消息模型有如下特性1、每个消息只有一个接受者自己测试了一下可以有多个接受者但是当有多个接收者时每个接收者只能获取随机的几条信息2、消息发送者和消息接受者并没有时间依赖性。3、当消息发送者发送消息的时候无论接收者程序在不在运行都能获取到消息4、当接收者收到消息的时候会发送确认收到通知acknowledgement。5、点对点消息模型图2、发布/订阅消息传送模型在发布/订阅消息模型中发布者发布一个消息该消息通过topic传递给所有的客户端。在这种模型中发布者和订阅者彼此不知道对方是匿名的且可以动态发布和订阅topic。topic主要用于保存和传递消息且会一直保存消息直到消息被传递给客户端。发布/订阅消息模型有如下特性1、一个消息可以传递给多个订阅者2、发布者和订阅者有时间依赖性只有当客户端创建订阅后才能接受消息且订阅者需一直保持活动状态以接收消息。3、为了缓和这样严格的时间相关性JMS允许订阅者创建一个可持久化的订阅。这样即使订阅者没有被激活运行它也能接收到发布者的消息。4、发布/订阅消息模型图五、接收消息在JMS中消息的接收可以使用以下两种方式1、同步方式使用同步方式接收消息的话消息订阅者调用receive()方法。在receive()中消息未到达或在到达指定时间之前方法会阻塞直到消息可用。1、 目的地是Queueconsumer session.createConsumer(queue); Message message consumer.receive(); //同步方式接收2、目的地是Destinationconsumer session.createConsumer(destination); //同步方式接受信息,如果还没有获取到则会阻塞直到接收到信息 Message messages consumer.receive();2、异步方式使用异步方式接收消息的话消息订阅者需注册一个消息监听者类似于事件监听器只要消息到达JMS服务提供者会通过调用监听器的onMessage()递送消息。异步方式接收是使用了监听方式六、JMS编程接口JMS应用程序由如下基本模块组成1、管理对象Administered objects-连接工厂Connection Factories和目的地Destination2、连接对象Connections3、会话Sessions4、消息生产者Message Producers5、消息消费者Message Consumers6、消息监听者Message Listeners7、JMS管理对象管理对象Administered objects是预先配置的JMS对象由系统管理员为使用JMS的客户端创建主要有两个被管理的对象连接工厂ConnectionFactory目的地Destination这两个管理对象由JMS系统管理员通过使用Application Server管理控制台创建存储在应用程序服务器的JNDI名字空间或JNDI注册表。8、连接工厂ConnectionFactory客户端使用一个连接工厂对象连接到JMS服务提供者它创建了JMS服务提供者和客户端之间的连接。JMS客户端如发送者或接受者会在JNDI名字空间中搜索并获取该连接。使用该连接客户端能够与目的地通讯往队列或话题发送/接收消息。让我们用一个例子来理解如何发送消息9、目的地Destination目的地指明消息被发送的目的地以及客户端接收消息的来源。JMS使用两种目的地队列和话题。10、JMS连接连接对象封装了与JMS提供者之间的虚拟连接如果我们有一个ConnectionFactory对象可以使用它来创建一个连接。//链接工厂 ActiveMQConnectionFactory connectionFactory null; //链接对象 Connection connection null; connectionFactory new ActiveMQConnectionFactory(admin,admin,tcp://192.168.1.111:61616); connection connectionFactory.createConnection(); connection.start();11、JMS 会话SessionSession是一个单线程上下文用于生产和消费消息可以创建出消息生产者和消息消费者。Session对象实现了Session接口在创建完连接后我们可以使用它创建Session。//第一个参数是否开启事务 true开启 ,false不开启事务如果开启记得手动提交 //参数二表示的是签收模式一般使用的有自动签收和客户端自己确认签收 session connection.createSession(true, Session.AUTO_ACKNOWLEDGE);12、JMS消息生产者消息生产者由Session创建用于往目的地发送消息。生产者实现MessageProducer接口我们可以为目的地、队列或话题创建生产者1、队列QueueQueue queue session.createQueue(test_queue); //为队列创建消息生产者 MessageProducer producer session.createProducer(queue);2、目的地DestinationDestination destination session.createQueue(test-queue); //为目的地创建消息生产者 MessageProducer producer session.createProducer(destination);12这两种方式只能用在点对点消息模型3、话题Topic//创建话题 Topic topic session.createTopic(myTopic.messages); //为话题创建消息生产者 MessageProducer producer session.createProducer(topic);4、只能用在发布/订阅消息模型上。创建完消息生产者后可以使用send方法发送消息//创建消息 TextMessage message session.createTextMessage(); message.setText(测试队列消息i); //发送消息到目的地 producer.send(message);13、JMS消息消费者消息消费者由Session创建用于接收目的地发送的消息。消费者实现MessageConsumer接口我们可以为目的地、队列或话题创建消费者1、队列QueueQueue queue session.createQueue(test_queue); //队列目的地消费者消费消息的地方 MessageConsumer consumer session.createConsumer(queue); //消息消费者2、目的地Destination//消息目的地 Destination destination session.createQueue(test-queue); //消息消费者 MessageConsumer consumer session.createConsumer(destination);3、话题Topic//创建话题 Topic topic session.createTopic(myTopic.messages); //为话题创建消费者 MessageConsumer consumer session.createConsumer(topic);14、JMS消息监听器消息监听这种方式也就是消息的异步接收方式JMS消息监听器是消息的默认事件处理者他实现了MessageListener接口该接口包含一个onMessage方法在该方法中需要定义消息达到后的具体动作。通过调用setMessageListener方法我们给指定消费者定义了消息监听器.1、TextMessageconsumer.setMessageListener(new MessageListener(){ Override public void onMessage(Message message) { TextMessage textMessage (TextMessage)message; try { String value textMessage.getText(); System.out.println(value: value); } catch (JMSException e) { // TODO Auto-generated catch block e.printStackTrace(); } } });2、ObjectMessageconsumer.setMessageListener(new MessageListener(){ Override public void onMessage(Message message){ try { TestBean tbean (TestBean)((ObjectMessage)message).getObject(); System.out.println(tbean: tbean); if(null ! message) { System.out.println(收到信息1 tbean.getName()); } } catch (JMSException e) { // TODO Auto-generated catch block e.printStackTrace(); } } });七、JMS消息结构JMS客户端使用JMS消息与系统通讯JMS消息虽然格式简单但是非常灵活 JMS消息由三部分组成1、消息头JMS消息头预定义了若干字段用于客户端与JMS提供者之间识别和发送消息预编译头如下– JMSDestination 消息发送的目的地主要是指Queue和Topic由session创建而由生产者的send方法设置.– JMSDeliveryMode传送模式:有两种即久模式和非持久模式。一条持久性的消息应该被传输一次仅仅一次这就意味着如果JMS提供者出现故障该消息并不会丢失它会在服务器恢复之后再次传递。一条非持久的消息最多会传递一次这意味着服务器出现故障该消息将永远丢失。由session穿件由消息生产者的send方法设置– JMSMessageID唯一识别每个消息的标识由JMS消息生产者产生。由send方法设置– JMSTimestamp一个JMS Provider在调用send()方法时自动设置它是消息被发送和消费者实际接收的时间差。由客户端设置– JMSCorrelationID用来连接到另外一个消息典型的应用是在回复消息中连接到原消息。在大多数情况下JMSCorrelationID用于将一条消息标记为对JMSMessageID标示的上一条消息的应答不过JMSCorrelationID可以是任何值不仅仅是JMSMessageID。由客户端设置– JMSReplyTo提供本消息回复消息的目的地址,由客户端设置– JMSRedelivered如果一个客户端收到一个设置了JMSRedelivered属性的消息则表示可能客户端曾经在早些时候收到过该消息但并没有签收(acknowledged)。如果该消息被重新传送JMSRedeliveredtrue 否则 JMSRedeliveredflase 。由JMS Provider设置– JMSType消息类型的标识符由客户端设置– JMSExpiration消息过期时间等于Destination的send方法中的timeToLive值加上发送时刻的GMT的时间值。如果timeToLive值等于零则JMSExpiration被设置为零表示该消息永不过期。如果发送后在消息过期时间之后消息还没有被发送到目的地则该消息被清除。由send方法设置– JMSPriority消息优先级从0-9十个级别0-4是普通消息5-9是加急消息。JMS不要求JMS Provider严格按照这十个优先级发送消息但必须保证加急消息要先于普通消息到达默认是4级。由send方法设置一个消息的消息头有这些属性我们可以按照需要对这个消息的消息进行设计在将这个消息使用消息生产者的send方法发送到消息服务上。2、消息属性我们可以给消息设置自定义属性这些属性主要是提供给应用程序的。对于实现消息过滤功能消息属性非常有用JMS API定义了一些标准属性JMS服务提供者可以选择性的提供部分标准属性。3、消息体在消息体中JMS API定义了五种类型的消息格式让我们可以以不同的形式发送和接受消息并提供了对已有消息格式的兼容。不同的消息类型如下Text message : javax.jms.TextMessage表示一个文本对象。Object message : javax.jms.ObjectMessage表示一个JAVA对象。Bytes message : javax.jms.BytesMessage表示字节数据。Stream message :javax.jms.StreamMessage表示java原始值数据流。Map message : javax.jms.MapMessage表示键值对。