270 likes | 446 Views
J2EE —— 第 33 章 Java Message Service API. 概述. 什么是消息传递 软件组件或应用程序之间通信的一种方法 点对点,客户端连接在消息传递代理上 松散耦合 什么是 JMS API 创建、发送、接收、阅读消息的 Java API 通用接口、可移植性强 异步, JMS 提供者主动把消息递送给客户端 可靠,消息传递一次且仅一次. 何时使用 JMS API. 接口信息无关,可替换组件 不要求所有组件同时运行 发送者可在收到响应前继续运转 各组件高效相互作用不占用网络和资源. JMS API 如何与 J2EE 平台一起工作.
E N D
概述 • 什么是消息传递 • 软件组件或应用程序之间通信的一种方法 • 点对点,客户端连接在消息传递代理上 • 松散耦合 • 什么是JMS API • 创建、发送、接收、阅读消息的Java API • 通用接口、可移植性强 • 异步,JMS提供者主动把消息递送给客户端 • 可靠,消息传递一次且仅一次
何时使用JMS API • 接口信息无关,可替换组件 • 不要求所有组件同时运行 • 发送者可在收到响应前继续运转 • 各组件高效相互作用不占用网络和资源
JMS API如何与J2EE平台一起工作 • 应用程序客户端、EJB、Web组件可发送或同步接收JMS消息,应用程序客户端还可异步接收消息 • 消息驱动bean可异步消耗消息 • 消息发送和接收操作可共享分布式事务,允许JMS操作和数据库访问在单个事务内发生 • 可通过资源适配器访问JMS提供者
公共接口和消息消费 • 使用公共接口编程 • 可以使用相同的代码在PTP或者发布/订阅域内发送和接收消息 • 管理对象是域特有的 • 消息消费 • 同步:receive方法,阻塞或超时 • 异步:onMessage方法,监听器
消息生产 Context ctx = new InitialContext(); ConnectionFactory connectionFactory = (ConnectionFactory) ctx.lookup("jms/ConnectionFactory"); Destination myDest = (Destination) ctx.lookup("jms/MyTopic"); Queue myQueue = (Queue) ctx.lookup("jms/MyQueue"); Connection connection = connectionFactory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); Session session1 = connection.createSession(true, 0); MessageProducer producer = session.createProducer(myQueue); MessageProducer producer = session.createProducer(myTopic); producer.send(message); connection.close();
消息消费 MessageConsumer consumer = session.createConsumer(myQueue); MessageConsumer consumer = session.createConsumer(myTopic); connection.start(); Message m = consumer.receive(); Message m1 = consumer.receive(1000); // time out after a second Listener myListener = new Listener(); consumer.setMessageListener(myListener); //onMessage方法被调用 • 任何时候,只有会话的一个消息监听器在运行 • 消息选择器用于让JMS提供者过滤消息 • createConsumer和createDurableSubscriber允许指定消息选择器作为一个参数
消息头 • JMSDestination • JMSDeliveryMode • JMSExpiration • JMSPriority • JMSMessageID • JMSTimestamp • JMSCorrelationID • JMSReplyTo • JMSType • JMSRedelivered
消息体 TextMessage message = session.createTextMessage(); message.setText(msg_text); // msg_text is a String producer.send(message); Message m = consumer.receive(); if (m instanceof TextMessage) { TextMessage message = (TextMessage) m; System.out.println("Reading message: " + message.getText()); } else { // Handle error }
JMS消息类型 • TextMessage • MapMessage • BytesMessage • StreamMessage • ObjectMessage • Message
异常处理 • IllegalStateException • InvalidClientIDException • InvalidDestinationException • InvalidSelectorException • JMSSecurityException • MessageEOFException • MessageFormatException • MessageNotReadableException • MessageNotWriteableException • ResourceAllocationException • TransactionInProgressException • TransactionRolledBackException
编写简单的JMS客户端应用程序 • 以JBoss为例
使用基本可靠性机制 • 控制消息确认 • 事务提交,自动确认;事务回滚,重新传递 • 非事务性会话:createSession的第二个参数 • Session.AUTO_ACKNOWLEDGE • Session.CLIENT_ACKNOWLEDGE • Session.DUPS_OK_ACKNOWLEDGE • 对于非长期TopicSubscriber,会话关闭时,未确认的消息丢失
指定消息持久性、优先级、过期 producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); producer.setPriority(7); producer.setTimeToLive(60000); producer.send(message, DeliveryMode.NON_PERSISTENT, 3, 10000); • 创建临时目的地 • Session.createTemporaryQueue • Session.createTemporaryTopic producer = session.createProducer(msg.getJMSReplyTo()); replyMsg = session.createTextMessage("Consumer " + "processed message: " + msg.getText()); replyMsg.setJMSCorrelationID(msg.getJMSMessageID()); producer.send(replyMsg);
使用高级可靠性机制 • 创建长期订阅 String subName = "MySub"; MessageConsumer topicSubscriber = session.createDurableSubscriber(myTopic, subName); topicSubscriber.close(); session.unsubscribe("MySub");
使用JMS API本地事务 • 用本地事务组织发送和接收 • Session.commit, Session.rollback • EJB组件不能使用,而要使用分布式事务 • 事务不能包含与任何已经发送的消息有关的接收 • 同一消息的生产和消费不能是同一事务的一部分,两个客户端之间没有事务 • 异步消费者可以利用相同的会话接收和发送 session = connection.createSession(true, 0);
本地事务示例 producer = session.createProducer(vendorOrderQueue); outMessage = session.createMapMessage(); outMessage.setString("Item", "Computer(s)"); outMessage.setJMSReplyTo(retailerConfirmQueue); producer.send(outMessage); orderConfirmReceiver = session.createConsumer(retailerConfirmQueue); connection.start(); vendorOrderReceiver = session.createConsumer(vendorOrderQueue); supplierOrderProducer = session.createProducer(supplierOrderTopic); inMessage = vendorOrderReceiver.receive(); supplierOrderProducer.send(orderMessage); session.commit();
管理分布式事务 • 允许多个应用程序对同一个数据库进行原子性修改 • 允许单个应用程序对多个数据库进行原子性修改 • 可以将消息发送或接收与数据库修改和资源管理器的操作结合在一个事务中 • EJB:容器管理的事务,bean管理的事务 • Web组件不能异步消费消息 • Web组件使用receive应指定超时时间,不应长期阻塞