JMS:
Java消息服务(Java Message Service)
JMS是用于访问企业消息系统的开发商中立的API。企业消息系统可以协助应用软件通过网络进行消息交互。
JMS的编程过程很简单,概括为:应用程序A发送一条消息到消息服务器的某个目得地(Destination),然后消息服务器把消息转发给应用程序B。因为应用程序A和应用程序B没有直接的代码关连,所以两者实现了解偶。
消息驱动bean(message-driven bean)
它是专门用于异步处理java消息的组件.具有处理大量并发消息的能力.
何时使用JMS:
在某些情况下,由于SessionBean方法的执行时间比较长,这就需要异步地调用该方法,否则客户端就需要等待比较长的时间。要实现异步调用, 就需要使用消息驱动Bean。
消息驱动Bean的基本原理是客户端向消息服务器发送一条消息后,消息服务器会将该消息保存在消息队列中。在这时消 息服务器中的某个消费者(读取并处理消息的对象)会读取该消息,并进行处理。发送消息的客户端被称为消息生产者。
JMS中的消息
消息传递系统的中心就是消息。一条 Message 由三个部分组成:
头(header),属性(property)和主体(body)。
消息有下面几种类型,他们都是派生自 Message 接口。
StreamMessage:一种主体中包含 Java 基元值流的消息。其填充和读取均按顺序进行。
MapMessage:一种主体中包含一组名-值对的消息。没有定义条目顺序。
TextMessage:一种主体中包含 Java 字符串的消息(例如,XML 消息)。
ObjectMessage:一种主体中包含序列化 Java 对象的消息。
BytesMessage:一种主体中包含连续字节流的消息
消息的传递模型
JMS 支持两种消息传递模型:点对点(point-to-point,简称 PTP)和发布/订阅(publish/subscribe,简称 pub/sub)。
这两种消息传递模型非常相似,但有以下区别:
PTP 消息传递模型规定了一条消息只能传递给一个接收方。 采用javax.jms.Queue 表示。
Pub/sub 消息传递模型允许一条消息传递给多个接收方。采用javax.jms.Topic表示
这两种模型都通过扩展公用基类来实现。例如:javax.jms.Queue 和javax.jms.Topic 都扩展自javax.jms.Destination 类。
配置目标地址
开始JMS编程前,我们需要先配置消息到达的目标地址(Destination),因为只有目标地址存在了,我们才能发送消息到这个地址。由于每个应用服务器关于目标地址的配置方式都有所不同,下面以jboss为例,配置一个queue类型的目标地址。
<?xml version="1.0" encoding="UTF-8"?> <server> <mbean code="org.jboss.mq.server.jmx.Queue" name="jboss.mq.destination:service=Queue,name=foshanshop"> <attribute name="JNDIName">queue/foshanshop</attribute> <depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends> </mbean> </server>
(项目中用的这个:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <server> <mbean xmbean-dd="xmdesc/Queue-xmbean.xml" name="jboss.messaging.destination:service=Queue,name=InstanceQueue" code="org.jboss.jms.server.destination.QueueService"> <attribute name="JNDIName">/queues/InstanceQueue</attribute> <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends> <depends>jboss.messaging:service=PostOffice</depends> </mbean> </server>
放在server\default\deploy\queues\InstanceQueue-service.xml 中)
模版可以在E:\jboss-5.1.0.GA-jdk6\jboss-5.1.0.GA\docs\examples\jms中的example-destinations-service.xml中找到。
Jboss使用一个XML文件配置队列地址,文件的取名格式应遵守*-service.xml
<attribute name="JNDIName">属性指定了该目标地址的全局JNDI名称。如果你不指定JNDIName属性,jboss会为你生成一个默认的全局JNDI,其名称由“queue”+“/”+目标地址名称组成。另外在任何队列或主题被部署之前,应用服务器必须先部署Destination Manager Mbean,所以我们通过<depends>节点声明这一依赖。
在java类中发送消息
一般发送消息有以下步骤:
(1) 得到一个JNDI初始化上下文(Context)
InitialContext ctx = new InitialContext();
(2) 根据上下文查找一个连接工厂 QueueConnectionFactory 。该连接工厂是由JMS提供的,不需我们自己创建,每个厂商都为它绑定了一个全局JNDI,我们通过它的全局JNDI便可获取它;
QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup("QueueConnectionFactory");
(3) 从连接工厂得到一个连接 QueueConnection
conn = factory.createQueueConnection();
(4) 通过连接来建立一个会话(Session);
session = conn.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
这句代码意思是:建立不需要事务的并且能自动确认消息已接收的会话。
(5) 查找目标地址:
Destination destination = (Destination ) ctx.lookup("queue/foshanshop"); //上面配置的那个目标地址
(6) 根据会话以及目标地址来建立消息生产者MessageProducer (QueueSender和TopicPublisher都扩展自MessageProducer接口)
例子对应代码:
MessageProducer producer = session.createProducer(destination); TextMessage msg = session.createTextMessage("您好,这是我的第一个消息驱动Bean"); producer.send(msg);
项目用:
JMS工厂和队列JNDI配在配置文件jmsqueue.properties里,内容如下:
connectionFactoryName=ConnectionFactory queueName=/queues/InstanceQueue
/** * 目的:读取jmsqueue.properties中消息队列的信息,初始化消息队列,提供发送消息的函数 * */ public class MsgQueueSender { private static final Logger logger = LoggerFactory.getLogger(MsgQueueSender.class); private static final MsgQueueSender ms = new MsgQueueSender(); private Properties info = new Properties(); /** * jms */ private QueueConnection conn; private Queue que; private MsgQueueSender() { initJMSInfo(); initMsgQueue(); } /** * 初始化jndi队列 * */ private void initMsgQueue() { InitialContext iniCtx; try { iniCtx = new InitialContext(); Object tmp = iniCtx.lookup(info.getProperty("connectionFactoryName", "ConnectionFactory")); QueueConnectionFactory qcf = (QueueConnectionFactory) tmp; conn = qcf.createQueueConnection(); que = (Queue) iniCtx.lookup(info.getProperty("queueName", "/queues/InstanceQueue")); conn.start(); } catch (Exception e) { logger.error("[MsgQueueSender.initMsgQueue] \u65e0\u6cd5\u8fde\u63a5\u5230\u6d88\u606f\u670d\u52a1\u5668\uff0c\u8bf7\u68c0\u67e5jms\u914d\u7f6e\u548c\u670d\u52a1\u7aef" + e.getMessage(),e); } } /** * 读取jms配置 */ private void initJMSInfo() { InputStream is = this.getClass().getClassLoader().getResourceAsStream("jmsqueue.properties"); if (is != null) { try { info.load(is); } catch (IOException e) { logger.error("[MsgQueueSender.initJMSInfo] \u8bfb\u53d6jmsqueue.properties\u51fa\u9519\uff0c\u5c06\u4f7f\u7528\u9ed8\u8ba4\u914d\u7f6e " + e.getMessage(),e); } } } public static MsgQueueSender getInstance() { return ms; } public void sendTextMsg(String msg) throws JMSException{ QueueSession session = conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE); session.createSender(que).send(session.createTextMessage(msg)); session.close(); } public void sendObjMsg(Serializable obj) throws JMSException{ QueueSession session = conn.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE); session.createSender(que).send(session.createObjectMessage(obj)); session.close(); } }
采用消息驱动Bean (Message Driven Bean)接收消息
消息驱动Bean(MDB)是设计用来专门处理基于消息请求的组件。它和无状态Session Bean一样也使用了实例池技术,容器可以使用一定数量的bean实例并发处理成百上千个JMS消息。正因为MDB具有处理大量并发消息的能力,所以非常适合应用在一些消息网关产品。如果一个业务执行的时间很长,而执行结果无需实时向用户反馈时,也很适合使用MDB。如订单成功后给用户发送一封电子邮件或发送一条短信等。
一个MDB通常要实现MessageListener接口,该接口定义了onMessage()方法。Bean通过它来处理收到的JMS消息。
package javax.jms; public interface MessageListener { public void onMessage(Message message); }
当容器检测到bean守候的目标地址有消息到达时,容器调用onMessage()方法,将消息作为参数传入MDB。MDB在onMessage()中决定如何处理该消息。你可以使用注释指定MDB监听哪一个目标地址(Destination)。当MDB部署时,容器将读取其中的配置信息。
@MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"), @ActivationConfigProperty(propertyName="destination", propertyValue="queue/foshanshop"), @ActivationConfigProperty(propertyName="acknowledgeMode", propertyValue="Auto-acknowledge") }) public class PrintBean implements MessageListener { public void onMessage(Message msg) { } }
项目中用:
META-INF下:
ejb-jar.xml:
<?xml version="1.0" encoding="UTF-8"?> <ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:ejb="http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" version="3.0"> <display-name>msgreceiver</display-name> <enterprise-beans> <message-driven> <display-name>instanceMDB</display-name> <ejb-name>instanceMDB</ejb-name> <ejb-class>com.project.soa.msgreceiver.InstanceReceiver</ejb-class> <activation-config> <activation-config-property> <activation-config-property-name>destinationType</activation-config-property-name> <activation-config-property-value>javax.jms.Queue</activation-config-property-value> </activation-config-property> <activation-config-property> <activation-config-property-name>destination</activation-config-property-name> <activation-config-property-value>/queues/InstanceQueue</activation-config-property-value> </activation-config-property> </activation-config> </message-driven> </enterprise-beans> </ejb-jar>
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="msgreceiver-ds"> <!-- 数据源:server\default\deploy\datasources\visesbdb-ds.xml 中jndi-name为datasources/visesbdb --> <jta-data-source>java:/datasources/visesbdb</jta-data-source> <jar-file>com.project.soa.bean-2.2.0.jar</jar-file> <properties> <property name="hibernate.hbm2ddl.auto" value="none" /> <property name="hibernate.show_sql" value="false" /> <property name="hibernate.format_sql" value="false" /> </properties> </persistence-unit> </persistence>
public class InstanceReceiver implements javax.jms.MessageListener { private static final Logger logger = LoggerFactory.getLogger(InstanceReceiver.class); @EJB(name="InstanceService") private InstanceService is; @Override public void onMessage(Message msg) { try { is.processMsg(((ObjectMessage)msg).getObject()); } catch (JMSException e) { logger.error("[InstanceReceiver.onMessage] " + e.getMessage()); e.printStackTrace(); } } } @Stateless @Local ({InstanceService.class}) public class InstanceServiceImpl implements InstanceService{ private static final Logger logger = LoggerFactory.getLogger(InstanceServiceImpl.class); @PersistenceContext private EntityManager em; ... }
JMS中消息的 同步消费 和 异步消费
同步消费 比如
connection.start();
Message message=queueReceiver.receive();
同步消费 receive 就执行一次,并返回message对象。
同步消费中,消息的接收者会一直等待下去,直到有消息到达,或者超时。
异步消费 比如
connection.start();
receiver.setMessageListener(new MyMessageListener()); //MyMessageListener实现了MessageListener接口
System.in.read(); //这句话是为了人为的阻塞程序不然 还没接收到消息 ,程序一下子就执行完了,关闭了。
异步消费会注册一个监听器,当有消息到达的时候,会回调它的onMessage()方法,没有次数限制
...
相关推荐
**JMS学习笔记精心总结** Java消息服务(Java Message Service,简称JMS)是Java平台中用于企业级应用间异步通信的一种标准接口。它允许应用程序创建、发送、接收和读取消息,使得应用程序能够在不直接连接的情况下...
总结来说,JMS583芯片是现代高速存储解决方案的重要组成部分,它利用先进的USB 3.1 Gen 2和PCIe Gen3x2技术,为存储设备提供高速、低延迟的数据传输,广泛应用于各种存储设备的开发中,对于提升系统性能和用户体验...
总结,`javax.jms-1.1.jar`是Java消息服务API的实现,它提供了在分布式系统中进行可靠、异步通信的能力,通过标准化接口和消息模型,使得开发者可以轻松地在不同消息中间件之间切换,提升了系统的灵活性和可扩展性。
总结,JMS 1.1.jar作为Java消息服务的重要组成部分,提供了在分布式系统中实现可靠消息传递的API。当遇到Maven下载问题时,手动将其放入本地仓库是解决问题的有效方法。理解和掌握JMS原理及操作,对于提升Java应用的...
#### 四、总结 通过上述步骤,可以完成 Maximo 中 JMS 的基本配置。这不仅有助于提高系统的消息处理能力,还能确保数据传输的安全性和稳定性。对于希望利用 JMS 实现 Maximo 与其他系统间高效通信的企业来说,这些...
#### 八、总结 通过本教程的学习,我们可以了解到JMS不仅仅是Java消息服务的一个标准API,更是构建高效、可靠的企业级应用的基础。掌握JMS的基本概念、架构和应用场景对于任何希望在分布式环境中构建稳定、高性能...
总结来说,JBOSS中的JMS应用实例涉及了JMS的基本概念、JBOSST的配置、代码编写以及具体的应用场景。通过实践这些步骤,开发者可以掌握如何在JBOSST环境中利用JMS进行高效的数据通信。同时,提供的文档和项目文件为...
总结起来,`javax.jms.jar` 包提供了Java开发人员与JMS兼容的消息中间件进行通信的工具,而`demo` 文件中的实例代码展示了如何在实际应用中使用这些工具。通过学习和实践这些示例,你可以更好地理解和掌握Java消息...
总结来说,"activeMQ-JMS实例"是一个基于Spring MVC的示例,它演示了如何使用Spring的JMS支持与ActiveMQ结合,实现消息的发送和接收。这个实例对于学习和理解JMS以及如何在实际项目中应用它是很有帮助的。通过这个...
总结起来,JMS提供了一种标准化的方式来处理分布式系统中的消息通信,而ActiveMQ作为JMS消息代理,为开发者提供了可靠的、高性能的消息传递服务。了解和掌握JMS及ActiveMQ,对于构建可扩展的、健壮的企业级应用至关...
**总结:** WebLogic与JMS+Spring的整合利用了WebLogic的稳定性和JMS的异步通信能力,结合Spring的灵活性和易用性,为开发高效、可扩展的企业级应用提供了强大的基础。通过详细的配置和测试,开发者可以确保系统能够...
#### 总结 JMS是Java EE中一个强大而灵活的组件,用于实现企业级应用中的消息传递。通过理解JMS的基本概念、实现和与Spring、Hibernate等其他框架的集成,开发人员可以构建出高度可靠、可扩展和健壮的分布式系统。...
#### 八、总结 通过本篇文章的学习,我们不仅了解了JMS的基本结构和开发实例,还深入了解了其高级接口、编程模型以及消息读取方式等内容。掌握JMS的核心概念和技术可以帮助开发者更好地构建复杂的企业级应用,提高...
#### 八、总结 JMS作为Java企业级应用中的重要组成部分,为消息传递提供了一个统一的标准接口。通过理解JMS的基本概念和工作原理,开发者可以更好地利用这一技术构建可靠、高效的分布式系统。随着技术的发展,虽然...
**JMS整合Spring实例** ...总结来说,整合JMS与Spring能让你在Java应用中轻松实现异步消息处理,提高系统的可扩展性和容错性。通过Spring的抽象和自动化配置,你可以更加专注于业务逻辑,而不是底层的消息传递细节。
**总结** JMS规范提供了一种标准化的方式来处理企业级应用间的异步通信,而SUN MQ是其早期的优秀实现。通过理解和应用JMS,开发者能够构建更稳定、高效且可扩展的分布式系统。学习JMS规范及其实现,如SUN MQ,对于...
总结,JMS是Java平台中实现企业级消息传递的重要工具,通过理解其基本概念、API接口以及应用场景,开发者可以有效地构建可扩展、可靠的分布式系统。阅读“JMS教程.pdf”将更深入地了解JMS的细节和实践技巧。
总结起来,这个"spring_jms"实例旨在帮助初学者了解如何在Spring应用中使用JMS进行异步通信。通过结合Maven、Spring框架和ActiveMQ,我们可以构建一个高效、可靠的分布式消息系统,提升应用的性能和灵活性。通过深入...
总结JMS(Java Message Service)是一种Java消息服务标准,用于在分布式环境中进行异步通信。它支持点对点和发布订阅两种消息模型,分别对应消息队列和主题。JMS客户端通过ConnectionFactory创建连接,Session进行...