`
uule
  • 浏览: 6322381 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

JMS总结

    博客分类:
  • JMS
 
阅读更多

深入掌握JMS

JMS与Java消息中间件

JBOSS配置JMS主题和队列

JMS入门实例

Spring整合JMS

 

 

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消息详解

 

消息的传递模型

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()方法,没有次数限制

 

 

...

 

分享到:
评论
1 楼 somefuture 2016-06-12  
有点老了,学习不懂

相关推荐

    JMS学习笔记精心总结

    **JMS学习笔记精心总结** Java消息服务(Java Message Service,简称JMS)是Java平台中用于企业级应用间异步通信的一种标准接口。它允许应用程序创建、发送、接收和读取消息,使得应用程序能够在不直接连接的情况下...

    javax.jms-1.1.jar

    总结,`javax.jms-1.1.jar`是Java消息服务API的实现,它提供了在分布式系统中进行可靠、异步通信的能力,通过标准化接口和消息模型,使得开发者可以轻松地在不同消息中间件之间切换,提升了系统的灵活性和可扩展性。

    javax.jms.jar包与JMS实例代码

    总结起来,`javax.jms.jar` 包提供了Java开发人员与JMS兼容的消息中间件进行通信的工具,而`demo` 文件中的实例代码展示了如何在实际应用中使用这些工具。通过学习和实践这些示例,你可以更好地理解和掌握Java消息...

    activeMQ-JMS实例

    总结来说,"activeMQ-JMS实例"是一个基于Spring MVC的示例,它演示了如何使用Spring的JMS支持与ActiveMQ结合,实现消息的发送和接收。这个实例对于学习和理解JMS以及如何在实际项目中应用它是很有帮助的。通过这个...

    JMS整合Spring实例

    **JMS整合Spring实例** ...总结来说,整合JMS与Spring能让你在Java应用中轻松实现异步消息处理,提高系统的可扩展性和容错性。通过Spring的抽象和自动化配置,你可以更加专注于业务逻辑,而不是底层的消息传递细节。

    JMS规范培训教程

    **总结** JMS规范提供了一种标准化的方式来处理企业级应用间的异步通信,而SUN MQ是其早期的优秀实现。通过理解和应用JMS,开发者能够构建更稳定、高效且可扩展的分布式系统。学习JMS规范及其实现,如SUN MQ,对于...

    JMS教程

    总结,JMS是Java平台中实现企业级消息传递的重要工具,通过理解其基本概念、API接口以及应用场景,开发者可以有效地构建可扩展、可靠的分布式系统。阅读“JMS教程.pdf”将更深入地了解JMS的细节和实践技巧。

    java-jms小例子

    总结,"java-jms小例子"是一个基础教程,帮助开发者理解如何在Java应用程序中使用JMS进行异步通信。通过创建消息生产者和消费者,设置消息队列或主题,以及发送和接收不同类型的JMS消息,开发者能够掌握JMS的核心...

    JMS标准规范培训教程

    总结,JMS是Java世界中进行消息传递的关键标准,它为分布式系统间的通信提供了一致的接口。SUN JMS 1.1规范是这个领域的基础,而SUN MQ则是这个规范的一个实现例证。通过深入学习"JMS规范培训教程",开发者能够更好...

    Spring发送接收JMS消息

    总结 Spring的JMS支持使得在应用中使用消息传递变得简单且灵活。通过配置`ConnectionFactory`、`JmsTemplate`和消息监听器,我们可以方便地实现消息的发送和接收,从而提高系统的可扩展性和解耦性。同时,Spring...

    JMS实现的信息的广播订阅

    总结起来,JMS的广播订阅模式通过Topic实现了高效的消息广播,使得多个订阅者能同时接收到相同的消息。这一特性在构建大型分布式系统、事件驱动架构以及实时通知系统中非常有价值。理解和熟练运用JMS广播订阅,能够...

    一个简单的JMS客户端应用

    总结,一个简单的JMS客户端应用涉及到连接管理、会话创建、消息生产和消费等多个环节,利用JMS提供的API实现异步、可靠的通信。理解并掌握这些基本概念和操作是构建高效、可扩展的企业级应用的关键。

    Spring-JMS把企业消息处理变容易.doc

    总结起来,Spring JMS通过提供高级抽象和模板类,降低了使用JMS的复杂度,使得开发者可以更加专注于业务逻辑,而不是底层消息传递的细节。同时,它与IBM WebSphere MQ等JMS提供者的无缝集成,使得消息传递变得更加...

    jms+sping+activeMq的例子serd和recevice

    总结来说,这个案例将教授初学者如何利用Spring框架集成ActiveMQ,创建一个简单的JMS应用,实现消息的发送和接收。通过学习这个案例,开发者可以更好地理解和掌握异步通信的原理以及Spring对JMS的支持。

    jms培训PPT

    总结来说,JMS作为Java平台上的消息中间件标准,为分布式系统中的组件间通信提供了强大的支持。理解和掌握JMS对于开发高可靠、高性能的企业级应用至关重要。通过学习和实践,我们可以利用JMS来提升系统的可扩展性、...

    JMX与JMS的概念

    总结来说,**JMX** 和 **JMS** 在目的和功能上有着明显的区别。**JMX** 关注于管理和监控,而 **JMS** 则专注于消息的传递。在实际应用中,两者可以协同工作,例如,JMX 可用于监控消息队列的状态,而 JMS 负责消息...

    WebSphere MQ开发JMS

    总结来说,【WebSphere MQ开发JMS】涉及到使用EJB组件,特别是SSB和MDB,通过JMS进行消息通信,并利用JNDI来管理和查找资源。配置WebSphere MQ作为消息中间件,确保消息传递的正确性和可靠性。这种架构适用于需要...

    weblogic中配置JMS及其测试程序

    总结,配置WebLogic中的JMS涉及创建JMS模块、定义目的地、配置服务器和连接工厂,编写生产者和消费者程序,部署并测试。在实际环境中,还需要关注监控、故障排查以及实现高可用性和扩展性。复件 weblogic中配置JMS...

    Spring+JMS+ActiveMQ+Tomcat jar下载

    总结起来,"Spring+JMS+ActiveMQ+Tomcat"的组合为企业级应用提供了一套高效、可靠的异步消息处理方案。Spring简化了开发流程,JMS提供了消息传输的标准,ActiveMQ保证了消息传递的稳定,而Tomcat则提供了运行环境。...

    jms文档资料(三份)

    总结,JMS作为Java平台上的消息服务标准,提供了强大且灵活的异步通信能力,是构建可扩展、高可用企业级系统的重要工具。理解并掌握JMS的概念和使用方法,对于提升系统的稳定性和效率具有重要意义。

Global site tag (gtag.js) - Google Analytics