Bluemix结合RabbitMq实现消息发送与接收实例

      林炳文Evankaka原创作品。转载请注明出处https://blog.csdn.net/Evankaka/article/details/50682197

什么是RabbitMq?

      MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消 息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

什么是Bluemix?

        BlueMix 是 IBM 基于 Cloud Foundry 的开放云架构实现,使您能够快速创建、部署和管理云应用程序。

      本文实现了在Bluemix上绑定rabbitMq,然后在本地运行项目来进行消息的发送和接收。

     本文实例访问:http://javahelloworld2.mybluemix.net/

    本文工程下载:http://download.csdn.net/detail/evankaka/9427970

BluxMix账号注册:https://apps.admin.ibmcloud.com/manage/trial/bluemix.html?cm_mmc=CMDeveloperGCG-_-Bluemix-_-CSDN-_-onlineeventQ2

一、Bluemix项目创建 

1、新建一个Bluemix的web工程

如何创建工程可看基于IBM Bluemix部署Java Web项目实战演练

2、添加RabbitMQ服务


选择CloudMQP


记下以下数据,工程中会用到


进入工程,打开如下页面


此时如果该服务已绑定项目的话,就会弹出如下界面,这个界面说明了如何在客户端来配置RabbitMq的参数,使用客户端能将消息发布的Bluemix这个类似信息中心的地方。如果没有出现此页面,请回去绑定服务到工程!


二、本地运行发布和获取消息

本文是基于Maven工程的。所以,先建一个Maven项目工程。最后整个工程目录如下:


1、添加Jar包依赖


    
    
  1. <properties>
  2. <!-- spring版本号 -->
  3. <spring.version>3.2.8.RELEASE </spring.version>
  4. <!-- log4j日志文件管理包版本 -->
  5. <slf4j.version>1.6.6 </slf4j.version>
  6. <log4j.version>1.2.12 </log4j.version>
  7. <!-- junit版本号 -->
  8. <junit.version>4.10 </junit.version>
  9. </properties>
  10. <dependencies>
  11. <!-- 添加Spring依赖 -->
  12. <dependency>
  13. <groupId>org.springframework </groupId>
  14. <artifactId>spring-core </artifactId>
  15. <version>${spring.version} </version>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework </groupId>
  19. <artifactId>spring-webmvc </artifactId>
  20. <version>${spring.version} </version>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework </groupId>
  24. <artifactId>spring-context </artifactId>
  25. <version>${spring.version} </version>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework </groupId>
  29. <artifactId>spring-context-support </artifactId>
  30. <version>${spring.version} </version>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework </groupId>
  34. <artifactId>spring-aop </artifactId>
  35. <version>${spring.version} </version>
  36. </dependency>
  37. <dependency>
  38. <groupId>org.springframework </groupId>
  39. <artifactId>spring-aspects </artifactId>
  40. <version>${spring.version} </version>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.springframework </groupId>
  44. <artifactId>spring-tx </artifactId>
  45. <version>${spring.version} </version>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.springframework </groupId>
  49. <artifactId>spring-jdbc </artifactId>
  50. <version>${spring.version} </version>
  51. </dependency>
  52. <dependency>
  53. <groupId>org.springframework </groupId>
  54. <artifactId>spring-web </artifactId>
  55. <version>${spring.version} </version>
  56. </dependency>
  57. <!--单元测试依赖 -->
  58. <dependency>
  59. <groupId>junit </groupId>
  60. <artifactId>junit </artifactId>
  61. <version>${junit.version} </version>
  62. <scope>test </scope>
  63. </dependency>
  64. <!-- 日志文件管理包 -->
  65. <!-- log start -->
  66. <dependency>
  67. <groupId>log4j </groupId>
  68. <artifactId>log4j </artifactId>
  69. <version>${log4j.version} </version>
  70. </dependency>
  71. <dependency>
  72. <groupId>org.slf4j </groupId>
  73. <artifactId>slf4j-api </artifactId>
  74. <version>${slf4j.version} </version>
  75. </dependency>
  76. <dependency>
  77. <groupId>org.slf4j </groupId>
  78. <artifactId>slf4j-log4j12 </artifactId>
  79. <version>${slf4j.version} </version>
  80. </dependency>
  81. <!-- log end -->
  82. <!--spring单元测试依赖 -->
  83. <dependency>
  84. <groupId>org.springframework </groupId>
  85. <artifactId>spring-test </artifactId>
  86. <version>${spring.version} </version>
  87. <scope>test </scope>
  88. </dependency>
  89. <!--rabbitmq依赖 -->
  90. <dependency>
  91. <groupId>org.springframework.amqp </groupId>
  92. <artifactId>spring-rabbit </artifactId>
  93. <version>1.4.5.RELEASE </version>
  94. </dependency>
  95. <!-- <dependency> -->
  96. <!-- <groupId>com.rabbitmq</groupId> -->
  97. <!-- <artifactId>amqp-client</artifactId> -->
  98. <!-- <version>3.3.4</version> -->
  99. <!-- </dependency> -->
  100. <dependency>
  101. <groupId>javax.validation </groupId>
  102. <artifactId>validation-api </artifactId>
  103. <version>1.1.0.Final </version>
  104. </dependency>
2、消息发送者

MessageProducer.java内容如下:


    
    
  1. package com.lin.producer;
  2. import javax.annotation.Resource;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.amqp.core.AmqpTemplate;
  6. import org.springframework.stereotype.Service;
  7. /**
  8. * 功能概要:消息产生,提交到队列中去
  9. *
  10. * @author linbingwen
  11. * @since 2016年1月15日
  12. */
  13. @Service
  14. public class MessageProducer {
  15. private Logger logger = LoggerFactory.getLogger(MessageProducer.class);
  16. @Resource
  17. private AmqpTemplate amqpTemplate;
  18. public void sendMessage(Object message){
  19. logger.info( "to send message:{}",message);
  20. amqpTemplate.convertAndSend( "queueTestKey",message);
  21. }
  22. }

3、消息接收者

MessageConsumer.java内容如下:


    
    
  1. package com.lin.consumer;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.amqp.core.Message;
  5. import org.springframework.amqp.core.MessageListener;
  6. /**
  7. * 功能概要:消费接收
  8. *
  9. * @author linbingwen
  10. * @since 2016年1月15日
  11. */
  12. public class MessageConsumer implements MessageListener {
  13. private Logger logger = LoggerFactory.getLogger(MessageConsumer.class);
  14. @Override
  15. public void onMessage(Message message) {
  16. logger.info( "receive message:{}",message.toString());
  17. }
  18. }

4、定义消息服务中心

这里笔者在rabbitmq.xml将消息生产和消息者都写在一个文件当中,您也可以分开写。配置基本一样。


    
    
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit= "http://www.springframework.org/schema/rabbit"
  4. xsi:schemaLocation= "http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  8. http://www.springframework.org/schema/rabbit
  9. http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
  10. <!--配置connection-factory,指定连接rabbit server参数 -->
  11. <rabbit:connection-factory id="connectionFactory"
  12. username= "zqwocdmu" password= "DRR6tF7DCuEq7ugHwlBP8A9zTwu6jI8D" host = "white-swan.rmq.cloudamqp.com" virtual-host= "zqwocdmu" />
  13. <!--定义rabbit template用于数据的接收和发送 -->
  14. <rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
  15. exchange= "exchangeTest" />
  16. <!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
  17. <rabbit:admin connection-factory="connectionFactory" />
  18. <!--定义queue -->
  19. <rabbit:queue name="queueTest" durable="true" auto-delete="false" exclusive="false" />
  20. <!-- 定义direct exchange,绑定queueTest -->
  21. <rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false">
  22. <rabbit:bindings>
  23. <rabbit:binding queue="queueTest" key="queueTestKey"> </rabbit:binding>
  24. </rabbit:bindings>
  25. </rabbit:direct-exchange>
  26. <!-- 消息接收者 -->
  27. <bean id="messageReceiver" class="com.lin.consumer.MessageConsumer"> </bean>
  28. <!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象-->
  29. <rabbit:listener-container connection-factory="connectionFactory">
  30. <rabbit:listener queues="queueTest" ref="messageReceiver"/>
  31. </rabbit:listener-container>
  32. </beans>
其中配置内容和Bluemix上的对应关系如下:

5、Spring中加载rabbitmq.xml的配置内容

整个application.xml内容如下:


    
    
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:context= "http://www.springframework.org/schema/context"
  4. xmlns:p= "http://www.springframework.org/schema/p"
  5. xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  6. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
  7. <import resource="classpath*:rabbitmq.xml" />
  8. <!-- 扫描指定package下所有带有如@controller,@services,@resource,@ods并把所注释的注册为Spring Beans -->
  9. <context:component-scan base-package="com.lin.consumer,com.lin.producer" />
  10. <!-- 激活annotation功能 -->
  11. <context:annotation-config />
  12. <!-- 激活annotation功能 -->
  13. <context:spring-configured />
  14. </beans>
6、测试消息服务

这里笔者简单写了一个不断发送消息和一个不断接收消息的测试


    
    
  1. package com.lin;
  2. import javax.annotation.Resource;
  3. import org.junit.Before;
  4. import org.junit.Test;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.amqp.core.AmqpTemplate;
  8. import org.springframework.context.ApplicationContext;
  9. import org.springframework.context.support.ClassPathXmlApplicationContext;
  10. import org.springframework.retry.backoff.Sleeper;
  11. import com.lin.producer.MessageProducer;
  12. /**
  13. * 功能概要:
  14. *
  15. * @author linbingwen
  16. * @since 2016年1月15日
  17. */
  18. public class MessageTest {
  19. private Logger logger = LoggerFactory.getLogger(MessageTest.class);
  20. private ApplicationContext context = null;
  21. @Before
  22. public void setUp() throws Exception {
  23. context = new ClassPathXmlApplicationContext( "application.xml");
  24. }
  25. @Test
  26. public void should_send_a_amq_message() throws Exception {
  27. MessageProducer messageProducer = (MessageProducer) context.getBean( "messageProducer");
  28. int a = Integer.MAX_VALUE;
  29. while (a > 0) {
  30. messageProducer.sendMessage( "Hello, I am amq sender num :" + a--);
  31. try {
  32. //暂停一下,好让消息消费者去取消息打印出来
  33. Thread.sleep( 1000);
  34. } catch (InterruptedException e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. }
  39. }
来看看Eclipse上运行的结果:

可以看到,消息不断的产生和消费。


当然,您也可以进入到RabbitMq的消息服务中心,点击如下:


点击进去如下显示,这里可以看到消息队列、当前的连接数


queueTest就是上面的代码中配置的队列


还可以看到其消息生产和消费的速度等。


三、web项目中来使用rabbitMq

1、定义一个页面用来发消息和接消息:


    
    
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <script src="<%=request.getContextPath()%>/static/js/jquery-2.1.4.min.js"> </script>
  6. </head>
  7. <body>
  8. <h2>Hello World! </h2>
  9. <div>
  10. <textarea rows="10" cols="40" id = "msg"> </textarea>
  11. </div>
  12. <div>
  13. <button id = "sendMsg">发送消息 </button>
  14. <button id = "recvMsg">接收消息 </button>
  15. </div>
  16. </body>
  17. <script type="text/javascript">
  18. $( document).ready( function(){
  19. //获取当前项目的路径
  20. var urlRootContext = ( function () {
  21. var strPath = window.document.location.pathname;
  22. var postPath = strPath.substring( 0, strPath.substr( 1).indexOf( '/') + 1);
  23. return postPath;
  24. })();
  25. $( "#sendMsg").click( function(){
  26. var msg = $( '#msg').val();
  27. if (msg == '') {
  28. alert( '请输入消息内容 ');
  29. return false;
  30. }
  31. $.ajax( {
  32. url:urlRootContext + '/sendMsg', // 跳转到 action
  33. data:{
  34. message :msg ,
  35. },
  36. type: 'POST',
  37. async: false,
  38. dataType: 'json',
  39. success: function(data) {
  40. console.log(data);
  41. alert( "发送信息成功!");
  42. },
  43. error: function(xhr, type, exception) {
  44. alert( "服务器异常,请稍候重试!");
  45. console.log(xhr);
  46. console.log(type);
  47. console.log(exception);
  48. }
  49. });
  50. });
  51. $( "#recvMsg").click( function(){
  52. $.ajax( {
  53. url:urlRootContext + '/revcMsg', // 跳转到 action
  54. type: 'POST',
  55. async: false,
  56. dataType: 'json',
  57. success: function(data) {
  58. console.log(data);
  59. alert( "接收一条消息成功!,消息为:" + data.string);
  60. },
  61. error: function(xhr, type, exception) {
  62. alert( "服务器异常,请稍候重试!");
  63. console.log(xhr);
  64. console.log(type);
  65. console.log(exception);
  66. }
  67. });
  68. });
  69. });
  70. </script>
  71. </html>
其中,发消息和接消息都是通过ajax的方式来传递到Controller层中,然后返回json数据到前台。

页面效果如下:


2、Controller层:

这里需要注意的是消息生产者是的数据服务中心是使用rabbitmq.xml里的配置,但是消息消费都这里是用Java代码来实现的。


    
    
  1. package com.lin.controller;
  2. import java.io.IOException;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import javax.annotation.Resource;
  6. import net.sf.json.JSONObject;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import org.springframework.stereotype.Controller;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.ResponseBody;
  12. import com.lin.consumer.MessageConsumer;
  13. import com.lin.producer.MessageProducer;
  14. import com.rabbitmq.client.Channel;
  15. import com.rabbitmq.client.Connection;
  16. import com.rabbitmq.client.ConnectionFactory;
  17. import com.rabbitmq.client.ConsumerCancelledException;
  18. import com.rabbitmq.client.QueueingConsumer;
  19. import com.rabbitmq.client.ShutdownSignalException;
  20. import com.rabbitmq.client.QueueingConsumer.Delivery;
  21. /**
  22. * 功能概要:UserController
  23. *
  24. * @author linbingwen
  25. * @since 2015年9月28日
  26. */
  27. @Controller
  28. public class MessageController {
  29. @Resource
  30. private MessageProducer messageProducer;
  31. private Logger logger = LoggerFactory.getLogger(getClass());
  32. /**
  33. * 显示首页
  34. * @author linbingwen
  35. * @since 2015年10月23日
  36. * @return
  37. */
  38. @RequestMapping( "/test")
  39. public String message(){
  40. logger.info( "open message.jsp");
  41. return "message";
  42. }
  43. /**
  44. * 用来发送消息
  45. * @author linbingwen
  46. * @since 2016年2月19日
  47. * @param message
  48. * @return
  49. */
  50. @RequestMapping( "/sendMsg")
  51. @ResponseBody
  52. public String sendMsg(String message) {
  53. logger.info( "to send message:{}",message);
  54. messageProducer.sendMessage(message);
  55. Map<String,Object> map = new HashMap<String,Object>();
  56. map.put( "flag", true);
  57. JSONObject jsonObject = JSONObject.fromObject(map);
  58. return jsonObject.toString();
  59. }
  60. /**
  61. * 用来接收消息
  62. * @author linbingwen
  63. * @since 2016年2月19日
  64. * @param message
  65. * @return
  66. */
  67. @RequestMapping( "/revcMsg")
  68. @ResponseBody
  69. public String revcMsg() {
  70. String string = getMsg();
  71. if (string != null) {
  72. } else {
  73. string = "null";
  74. }
  75. Map<String,Object> map = new HashMap<String,Object>();
  76. map.put( "string", string);
  77. JSONObject jsonObject = JSONObject.fromObject(map);
  78. return jsonObject.toString();
  79. }
  80. public String getMsg() {
  81. ConnectionFactory connFac = new ConnectionFactory() ;
  82. connFac.setHost( "white-swan.rmq.cloudamqp.com");
  83. connFac.setPassword( "DRR6tF7DCuEq7ugHwlBP8A9zTwu6jI8D");
  84. connFac.setUsername( "zqwocdmu");
  85. connFac.setVirtualHost( "zqwocdmu");
  86. Connection conn = null;
  87. try {
  88. conn = connFac.newConnection();
  89. } catch (IOException e) {
  90. e.printStackTrace();
  91. }
  92. Channel channel = null;
  93. try {
  94. channel = conn.createChannel();
  95. } catch (IOException e) {
  96. e.printStackTrace();
  97. }
  98. String queueName = "queueTest";
  99. try {
  100. channel.queueDeclare(queueName, true, false, false, null) ;
  101. } catch (IOException e) {
  102. e.printStackTrace();
  103. }
  104. //配置好获取消息的方式
  105. QueueingConsumer consumer = new QueueingConsumer(channel) ;
  106. try {
  107. channel.basicConsume(queueName, true, consumer) ;
  108. } catch (IOException e) {
  109. e.printStackTrace();
  110. }
  111. // //循环获取消息
  112. // while(true){
  113. //获取消息,如果没有消息,这一步将会一直阻塞
  114. Delivery delivery = null;
  115. try {
  116. delivery = consumer.nextDelivery();
  117. } catch (ShutdownSignalException e) {
  118. e.printStackTrace();
  119. } catch (ConsumerCancelledException e) {
  120. e.printStackTrace();
  121. } catch (InterruptedException e) {
  122. e.printStackTrace();
  123. }
  124. String msg = new String(delivery.getBody()) ;
  125. System.out.println( "received message[" + msg + "] from " + queueName);
  126. // }
  127. try {
  128. conn.close();
  129. } catch (IOException e) {
  130. e.printStackTrace();
  131. }
  132. return msg;
  133. }
  134. }

3、rabbitMq.xml内容如下:

和上面的工程相比,去掉了消息监听器。而把它放在Controller层中来使用。就是上面的getMsg()代码。


    
    
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit= "http://www.springframework.org/schema/rabbit"
  4. xsi:schemaLocation= "http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  8. http://www.springframework.org/schema/rabbit
  9. http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
  10. <!--配置connection-factory,指定连接rabbit server参数 -->
  11. <!-- <rabbit:connection-factory id="connectionFactory" -->
  12. <!-- username="asdf" password="123456" host="10.75.4.25" port="5672" /> -->
  13. <rabbit:connection-factory id="connectionFactory"
  14. username= "zqwocdmu" password= "DRR6tF7DCuEq7ugHwlBP8A9zTwu6jI8D" host = "white-swan.rmq.cloudamqp.com" virtual-host= "zqwocdmu" />
  15. <!--定义rabbit template用于数据的接收和发送 -->
  16. <rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
  17. exchange= "exchangeTest" />
  18. <!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
  19. <rabbit:admin connection-factory="connectionFactory" />
  20. <!--定义queue -->
  21. <rabbit:queue name="queueTest" durable="true" auto-delete="false" exclusive="false" />
  22. <!-- 定义direct exchange,绑定queueTest -->
  23. <rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false">
  24. <rabbit:bindings>
  25. <rabbit:binding queue="queueTest" key="queueTestKey"> </rabbit:binding>
  26. </rabbit:bindings>
  27. </rabbit:direct-exchange>
  28. <!-- 消息接收者 -->
  29. <!-- <bean id="messageReceiver" class="com.lin.consumer.MessageConsumer"></bean> -->
  30. <!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象-->
  31. <!-- <rabbit:listener-container connection-factory="connectionFactory"> -->
  32. <!-- <rabbit:listener queues="queueTest" ref="messageReceiver"/> -->
  33. <!-- </rabbit:listener-container> -->
  34. </beans>

这是给远程的Bluemix上绑定的服务中心发消息,

这是获取消息


当然,也可以看日志:



最后一步打war包,然后上传到Bluemix中心即可:

发送消息


接收消息:

(这里要注意一定要先发送消息,要不接收消息会一直阻塞会去,整个页面会卡死,而且接收消息的过程非常缓慢,请耐心等待!)


  本文实例访问:http://javahelloworld2.mybluemix.net/

   本文工程下载:http://download.csdn.net/detail/evankaka/9427970


      林炳文Evankaka原创作品。转载请注明出处https://blog.csdn.net/Evankaka/article/details/50682197

什么是RabbitMq?

      MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。消 息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术。排队指的是应用程序通过 队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求。

什么是Bluemix?

        BlueMix 是 IBM 基于 Cloud Foundry 的开放云架构实现,使您能够快速创建、部署和管理云应用程序。

      本文实现了在Bluemix上绑定rabbitMq,然后在本地运行项目来进行消息的发送和接收。

     本文实例访问:http://javahelloworld2.mybluemix.net/

    本文工程下载:http://download.csdn.net/detail/evankaka/9427970

BluxMix账号注册:https://apps.admin.ibmcloud.com/manage/trial/bluemix.html?cm_mmc=CMDeveloperGCG-_-Bluemix-_-CSDN-_-onlineeventQ2

一、Bluemix项目创建 

1、新建一个Bluemix的web工程

如何创建工程可看基于IBM Bluemix部署Java Web项目实战演练

2、添加RabbitMQ服务


选择CloudMQP


记下以下数据,工程中会用到


进入工程,打开如下页面


此时如果该服务已绑定项目的话,就会弹出如下界面,这个界面说明了如何在客户端来配置RabbitMq的参数,使用客户端能将消息发布的Bluemix这个类似信息中心的地方。如果没有出现此页面,请回去绑定服务到工程!


二、本地运行发布和获取消息

本文是基于Maven工程的。所以,先建一个Maven项目工程。最后整个工程目录如下:


1、添加Jar包依赖


  
  
  1. <properties>
  2. <!-- spring版本号 -->
  3. <spring.version>3.2.8.RELEASE </spring.version>
  4. <!-- log4j日志文件管理包版本 -->
  5. <slf4j.version>1.6.6 </slf4j.version>
  6. <log4j.version>1.2.12 </log4j.version>
  7. <!-- junit版本号 -->
  8. <junit.version>4.10 </junit.version>
  9. </properties>
  10. <dependencies>
  11. <!-- 添加Spring依赖 -->
  12. <dependency>
  13. <groupId>org.springframework </groupId>
  14. <artifactId>spring-core </artifactId>
  15. <version>${spring.version} </version>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework </groupId>
  19. <artifactId>spring-webmvc </artifactId>
  20. <version>${spring.version} </version>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework </groupId>
  24. <artifactId>spring-context </artifactId>
  25. <version>${spring.version} </version>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework </groupId>
  29. <artifactId>spring-context-support </artifactId>
  30. <version>${spring.version} </version>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework </groupId>
  34. <artifactId>spring-aop </artifactId>
  35. <version>${spring.version} </version>
  36. </dependency>
  37. <dependency>
  38. <groupId>org.springframework </groupId>
  39. <artifactId>spring-aspects </artifactId>
  40. <version>${spring.version} </version>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.springframework </groupId>
  44. <artifactId>spring-tx </artifactId>
  45. <version>${spring.version} </version>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.springframework </groupId>
  49. <artifactId>spring-jdbc </artifactId>
  50. <version>${spring.version} </version>
  51. </dependency>
  52. <dependency>
  53. <groupId>org.springframework </groupId>
  54. <artifactId>spring-web </artifactId>
  55. <version>${spring.version} </version>
  56. </dependency>
  57. <!--单元测试依赖 -->
  58. <dependency>
  59. <groupId>junit </groupId>
  60. <artifactId>junit </artifactId>
  61. <version>${junit.version} </version>
  62. <scope>test </scope>
  63. </dependency>
  64. <!-- 日志文件管理包 -->
  65. <!-- log start -->
  66. <dependency>
  67. <groupId>log4j </groupId>
  68. <artifactId>log4j </artifactId>
  69. <version>${log4j.version} </version>
  70. </dependency>
  71. <dependency>
  72. <groupId>org.slf4j </groupId>
  73. <artifactId>slf4j-api </artifactId>
  74. <version>${slf4j.version} </version>
  75. </dependency>
  76. <dependency>
  77. <groupId>org.slf4j </groupId>
  78. <artifactId>slf4j-log4j12 </artifactId>
  79. <version>${slf4j.version} </version>
  80. </dependency>
  81. <!-- log end -->
  82. <!--spring单元测试依赖 -->
  83. <dependency>
  84. <groupId>org.springframework </groupId>
  85. <artifactId>spring-test </artifactId>
  86. <version>${spring.version} </version>
  87. <scope>test </scope>
  88. </dependency>
  89. <!--rabbitmq依赖 -->
  90. <dependency>
  91. <groupId>org.springframework.amqp </groupId>
  92. <artifactId>spring-rabbit </artifactId>
  93. <version>1.4.5.RELEASE </version>
  94. </dependency>
  95. <!-- <dependency> -->
  96. <!-- <groupId>com.rabbitmq</groupId> -->
  97. <!-- <artifactId>amqp-client</artifactId> -->
  98. <!-- <version>3.3.4</version> -->
  99. <!-- </dependency> -->
  100. <dependency>
  101. <groupId>javax.validation </groupId>
  102. <artifactId>validation-api </artifactId>
  103. <version>1.1.0.Final </version>
  104. </dependency>
2、消息发送者

MessageProducer.java内容如下:


  
  
  1. package com.lin.producer;
  2. import javax.annotation.Resource;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.amqp.core.AmqpTemplate;
  6. import org.springframework.stereotype.Service;
  7. /**
  8. * 功能概要:消息产生,提交到队列中去
  9. *
  10. * @author linbingwen
  11. * @since 2016年1月15日
  12. */
  13. @Service
  14. public class MessageProducer {
  15. private Logger logger = LoggerFactory.getLogger(MessageProducer.class);
  16. @Resource
  17. private AmqpTemplate amqpTemplate;
  18. public void sendMessage(Object message){
  19. logger.info( "to send message:{}",message);
  20. amqpTemplate.convertAndSend( "queueTestKey",message);
  21. }
  22. }

3、消息接收者

MessageConsumer.java内容如下:


  
  
  1. package com.lin.consumer;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.amqp.core.Message;
  5. import org.springframework.amqp.core.MessageListener;
  6. /**
  7. * 功能概要:消费接收
  8. *
  9. * @author linbingwen
  10. * @since 2016年1月15日
  11. */
  12. public class MessageConsumer implements MessageListener {
  13. private Logger logger = LoggerFactory.getLogger(MessageConsumer.class);
  14. @Override
  15. public void onMessage(Message message) {
  16. logger.info( "receive message:{}",message.toString());
  17. }
  18. }

4、定义消息服务中心

这里笔者在rabbitmq.xml将消息生产和消息者都写在一个文件当中,您也可以分开写。配置基本一样。


  
  
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit= "http://www.springframework.org/schema/rabbit"
  4. xsi:schemaLocation= "http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  8. http://www.springframework.org/schema/rabbit
  9. http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
  10. <!--配置connection-factory,指定连接rabbit server参数 -->
  11. <rabbit:connection-factory id="connectionFactory"
  12. username= "zqwocdmu" password= "DRR6tF7DCuEq7ugHwlBP8A9zTwu6jI8D" host = "white-swan.rmq.cloudamqp.com" virtual-host= "zqwocdmu" />
  13. <!--定义rabbit template用于数据的接收和发送 -->
  14. <rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
  15. exchange= "exchangeTest" />
  16. <!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
  17. <rabbit:admin connection-factory="connectionFactory" />
  18. <!--定义queue -->
  19. <rabbit:queue name="queueTest" durable="true" auto-delete="false" exclusive="false" />
  20. <!-- 定义direct exchange,绑定queueTest -->
  21. <rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false">
  22. <rabbit:bindings>
  23. <rabbit:binding queue="queueTest" key="queueTestKey"> </rabbit:binding>
  24. </rabbit:bindings>
  25. </rabbit:direct-exchange>
  26. <!-- 消息接收者 -->
  27. <bean id="messageReceiver" class="com.lin.consumer.MessageConsumer"> </bean>
  28. <!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象-->
  29. <rabbit:listener-container connection-factory="connectionFactory">
  30. <rabbit:listener queues="queueTest" ref="messageReceiver"/>
  31. </rabbit:listener-container>
  32. </beans>
其中配置内容和Bluemix上的对应关系如下:

5、Spring中加载rabbitmq.xml的配置内容

整个application.xml内容如下:


  
  
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:context= "http://www.springframework.org/schema/context"
  4. xmlns:p= "http://www.springframework.org/schema/p"
  5. xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  6. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
  7. <import resource="classpath*:rabbitmq.xml" />
  8. <!-- 扫描指定package下所有带有如@controller,@services,@resource,@ods并把所注释的注册为Spring Beans -->
  9. <context:component-scan base-package="com.lin.consumer,com.lin.producer" />
  10. <!-- 激活annotation功能 -->
  11. <context:annotation-config />
  12. <!-- 激活annotation功能 -->
  13. <context:spring-configured />
  14. </beans>
6、测试消息服务

这里笔者简单写了一个不断发送消息和一个不断接收消息的测试


  
  
  1. package com.lin;
  2. import javax.annotation.Resource;
  3. import org.junit.Before;
  4. import org.junit.Test;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.amqp.core.AmqpTemplate;
  8. import org.springframework.context.ApplicationContext;
  9. import org.springframework.context.support.ClassPathXmlApplicationContext;
  10. import org.springframework.retry.backoff.Sleeper;
  11. import com.lin.producer.MessageProducer;
  12. /**
  13. * 功能概要:
  14. *
  15. * @author linbingwen
  16. * @since 2016年1月15日
  17. */
  18. public class MessageTest {
  19. private Logger logger = LoggerFactory.getLogger(MessageTest.class);
  20. private ApplicationContext context = null;
  21. @Before
  22. public void setUp() throws Exception {
  23. context = new ClassPathXmlApplicationContext( "application.xml");
  24. }
  25. @Test
  26. public void should_send_a_amq_message() throws Exception {
  27. MessageProducer messageProducer = (MessageProducer) context.getBean( "messageProducer");
  28. int a = Integer.MAX_VALUE;
  29. while (a > 0) {
  30. messageProducer.sendMessage( "Hello, I am amq sender num :" + a--);
  31. try {
  32. //暂停一下,好让消息消费者去取消息打印出来
  33. Thread.sleep( 1000);
  34. } catch (InterruptedException e) {
  35. e.printStackTrace();
  36. }
  37. }
  38. }
  39. }
来看看Eclipse上运行的结果:

可以看到,消息不断的产生和消费。


当然,您也可以进入到RabbitMq的消息服务中心,点击如下:


点击进去如下显示,这里可以看到消息队列、当前的连接数


queueTest就是上面的代码中配置的队列


还可以看到其消息生产和消费的速度等。


三、web项目中来使用rabbitMq

1、定义一个页面用来发消息和接消息:


  
  
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <script src="<%=request.getContextPath()%>/static/js/jquery-2.1.4.min.js"> </script>
  6. </head>
  7. <body>
  8. <h2>Hello World! </h2>
  9. <div>
  10. <textarea rows="10" cols="40" id = "msg"> </textarea>
  11. </div>
  12. <div>
  13. <button id = "sendMsg">发送消息 </button>
  14. <button id = "recvMsg">接收消息 </button>
  15. </div>
  16. </body>
  17. <script type="text/javascript">
  18. $( document).ready( function(){
  19. //获取当前项目的路径
  20. var urlRootContext = ( function () {
  21. var strPath = window.document.location.pathname;
  22. var postPath = strPath.substring( 0, strPath.substr( 1).indexOf( '/') + 1);
  23. return postPath;
  24. })();
  25. $( "#sendMsg").click( function(){
  26. var msg = $( '#msg').val();
  27. if (msg == '') {
  28. alert( '请输入消息内容 ');
  29. return false;
  30. }
  31. $.ajax( {
  32. url:urlRootContext + '/sendMsg', // 跳转到 action
  33. data:{
  34. message :msg ,
  35. },
  36. type: 'POST',
  37. async: false,
  38. dataType: 'json',
  39. success: function(data) {
  40. console.log(data);
  41. alert( "发送信息成功!");
  42. },
  43. error: function(xhr, type, exception) {
  44. alert( "服务器异常,请稍候重试!");
  45. console.log(xhr);
  46. console.log(type);
  47. console.log(exception);
  48. }
  49. });
  50. });
  51. $( "#recvMsg").click( function(){
  52. $.ajax( {
  53. url:urlRootContext + '/revcMsg', // 跳转到 action
  54. type: 'POST',
  55. async: false,
  56. dataType: 'json',
  57. success: function(data) {
  58. console.log(data);
  59. alert( "接收一条消息成功!,消息为:" + data.string);
  60. },
  61. error: function(xhr, type, exception) {
  62. alert( "服务器异常,请稍候重试!");
  63. console.log(xhr);
  64. console.log(type);
  65. console.log(exception);
  66. }
  67. });
  68. });
  69. });
  70. </script>
  71. </html>
其中,发消息和接消息都是通过ajax的方式来传递到Controller层中,然后返回json数据到前台。

页面效果如下:


2、Controller层:

这里需要注意的是消息生产者是的数据服务中心是使用rabbitmq.xml里的配置,但是消息消费都这里是用Java代码来实现的。


  
  
  1. package com.lin.controller;
  2. import java.io.IOException;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import javax.annotation.Resource;
  6. import net.sf.json.JSONObject;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import org.springframework.stereotype.Controller;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.ResponseBody;
  12. import com.lin.consumer.MessageConsumer;
  13. import com.lin.producer.MessageProducer;
  14. import com.rabbitmq.client.Channel;
  15. import com.rabbitmq.client.Connection;
  16. import com.rabbitmq.client.ConnectionFactory;
  17. import com.rabbitmq.client.ConsumerCancelledException;
  18. import com.rabbitmq.client.QueueingConsumer;
  19. import com.rabbitmq.client.ShutdownSignalException;
  20. import com.rabbitmq.client.QueueingConsumer.Delivery;
  21. /**
  22. * 功能概要:UserController
  23. *
  24. * @author linbingwen
  25. * @since 2015年9月28日
  26. */
  27. @Controller
  28. public class MessageController {
  29. @Resource
  30. private MessageProducer messageProducer;
  31. private Logger logger = LoggerFactory.getLogger(getClass());
  32. /**
  33. * 显示首页
  34. * @author linbingwen
  35. * @since 2015年10月23日
  36. * @return
  37. */
  38. @RequestMapping( "/test")
  39. public String message(){
  40. logger.info( "open message.jsp");
  41. return "message";
  42. }
  43. /**
  44. * 用来发送消息
  45. * @author linbingwen
  46. * @since 2016年2月19日
  47. * @param message
  48. * @return
  49. */
  50. @RequestMapping( "/sendMsg")
  51. @ResponseBody
  52. public String sendMsg(String message) {
  53. logger.info( "to send message:{}",message);
  54. messageProducer.sendMessage(message);
  55. Map<String,Object> map = new HashMap<String,Object>();
  56. map.put( "flag", true);
  57. JSONObject jsonObject = JSONObject.fromObject(map);
  58. return jsonObject.toString();
  59. }
  60. /**
  61. * 用来接收消息
  62. * @author linbingwen
  63. * @since 2016年2月19日
  64. * @param message
  65. * @return
  66. */
  67. @RequestMapping( "/revcMsg")
  68. @ResponseBody
  69. public String revcMsg() {
  70. String string = getMsg();
  71. if (string != null) {
  72. } else {
  73. string = "null";
  74. }
  75. Map<String,Object> map = new HashMap<String,Object>();
  76. map.put( "string", string);
  77. JSONObject jsonObject = JSONObject.fromObject(map);
  78. return jsonObject.toString();
  79. }
  80. public String getMsg() {
  81. ConnectionFactory connFac = new ConnectionFactory() ;
  82. connFac.setHost( "white-swan.rmq.cloudamqp.com");
  83. connFac.setPassword( "DRR6tF7DCuEq7ugHwlBP8A9zTwu6jI8D");
  84. connFac.setUsername( "zqwocdmu");
  85. connFac.setVirtualHost( "zqwocdmu");
  86. Connection conn = null;
  87. try {
  88. conn = connFac.newConnection();
  89. } catch (IOException e) {
  90. e.printStackTrace();
  91. }
  92. Channel channel = null;
  93. try {
  94. channel = conn.createChannel();
  95. } catch (IOException e) {
  96. e.printStackTrace();
  97. }
  98. String queueName = "queueTest";
  99. try {
  100. channel.queueDeclare(queueName, true, false, false, null) ;
  101. } catch (IOException e) {
  102. e.printStackTrace();
  103. }
  104. //配置好获取消息的方式
  105. QueueingConsumer consumer = new QueueingConsumer(channel) ;
  106. try {
  107. channel.basicConsume(queueName, true, consumer) ;
  108. } catch (IOException e) {
  109. e.printStackTrace();
  110. }
  111. // //循环获取消息
  112. // while(true){
  113. //获取消息,如果没有消息,这一步将会一直阻塞
  114. Delivery delivery = null;
  115. try {
  116. delivery = consumer.nextDelivery();
  117. } catch (ShutdownSignalException e) {
  118. e.printStackTrace();
  119. } catch (ConsumerCancelledException e) {
  120. e.printStackTrace();
  121. } catch (InterruptedException e) {
  122. e.printStackTrace();
  123. }
  124. String msg = new String(delivery.getBody()) ;
  125. System.out.println( "received message[" + msg + "] from " + queueName);
  126. // }
  127. try {
  128. conn.close();
  129. } catch (IOException e) {
  130. e.printStackTrace();
  131. }
  132. return msg;
  133. }
  134. }

3、rabbitMq.xml内容如下:

和上面的工程相比,去掉了消息监听器。而把它放在Controller层中来使用。就是上面的getMsg()代码。


  
  
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit= "http://www.springframework.org/schema/rabbit"
  4. xsi:schemaLocation= "http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  8. http://www.springframework.org/schema/rabbit
  9. http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
  10. <!--配置connection-factory,指定连接rabbit server参数 -->
  11. <!-- <rabbit:connection-factory id="connectionFactory" -->
  12. <!-- username="asdf" password="123456" host="10.75.4.25" port="5672" /> -->
  13. <rabbit:connection-factory id="connectionFactory"
  14. username= "zqwocdmu" password= "DRR6tF7DCuEq7ugHwlBP8A9zTwu6jI8D" host = "white-swan.rmq.cloudamqp.com" virtual-host= "zqwocdmu" />
  15. <!--定义rabbit template用于数据的接收和发送 -->
  16. <rabbit:template id="amqpTemplate" connection-factory="connectionFactory"
  17. exchange= "exchangeTest" />
  18. <!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->
  19. <rabbit:admin connection-factory="connectionFactory" />
  20. <!--定义queue -->
  21. <rabbit:queue name="queueTest" durable="true" auto-delete="false" exclusive="false" />
  22. <!-- 定义direct exchange,绑定queueTest -->
  23. <rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false">
  24. <rabbit:bindings>
  25. <rabbit:binding queue="queueTest" key="queueTestKey"> </rabbit:binding>
  26. </rabbit:bindings>
  27. </rabbit:direct-exchange>
  28. <!-- 消息接收者 -->
  29. <!-- <bean id="messageReceiver" class="com.lin.consumer.MessageConsumer"></bean> -->
  30. <!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象-->
  31. <!-- <rabbit:listener-container connection-factory="connectionFactory"> -->
  32. <!-- <rabbit:listener queues="queueTest" ref="messageReceiver"/> -->
  33. <!-- </rabbit:listener-container> -->
  34. </beans>

这是给远程的Bluemix上绑定的服务中心发消息,

这是获取消息


当然,也可以看日志:



最后一步打war包,然后上传到Bluemix中心即可:

发送消息


接收消息:

(这里要注意一定要先发送消息,要不接收消息会一直阻塞会去,整个页面会卡死,而且接收消息的过程非常缓慢,请耐心等待!)


  本文实例访问:http://javahelloworld2.mybluemix.net/

   本文工程下载:http://download.csdn.net/detail/evankaka/9427970


猜你喜欢

转载自blog.csdn.net/weixin_42581112/article/details/89197392