Spring+JMS+ActiveMQ+Tomcat实现消息服务

基于Spring+JMS+ActiveMQ+Tomcat,我使用的版本情况如下所示:

Spring2.5

ActiveMQ5.4.0

Tomcat6.0.30

下面通过学习与配置,实现消息服务的基本功能:发送与接收。Spring对JMS提供了很好的支持,可以通过JmsTemplate来方便地实现消息服务。这里,我们的消息服务不涉及事务管理。下面简单说明实现过程:

先看一下,我们最终的Spring配置文件applicationContext.xml的内容,如下所示:

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://activemq.apache.org/schema/corehttp://activemq.apache.org/schema/core/activemq-core.xsd">

<beanid="listenerContainer"

class="org.springframework.jms.listener.DefaultMessageListenerContainer">

<propertyname="connectionFactory"ref="connectionFactory"></property>

<propertyname="destination"ref="messageQueue"></property>

<propertyname="messageListener"ref="receiveMessageListener"></property>

</bean>

<beanid="connectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="java:comp/env/myJMS/ConnectionFactory"></property>

</bean>

<beanid="messageQueue"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="java:comp/env/myJMS/MessageQueue"></property>

</bean>

<beanid="receiveMessageListener"

class="org.shirdrn.spring.jms.integration.ReceiveMessageListener"></bean>

<beanid="messageSender"class="org.shirdrn.spring.jms.integration.MessageSender">

<propertyname="jmsTemplate"ref="jmsTemplate"></property>

</bean>

<beanid="jmsTemplate"class="org.springframework.jms.core.JmsTemplate">

<propertyname="connectionFactory"ref="connectionFactory"></property>

<propertyname="defaultDestination"ref="messageQueue"></property>

</bean>

<beanid="sendMessageController"

class="org.shirdrn.spring.jms.integration.SendMessageController">

<propertyname="messageSender"ref="messageSender"/>

<propertyname="successView"value="/success"/>

</bean>

<beanid="urlMapping"

class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<propertyname="mappings">

<props>

<propkey="/sendMessage.do">sendMessageController</prop>

</props>

</property>

</bean>

<beanid="viewResolver"

class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<propertyname="requestContextAttribute"value="rc"/>

<propertyname="viewClass"

value="org.springframework.web.servlet.view.JstlView"/>

<propertyname="prefix"value="/"/>

<propertyname="suffix"value=".jsp"/>

</bean>

</beans>

我们使用Spring的org.springframework.jms.listener.DefaultMessageListenerContainer来收集消息,通过设置一个消息监听器,具体实现类为org.shirdrn.spring.jms.integration.ReceiveMessageListener,代码如下所示:

packageorg.shirdrn.spring.jms.integration;

importjavax.jms.JMSException;

importjavax.jms.Message;

importjavax.jms.MessageListener;

importjavax.jms.TextMessage;

importorg.apache.log4j.Logger;

publicclassReceiveMessageListenerimplementsMessageListener{

privatestaticfinalLoggerLOG=Logger.getLogger(ReceiveMessageListener.class);

publicvoidonMessage(Messagemessage){

if(messageinstanceofTextMessage){

TextMessagetext=(TextMessage)message;

try{

LOG.info("Receivedmessage:"+text.getText());

}catch(JMSExceptione){

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>元素里面加上如下配置:

<Resourcename="myJMS/ConnectionFactory"

auth="Container"

type="org.apache.activemq.ActiveMQConnectionFactory"

description="JMSConnectionFactory"

factory="org.apache.activemq.jndi.JNDIReferenceFactory"

brokerURL="vm://shirdrnUrl"

brokername="MyActiveMQBroker"/>

<Resourcename="myJMS/MessageQueue"

auth="Container"

type="org.apache.activemq.command.ActiveMQQueue"

description="MyMessageQueue"

factory="org.apache.activemq.jndi.JNDIReferenceFactory"

physicalname="MyMessageQueue"/>

我们通过使用JmsTemplate来实现消息的发送,所以实现的发送类要将JmsTemplate注入进去,实现代码如下所示:

packageorg.shirdrn.spring.jms.integration;

importjavax.jms.JMSException;

importjavax.jms.Message;

importjavax.jms.Session;

importjavax.jms.TextMessage;

importorg.apache.log4j.Logger;

importorg.springframework.jms.core.JmsTemplate;

importorg.springframework.jms.core.MessageCreator;

publicclassMessageSender{

privatestaticfinalLoggerLOG=Logger.getLogger(MessageSender.class);

privateJmsTemplatejmsTemplate;

publicvoidsetJmsTemplate(JmsTemplatejmsTemplate){

this.jmsTemplate=jmsTemplate;

}

publicvoidsendMessage(finalStringmessage){

LOG.info("Sendmessage:"+message);

jmsTemplate.send(newMessageCreator(){

publicMessagecreateMessage(Sessionsession)throwsJMSException{

TextMessagetextMessage=session.createTextMessage(message);

returntextMessage;

}

});

}

}

上面基于Spring的MessageCreator来创建消息,通过调用JmsTemplate的send方法发送出去。

对于Web,我们使用了SpringMVC,通过实现一个控制器org.shirdrn.spring.jms.integration.SendMessageController来控制页面消息的发送及其视图的派发。我们实现的SendMessageController类继承自MultiActionController,可以在一个控制器中实现多个Action,代码实现如下所示:

packageorg.shirdrn.spring.jms.integration;

importjava.util.HashMap;

importjava.util.Map;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

importorg.springframework.web.servlet.ModelAndView;

importorg.springframework.web.servlet.mvc.multiaction.MultiActionController;

publicclassSendMessageControllerextendsMultiActionController{

privateStringsuccessView;

privateMessageSendermessageSender;

publicModelAndViewsendMessage(HttpServletRequestrequest,

HttpServletResponseresponse)throwsException{

Map<String,Object>retMap=newHashMap<String,Object>();

Stringmessage=request.getParameter("message");

messageSender.sendMessage(message);

returnnewModelAndView(successView,retMap);

}

publicStringgetSuccessView(){

returnsuccessView;

}

publicvoidsetSuccessView(StringsuccessView){

this.successView=successView;

}

publicMessageSendergetMessageSender(){

returnmessageSender;

}

publicvoidsetMessageSender(MessageSendermessageSender){

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文件配置内容,如下所示:

<?xmlversion="1.0"encoding="UTF-8"?>

<web-appversion="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,如下所示:

<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%>

<%

Stringpath=request.getContextPath();

StringbasePath=request.getScheme()+"://"

+request.getServerName()+":"+request.getServerPort()

+path+"/";

%>

<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">

<html>

<head>

<basehref=../../"<%=basePath%>">

<title>MyJSP'index.jsp'startingpage</title>

<metahttp-equiv="pragma"content="no-cache">

<metahttp-equiv="cache-control"content="no-cache">

<metahttp-equiv="expires"content="0">

<metahttp-equiv="keywords"content="keyword1,keyword2,keyword3">

<metahttp-equiv="description"content="Thisismypage">

<!--

<linkrel="stylesheet"type="text/css"href=../../"styles.css"mce_href=../../"styles.css">

-->

</head>

<body>

<divalign="center"style="width:500px;height:300px;border:2px;borderColor:black">

<formaction="sendMessage.do"method="post">

<tablealign="center">

<tr>

<thcolspan="2">

消息发送控制台

</th>

</tr>

<tr>

<td>

消息内容:

</td>

<td>

<inputtype="text"name="message">

</td>

</tr>

<tr>

<tdalign="center"colspan="2">

<inputtype="reset"value="清除">

<inputtype="submit"value="发送">

</td>

</tr>

</table>

</form>

</div>

</body>

</html>

成功页面为success.jsp,就是给一个成功的提示信息,如下所示:

<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%>

<%

Stringpath=request.getContextPath();

StringbasePath=request.getScheme()+"://"

+request.getServerName()+":"+request.getServerPort()

+path+"/";

%>

<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">

<html>

<head>

<basehref=../../"<%=basePath%>">

<title>MyJSP'index.jsp'startingpage</title>

<metahttp-equiv="pragma"content="no-cache">

<metahttp-equiv="cache-control"content="no-cache">

<metahttp-equiv="expires"content="0">

<metahttp-equiv="keywords"content="keyword1,keyword2,keyword3">

<metahttp-equiv="description"content="Thisismypage">

<!--

<linkrel="stylesheet"type="text/css"href=../../"styles.css"mce_href=../../"styles.css">

-->

</head>

<body>

<divalign="center"style="width:500px;height:300px;border:2px;borderColor:black">

<formaction="sendMessage.do"method="post">

<tablealign="center">

<tr>

<thcolspan="2">

消息发送报告

</th>

</tr>

<tr>

<tdcolspan="2">

状态:发送成功

</td>

</tr>

<tr>

<tdalign="center"colspan="2">

<ahref=../../"index.jsp"mce_href=../../"index.jsp">返回</a>

</td>

</tr>

</table>

</form>

</div>

</body>

</html>

至此,我们可以将实现的简单web工程发布到Tomcat容器,然后启动Tomcat服务器,通过页面可以发送消息,并通过日志查看,实际消息发送和接收的情况

相关推荐