设为首页 收藏本站
查看: 578|回复: 0

[经验分享] Spring+JMS+ActiveMQ+Tomcat实现消息服务

[复制链接]

尚未签到

发表于 2017-1-30 14:03:14 | 显示全部楼层 |阅读模式
基于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服务器,通过页面可以发送消息,并通过日志查看,实际消息发送和接收的情况

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-335405-1-1.html 上篇帖子: HOWTO: Disable HTTP Methods in Tomcat Introduction 下篇帖子: dwr消息推送和tomcat集群
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表