问题一:为什么要整合ActiveMQ?
传统的JDBC代码在处理连接、语句、结果集和异常时是多么冗长和繁杂你一定不会忘记,传统的JMS继承了JDBC的“关荣传统”。发送一个简单的消息,要几行代码呢?请仔细数数吧。
Java代码
以下是引用片段: public void sendMessage() throws JMSException { ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory( “tcp://localhost:61616”); Connection connection = null; Session session=null; try { connection = (Connection) connectionFactory.createConnection();//创建连接 session = (Session) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);//创建会话 Destination destination = session.createQueue(“myQueue”); MessageProducer producer = session.createProducer(destination); TextMessage message = session.createTextMessage(expectedBody); message.setStringProperty(“headname”, “remoteB”); producer.send(message); connection.close(); } catch (Exception e) { e.printStackTrace(); }finally{ try { if(session!=null){ session.close(); } if(connection!=null){ connection=null; } } catch (Exception e) { } } } public void sendMessage() throws JMSException { ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory( “tcp://localhost:61616”); Connection connection = null; Session session=null; try { connection = (Connection) connectionFactory.createConnection();//创建连接 session = (Session) connection.createSession(false, Session.AUTO_ACKNOWLEDGE);//创建会话 Destination destination = session.createQueue(“myQueue”); MessageProducer producer = session.createProducer(destination); TextMessage message = session.createTextMessage(expectedBody); message.setStringProperty(“headname”, “remoteB”); producer.send(message); connection.close(); } catch (Exception e) { e.printStackTrace(); }finally{ try { if(session!=null){ session.close(); } if(connection!=null){ connection=null; } } catch (Exception e) { } } } |
传统接受消息而是类似的代码,其实我们的目的就是发送和接受消息。幸运的是Spring为我们提供了大量的模板。项目一期用的较多的是JdbCTemplate,spring也为我们提供了JMSTemplate模板。
问题二:JMSTemplate模板该如何配置呢?
类似于jdbcTemplate,首先要配置一个ConnectionFactory,我们采用ActiveMQ5.2作为消息服务器。之后要开始配置JmsTemplate模板了。最后是配置消息目标了。消息分为队列和主题两大类,因此要配置两个消息目标了。
Java代码
以下是引用片段: <!– ActiveMQ –> <!– 配置JMS连接工厂 –> <bean id=”JmsConnectionFactory” class=”org.apache.activemq.spring.ActiveMQConnectionFactory”> <property name=”brokerURL” value=”tcp://localhost:61616″/> </bean> <!– 配置JMS模版 –> <bean id=”JmsTemplate” class=”org.springframework.jms.core.JmsTemplate”> <property name=”connectionFactory” ref=”JmsConnectionFactory”/> </bean> <!– 发送消息的目的地(队列) –> <bean id=”QueueDestination” class=”org.apache.activemq.command.ActiveMQQueue”> <!– 设置消息队列的名字 –> <constructor-arg index=”0″ value=”HelloWorldQueue”/> </bean> <!– 发送消息的目的地(主题) –> <bean id=”TopicDestination” class=”org.apache.activemq.command.ActiveMQTopic”> <!– 设置消息主题的名字 –> <constructor-arg index=”0″ value=”FlexTopic”/> </bean> <!– ActiveMQ –> <!– 配置JMS连接工厂 –> <bean id=”JmsConnectionFactory” class=”org.apache.activemq.spring.ActiveMQConnectionFactory”> <property name=”brokerURL” value=”tcp://localhost:61616″/> </bean> <!– 配置JMS模版 –> <bean id=”JmsTemplate” class=”org.springframework.jms.core.JmsTemplate”> <property name=”connectionFactory” ref=”JmsConnectionFactory”/> </bean> <!– 发送消息的目的地(队列) –> <bean id=”QueueDestination” class=”org.apache.activemq.command.ActiveMQQueue”> <!– 设置消息队列的名字 –> <constructor-arg index=”0″ value=”HelloWorldQueue”/> </bean> <!– 发送消息的目的地(主题) –> <bean id=”TopicDestination” class=”org.apache.activemq.command.ActiveMQTopic”> <!– 设置消息主题的名字 –> <constructor-arg index=”0″ value=”FlexTopic”/> </bean> |
问题三:如何使用JmsTemplate发送消息呢?
spring的beanfactory得到一个jmsTemplate的实例和消息目标的实例,发送消息,够简单的吧。看看代码:
Java代码
以下是引用片段: JmsTemplate template = (JmsTemplate) SpringContext.getBean(“JmsTemplate”); ActiveMQTopic destination=(ActiveMQTopic)SpringContext.getBean(“TopicDestination”); template.send((javax.jms.Destination) destination, new MessageCreator(){ public Message createMessage(Session session) throws JMSException { return session.createTextMessage(“hello”); } }); JmsTemplate template = (JmsTemplate) SpringContext.getBean(“JmsTemplate”); ActiveMQTopic destination=(ActiveMQTopic)SpringContext.getBean(“TopicDestination”); template.send((javax.jms.Destination) destination, new MessageCreator(){ public Message createMessage(Session session) throws JMSException { return session.createTextMessage(“hello”); } }); |
问题四:上面的代码能不能在简单些?
很多时候,发送消息的目标都是默认的,因此是不是可以在jmsTemplate中设置一个默认的消息目标呢?答案是肯定的。
Java代码
以下是引用片段: <!– 配置JMS模版 –> <bean id=”JmsTemplate” class=”org.springframework.jms.core.JmsTemplate”> <property name=”connectionFactory” ref=”JmsConnectionFactory”/> <property name=”defaultDestination” ref=”TopicDestination”></property> </bean> <!– 配置JMS模版 –> <bean id=”JmsTemplate” class=”org.springframework.jms.core.JmsTemplate”> <property name=”connectionFactory” ref=”JmsConnectionFactory”/> <property name=”defaultDestination” ref=”TopicDestination”></property> </bean> |
发送消息的时候,不指定目标,spring就会调用默认的目标了。
Java代码
以下是引用片段: JmsTemplate template = (JmsTemplate) SpringContext.getBean(“JmsTemplate”); template.send( new MessageCreator(){ public Message createMessage(Session session) throws JMSException { return session.createTextMessage(“hello”); } }); JmsTemplate template = (JmsTemplate) SpringContext.getBean(“JmsTemplate”); template.send( new MessageCreator(){ public Message createMessage(Session session) throws JMSException { return session.createTextMessage(“hello”); } }); |
问题四:jmsTemplate怎么接受信息?
jmsTemplate接收消息十分的简单,只需要调用template.receive()方法,receive方法是同步的,默认情况下,对receive()方法的调用会造成阻塞,知道消息到达目标—-如果必要,永远等下去。为了避免对消息内容等待,可以配置jmsTemplate时,通过设置receiveTimeout属性来指定接收消息超时时间。下面的配置将接收消息的超时时间设置为一分钟(60000毫秒)。
Xml代码
以下是引用片段: <!– 配置JMS模版 –> <bean id=”JmsTemplate” class=”org.springframework.jms.core.JmsTemplate”> <property name=”connectionFactory” ref=”JmsConnectionFactory”/> <property name=”defaultDestination” ref=”TopicDestination”></property> <property name=”receiveTimeout” value=”60000″></property> </bean> <!– 配置JMS模版 –> <bean id=”JmsTemplate” class=”org.springframework.jms.core.JmsTemplate”> <property name=”connectionFactory” ref=”JmsConnectionFactory”/> <property name=”defaultDestination” ref=”TopicDestination”></property> <property name=”receiveTimeout” value=”60000″></property> </bean> |
template.receive()会从默认目标接收消息,如果你希望指定一个目标,可以传一个目标。如:template.receive(“myQueue”).
同步接收消息并不是spring唯一的选择,消息监听器可以实现异步(下篇文章将会介绍消息驱动)。
问题五:怎么自动将消息转化为Java对象?
转化器在很多组件中都是必不缺少的东西。Spring挺过MessageConverter接口提供了对消息转换的支持。
Java代码
以下是引用片段: public class MyMessageConverter implements MessageConverter { @Override public Object fromMessage(Message arg0) throws JMSException, MessageConversionException { // TODO Auto-generated method stub return null; } @Override public Message toMessage(Object arg0, Session arg1) throws JMSException, MessageConversionException { // TODO Auto-generated method stub return null; } } public class MyMessageConverter implements MessageConverter { @Override public Object fromMessage(Message arg0) throws JMSException, MessageConversionException { // TODO Auto-generated method stub return null; } @Override public Message toMessage(Object arg0, Session arg1) throws JMSException, MessageConversionException { // TODO Auto-generated method stub return null; } } |
MessageConverter接口的两个方法简单明了。在发送端toMessage会将java对象转化为消息,在接收端fromMessage会将消息转化为java对象。
下面的代码简单的实现了MessageConverter的两个接口。
以下是引用片段: Java代码 public class MyMessageConverter implements MessageConverter { @Override public Object fromMessage(Message message) throws JMSException, MessageConversionException { if(!(message instanceof MapMessage)){ throw new MessageConversionException(“Messae is not MapMessage”); } MapMessage mapMessage=(MapMessage)message; MessageObj messageObj=new MessageObj(); messageObj.setId(mapMessage.getString(“id”)); messageObj.setInfo(mapMessage.getString(“info”)); return messageObj; } @Override public Message toMessage(Object obj, Session session) throws JMSException, MessageConversionException { if(!(obj instanceof MessageObj)){ throw new MessageConversionException(“obj is not MessageObj”); } MessageObj messageObj=(MessageObj)obj; MapMessage mapMessage=session.createMapMessage(); mapMessage.setString(“id”, messageObj.getId()); mapMessage.setString(“info”, messageObj.getInfo()); return mapMessage; } } public class MyMessageConverter implements MessageConverter { @Override public Object fromMessage(Message message) throws JMSException, MessageConversionException { if(!(message instanceof MapMessage)){ throw new MessageConversionException(“Messae is not MapMessage”); } MapMessage mapMessage=(MapMessage)message; MessageObj messageObj=new MessageObj(); messageObj.setId(mapMessage.getString(“id”)); messageObj.setInfo(mapMessage.getString(“info”)); return messageObj; } @Override public Message toMessage(Object obj, Session session) throws JMSException, MessageConversionException { if(!(obj instanceof MessageObj)){ throw new MessageConversionException(“obj is not MessageObj”); } MessageObj messageObj=(MessageObj)obj; MapMessage mapMessage=session.createMapMessage(); mapMessage.setString(“id”, messageObj.getId()); mapMessage.setString(“info”, messageObj.getInfo()); return mapMessage; } } |
此时,发送和接收消息要换成template.convertAndSend(message);template.receiveAndConvert();
可是jmsTemplate如何知道消息转换器呢?需要在配置jmsTemplate的时候,加上messageConverter属性。
Java代码
以下是引用片段: <!– 配置JMS模版 –> <bean id=”JmsTemplate” class=”org.springframework.jms.core.JmsTemplate”> <property name=”connectionFactory” ref=”JmsConnectionFactory”/> <property name=”defaultDestination” ref=”TopicDestination”></property> <property name=”receiveTimeout” value=”60000″></property> <property name=”messageConverter” ref=”messageObj”></property> </bean> <!– 配置JMS模版 –> <bean id=”JmsTemplate” class=”org.springframework.jms.core.JmsTemplate”> <property name=”connectionFactory” ref=”JmsConnectionFactory”/> <property name=”defaultDestination” ref=”TopicDestination”></property> <property name=”receiveTimeout” value=”60000″></property> <property name=”messageConverter” ref=”messageObj”></property> </bean> |
messageObj是要转化的java对象的bean的id。
我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。
我原创,你原创,我们的内容世界才会更加精彩!
【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】
微信公众号
TechTarget
官方微博
TechTarget中国
作者
相关推荐
-
内存数据网格提供商一头扎进Java
10年的时间里,应用性能解决方案提供商Alachisoft一直在用NCache(针对N-Tier和网格计算.NET应用的内存计算和数据网格产品)为.NET社区服务。
-
遇到这样一个问题:通过java service wrapper部署应用,wrapper进程占用的内存会一直升高, 直到把内存吃完应用崩溃,但是这个wrapper
遇到这样一个问题:通过java service wrapper部署应用,wrapper进程占用的内存会一直升高 […]
-
Google App Engine for Java 对于目前中国需要学习吗?
-
前无古人后无来者的Java平台
开发人员一直在致力于保持Java的活力,经过20年后,我们感觉从来没有更好的、更令人激动的时刻如同Java社区一样。