java JMS消息队列
http://blog.csdn.net/shirdrn/article/details/6362792
http://haohaoxuexi.iteye.com/blog/1893038
http://afreon.blog.163.com/blog/static/223794094201431422654237/
http://www.cnblogs.com/huang0925/p/3558690.html
ActiveMQ第二弹:使用Spring JMS与ActiveMQ通讯
本文章的完整代码可从我的github中下载:https://github.com/huangbowen521/SpringJMSSample.git
上一篇文章中介绍了如何安装和运行ActiveMQ。这一章主要讲述如何使用Spring JMS向ActiveMQ的Message Queue中发消息和读消息。
首先需要在项目中引入依赖库。
spring-core: 用于启动Spring容器,加载bean。
spring-jms:使用Spring JMS提供的API。
activemq-all:使用ActiveMQ提供的API。
在本示例中我使用maven来导入相应的依赖库。
pom.xml
1 |
|
接下来配置与ActiveMQ的连接,以及一个自定义的MessageSender。
springJMSConfiguration.xml
1 |
|
在此配置文件中,我们配置了一个ActiveMQ的connection factory,使用的是ActiveMQ提供的ActiveMQConnectionFactory类。然后又配置了一个Spring JMS提供的CachingConnectionFactory。我们定义了一个ActiveMQQueue作为消息的接收Queue。并创建了一个JmsTemplate,使用了之前创建的ConnectionFactory和Message Queue作为参数。最后自定义了一个MessageSender,使用该JmsTemplate进行消息发送。
以下MessageSender的实现。
MessageSender.java
1 |
|
这个MessageSender很简单,就是通过jmsTemplate发送一个字符串信息。
我们还需要配置一个Listener来监听和处理当前的Message Queue。
springJMSReceiver.xml
1 |
|
在上述xml文件中,我们自定义了一个MessageListener,并且使用Spring提供的SimpleMessageListenerContainer作为Container。
以下是MessageLinser的具体实现。
MessageReceiver.java
1 |
|
这个MessageListener也相当的简单,就是从Queue中读取出消息以后输出到当前控制台中。
另外有关ActiveMQ的url和所使用的Message Queue的配置在application.properties文件中。
application.properties
1 |
|
好了,配置大功告成。如何演示那?我创建了两个Main方法,一个用于发送消息到ActiveMQ的MessageQueue中,一个用于从MessageQueue中读取消息。
SenderApp
1 |
|
ReceiverApp.java
1 |
|
OK,如果运行的话要先将ActiveMQ服务启动起来(更多启动方式参见我上篇文章)。
1 |
|
然后运行SenderApp中的Main方法,就可以在控制台中输入消息发送到ActiveMQ的Message Queue中了。运行ReceiverApp中的Main方法,则会从Queue中将消息读出来,打印到控制台。
这就是使用Spring JMS与ActiveMQ交互的一个简单例子了。完整代码可从https://github.com/huangbowen521/SpringJMSSample下载。
//------------------------------------------------------------------------------
基于Spring+JMS+ActiveMQ+Tomcat,我使用的版本情况如下所示:
- Spring 2.5
- ActiveMQ 5.4.0
- Tomcat 6.0.30
下面通过学习与配置,实现消息服务的基本功能:发送与接收。Spring对JMS提供了很好的支持,可以通过JmsTemplate来方便地实现消息服务。这里,我们的消息服务不涉及事务管理。下面简单说明实现过程:
先看一下,我们最终的Spring配置文件applicationContext.xml的内容,如下所示:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:amq="http://activemq.apache.org/schema/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
- <bean id="listenerContainer"
- class="org.springframework.jms.listener.DefaultMessageListenerContainer">
- <property name="connectionFactory" ref="connectionFactory"></property>
- <property name="destination" ref="messageQueue"></property>
- <property name="messageListener" ref="receiveMessageListener"></property>
- </bean>
- <bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
- <property name="jndiName" value="java:comp/env/myJMS/ConnectionFactory"></property>
- </bean>
- <bean id="messageQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
- <property name="jndiName" value="java:comp/env/myJMS/MessageQueue"></property>
- </bean>
- <bean id="receiveMessageListener"
- class="org.shirdrn.spring.jms.integration.ReceiveMessageListener"></bean>
- <bean id="messageSender" class="org.shirdrn.spring.jms.integration.MessageSender">
- <property name="jmsTemplate" ref="jmsTemplate"></property>
- </bean>
- <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
- <property name="connectionFactory" ref="connectionFactory"></property>
- <property name="defaultDestination" ref="messageQueue"></property>
- </bean>
- <bean id="sendMessageController"
- class="org.shirdrn.spring.jms.integration.SendMessageController">
- <property name="messageSender" ref="messageSender" />
- <property name="successView" value="/success" />
- </bean>
- <bean id="urlMapping"
- class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
- <property name="mappings">
- <props>
- <prop key="/sendMessage.do">sendMessageController</prop>
- </props>
- </property>
- </bean>
- <bean id="viewResolver"
- class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="requestContextAttribute" value="rc" />
- <property name="viewClass"
- value="org.springframework.web.servlet.view.JstlView" />
- <property name="prefix" value="/" />
- <property name="suffix" value=".jsp" />
- </bean>
- </beans>
我们使用Spring的org.springframework.jms.listener.DefaultMessageListenerContainer来收集消息,通过设置一个消息监听器,具体实现类为org.shirdrn.spring.jms.integration.ReceiveMessageListener,代码如下所示:
- package org.shirdrn.spring.jms.integration;
- import javax.jms.JMSException;
- import javax.jms.Message;
- import javax.jms.MessageListener;
- import javax.jms.TextMessage;
- import org.apache.log4j.Logger;
- public class ReceiveMessageListener implements MessageListener {
- private static final Logger LOG = Logger.getLogger(ReceiveMessageListener.class);
- public void onMessage(Message message) {
- if (message instanceof TextMessage) {
- TextMessage text = (TextMessage) message;
- try {
- LOG.info("Received message:" + text.getText());
- } catch (JMSException e) {
- e.printStackTrace();
- }
- }
- }
- }
上面,对发送的消息进行监听,并接收处理,我们只是简单地打印出一条日志内容。
对于listenerContainer,还需要注入连接工厂connectionFactory和消息目的destination这两个属性:connectionFactory我们使用ActiveMQ的org.apache.activemq.ActiveMQConnectionFactory,并通过JNDI服务,绑定到名字java:comp/env/myJMS/ConnectionFactory上;而destination属性通过使用ActiveMQ的org.apache.activemq.command.ActiveMQQueue消息队列,也是通过JNDI服务绑定到名字java:comp/env/myJMS/MessageQueue上。所以,在Tomcat的conf/context.xml中的<Context>元素里面加上如下配置:
- <Resource name="myJMS/ConnectionFactory"
- auth="Container"
- type="org.apache.activemq.ActiveMQConnectionFactory"
- description="JMS Connection Factory"
- factory="org.apache.activemq.jndi.JNDIReferenceFactory"
- brokerURL="vm://shirdrnUrl"
- brokerName="MyActiveMQBroker"/>
- <Resource name="myJMS/MessageQueue"
- auth="Container"
- type="org.apache.activemq.command.ActiveMQQueue"
- description="My Message Queue"
- factory="org.apache.activemq.jndi.JNDIReferenceFactory"
- physicalName="MyMessageQueue"/>
我们通过使用JmsTemplate来实现消息的发送,所以实现的发送类要将JmsTemplate注入进去,实现代码如下所示:
- package org.shirdrn.spring.jms.integration;
- import javax.jms.JMSException;
- import javax.jms.Message;
- import javax.jms.Session;
- import javax.jms.TextMessage;
- import org.apache.log4j.Logger;
- import org.springframework.jms.core.JmsTemplate;
- import org.springframework.jms.core.MessageCreator;
- public class MessageSender {
- private static final Logger LOG = Logger.getLogger(MessageSender.class);
- private JmsTemplate jmsTemplate;
- public void setJmsTemplate(JmsTemplate jmsTemplate) {
- this.jmsTemplate = jmsTemplate;
- }
- public void sendMessage(final String message) {
- LOG.info("Send message: " + message);
- jmsTemplate.send(new MessageCreator() {
- public Message createMessage(Session session) throws JMSException {
- TextMessage textMessage = session.createTextMessage(message);
- return textMessage;
- }
- });
- }
- }
上面基于Spring的MessageCreator来创建消息,通过调用JmsTemplate的send方法发送出去。
对于Web,我们使用了Spring MVC,通过实现一个控制器org.shirdrn.spring.jms.integration.SendMessageController来控制页面消息的发送及其视图的派发。我们实现的SendMessageController类继承自MultiActionController,可以在一个控制器中实现多个Action,代码实现如下所示:
- package org.shirdrn.spring.jms.integration;
- import java.util.HashMap;
- import java.util.Map;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.web.servlet.ModelAndView;
- import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
- public class SendMessageController extends MultiActionController {
- private String successView;
- private MessageSender messageSender;
- public ModelAndView sendMessage(HttpServletRequest request,
- HttpServletResponse response) throws Exception {
- Map<String, Object> retMap = new HashMap<String, Object>();
- String message = request.getParameter("message");
- messageSender.sendMessage(message);
- return new ModelAndView(successView, retMap);
- }
- public String getSuccessView() {
- return successView;
- }
- public void setSuccessView(String successView) {
- this.successView = successView;
- }
- public MessageSender getMessageSender() {
- return messageSender;
- }
- public void setMessageSender(MessageSender messageSender) {
- this.messageSender = messageSender;
- }
- }
上面调用模型层(Model)的MessageSender来实现发送消息的处理逻辑,如果发送成功,视图派发到successView指定的页面。可以看到,最前面我们给出的Spring配置内容分为三组,最后一组是对控制器的配置:
viewResolver 视图解析器配置,可以将控制器中指定前缀(/)解析为后缀是.jsp的页面,例如/success解析为/sucess.jsp
urlMapping 请求URL与控制器的映射,例如对于满足/sendMessage.do模式的请求,都会被指派给sendMessageController去处理
sendMessageController 控制器实现类,里面的方法名称可以自定义,但要在org.springframework.web.servlet.handler.SimpleUrlHandlerMapping中的mappings属性中配置映射
然后,我们需要一个web部署描述文件,web.xml文件配置内容,如下所示:
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- classpath:org/shirdrn/spring/jms/integration/applicationContext.xml
- </param-value>
- </context-param>
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <servlet>
- <servlet-name>controller</servlet-name>
- <servlet-class>
- org.springframework.web.servlet.DispatcherServlet
- </servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- classpath:org/shirdrn/spring/jms/integration/applicationContext.xml
- </param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>controller</servlet-name>
- <url-pattern>*.do</url-pattern>
- </servlet-mapping>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
另外,我们还要实现一个页面,提供输入发送消息的表单,提交后交给后台处理,成功发送后跳转到一个成功页面。表单输入页面为index.jsp,如下所示:
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme() + "://"
- + request.getServerName() + ":" + request.getServerPort()
- + path + "/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>My JSP 'index.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <!--
- <link rel="stylesheet" type="text/css" href="styles.css" mce_href="styles.css">
- -->
- </head>
- <body>
- <div align="center" style="width: 500px; height: 300px; border:2px; borderColor:black">
- <form action="sendMessage.do" method="post">
- <table align="center">
- <tr>
- <th colspan="2">
- 消息发送控制台
- </th>
- </tr>
- <tr>
- <td>
- 消息内容:
- </td>
- <td>
- <input type="text" name="message">
- </td>
- </tr>
- <tr>
- <td align="center" colspan="2">
- <input type="reset" value="清除">
- <input type="submit" value="发送">
- </td>
- </tr>
- </table>
- </form>
- </div>
- </body>
- </html>
成功页面为success.jsp,就是给一个成功的提示信息,如下所示:
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme() + "://"
- + request.getServerName() + ":" + request.getServerPort()
- + path + "/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
- <title>My JSP 'index.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <!--
- <link rel="stylesheet" type="text/css" href="styles.css" mce_href="styles.css">
- -->
- </head>
- <body>
- <div align="center" style="width: 500px; height: 300px; border:2px; borderColor:black">
- <form action="sendMessage.do" method="post">
- <table align="center">
- <tr>
- <th colspan="2">
- 消息发送报告
- </th>
- </tr>
- <tr>
- <td colspan="2">
- 状态:发送成功
- </td>
- </tr>
- <tr>
- <td align="center" colspan="2">
- <a href="index.jsp" mce_href="index.jsp">返回</a>
- </td>
- </tr>
- </table>
- </form>
- </div>
- </body>
- </html>
至此,我们可以将实现的简单web工程发布到Tomcat容器,然后启动Tomcat服务器,通过页面可以发送消息,并通过日志查看,实际消息发送和接收的情况。
java JMS消息队列的更多相关文章
- Flume 读取JMS 消息队列消息,并将消息写入HDFS
利用Apache Flume 读取JMS 消息队列消息.并将消息写入HDFS,flume agent配置例如以下: flume-agent.conf #name the components on ...
- JAVA记录-消息队列介绍
1.JMS概述 JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消 ...
- Java JMS——消息服务
转载请注明原文地址: https://www.cnblogs.com/ygj0930/p/10921569.html 一:什么是Java消息服务—— 消息通信接口规范 Java消息服务指的:两个应用程 ...
- java之消息队列ActiveMQ实践
原创论文:https://www.cnblogs.com/goujh/p/8510239.html 消息队列的应用场景: 消息队列应用场景 异步处理,应用解耦,流量削锋和消息通讯四个场景 异步处理: ...
- [Java] 分布式消息队列(MQ)
概述 场景 服务解耦 削峰填谷 异步化缓冲:最终一致性/柔性事务 MQ应用思考点 生产端可靠性投递 消费端幂等:消息只能消费一次 高可用.低延迟.可靠性 消息堆积能力 可扩展性 业界主流MQ Acti ...
- JMS 消息队列
1.jms broker服务器:Broker:消息队列核心,相当于一个控制中心,负责路由消息.保存订阅和连接.消息确认和控制事务
- Java服务器端消息队列实战
服务端口监听--报文接收--报文解码--业务处理--报文编码--写回客户端 从服务端与客户端成功握手并产生一个socket后,为了提高吞吐能力,接下来的事情就可以交给多线程去处理. 为了对接入的请求做 ...
- Java面试—消息队列
消息队列面试题 题目来自于中华石杉,解决方案根据自己的思路来总结而得. 题目主要如下: 1. 为什么要引入消息队列? 消息队列的引入可以解决3个核心问题: 解耦 异步 削峰 解耦 在一个项目中,如果一 ...
- Java基础——消息队列
1.消息队列的适用场景:商品秒杀.系统解耦.日志记录等 2.使用Queue实现消息对列 双端队列(Deque)是 Queue 的子类也是 Queue 的补充类,头部和尾部都支持元素插入和获取阻塞队列指 ...
随机推荐
- ExcelApplication 另存Excel的SaveAs函数
procedure SaveAs(const Filename: WideString; FileFormat: OleVariant; Password: OleVariant; WriteResP ...
- SAS学习笔记
一. 在SAS中进行随机抽样: 1. 在实际数据处理中常常需要进行样本抽样,在实践中主要有两种情况: (1)简单无重复抽样(2)分层抽样 a.等比例分层抽样 b. 不等比例 ...
- [转载]C++中声明与定义的区别
C++学了这么多年你知道为什么定义类时,类的定义放在.h文件中,而类的实现放在cpp文件中.它们为什么能够关联到一起呢?你知道什么东西可以放在.h文件中,什么不能.什么东西又可以放在cpp文件中.如果 ...
- echarts的使用
ECharts是一个图形展示控件,基于javascript开发出来的,挺好用的,研究了下. 主页地址:http://echarts.baidu.com/index.html API地址:http:// ...
- Oracle中批量插入
为了防止OracleConnection的重复打开和关闭,使用begin end:将sql语句包在里面,然后一次性执行提高插入的效率. 下面代码中要插入的数据在list集合中,如果list集合的cou ...
- shell之小括号、中括号、大括号
1.Shell中变量的原形:${var} 一串命令的执行 #等价于 $ var=test $ echo $var test #例如,用在这个位置 $ echo ${var}AA testAA 2.命 ...
- android:ListView的局部刷新
1.简介 对于android中的ListView刷新机制,大多数的程序员都是很熟悉的,修改或者添加adapter中的数据源之后,然后调用notifyDataSetChanged()刷新ListView ...
- VMware 11安装Mac OS X 10.10
http://jingyan.baidu.com/article/ff411625b9011212e48237b4.html
- 可以把一些常用的方法,写入js文件,引入html界面
这样,可以在多处应用.更好一些.缺点是不够灵活. 优点是,一处修改,多处应用. 函数这东西,一般都是先加载的,之后就可以随便调用了. function delquestion(obj){ //conf ...
- 【UIView与控件】