转载请注明出处。
智慧公交-核心的部分就是消息推送这一块,推送和接受消息能跑通了,其他的就是业务上问题了。
智能公交调度系统-系统结合了GPS GIS GPRS 等。GPS、GPRS大家都明白,GIS(地理信息系统)在智慧公交项目上主要是用来展示公交线路的地图。在地图上我们可以看到公交线路,车辆位置、行驶方向,可以查看公交车内部的监控、公交站点监控等实时信息。
通过实时监控、超速报警、自动报站、车载LED跑马板等功能使司机操作服务更规范。
通过车内安装监控设备使市民安全性提高,如遇被偷窃等特殊情况将方便调查及作为有效的证据。
对市民投诉较多的司机越站、过站等问题,可通过轨迹回放与监控追查原因,及时地进行处理。啰嗦的有点多,下面就进入正题。
**************************************************************************************************************************************************************************************上一篇文章有三个问题还没有解决,现在就来解决这几个问题。
1. Spring如何更有效地管理ActiveMQ?
2. ActiveMQ如何将对象推送到前端,前端又是如何接受对象?
3. 如何实现订阅信息的筛选?一.消息的发送和接受
Spring也为我们提供了JMSTemplate模板,可以发送和接受消息,类似hibernateTemplate。
可是jmsTemplate如何知道消息转换器呢?需要在配置jmsTemplate的时候,加上messageConverter属性。
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="topicSendConnectionFactory" />
<property name="defaultDestination" ref="myTopic" />
<property name="messageConverter" ref="messageConvertForSys" />
<property name="deliveryMode" value="1" />
<!-- 发送模式 DeliveryMode.NON_PERSISTENT=1:非持久 ; DeliveryMode.PERSISTENT=2:持久-->
<property name="pubSubDomain" value="true" /> <span style="font-family: Arial, Helvetica, sans-serif;"> <!-- 开启订阅模式 --> </span>
</bean>
二.当有消息推送过来,我们如何来监听呢?
Spring提供了三种 AbstractMessageListenerContainer 的子类,每种各有其特点。
第一种:SimpleMessageListenerContainer
这个消息侦听容器是三种中最简单的。它在启动时创建固定数量的JMS session并在容器的整个生命周期中使用它们。这个类不能动态的适应运行时的要求或参与消息接收的事务处理。然而它对JMS提供者的要求也最低。它只需要简单的JMS API。
第二种:DefaultMessageListenerContainer
这个消息侦听器使用的最多。和 SimpleMessageListenerContainer 相反,这个子类可以动态适应运行时侯的要求,也可以参与事务管理。每个收到的消息都注册到一个XA事务中(如果使用 JtaTransactionManager 配置过),这样就可以利用XA事务语义的优势了。这个类在对JMS提供者的低要求和提供包括事务参于等的强大功能上取得了很好的平衡。
第三种:ServerSessionMessageListenerContainer
这个监听器容器利用JMS ServerSessionPool SPI动态管理JMS Session。使用者各种消息监听器可以获得运行时动态调优功能,但是这也要求JMS提供者支持ServerSessionPoolSPI。
<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
三.消息的转换
转化器在很多组件中都是必不缺少的东西。Spring MessageConverter接口提供了对消息转换的支持,这样我们接可以推送java对象了。
四.Java与Flex通过Blazeds通信
blazeDS采用amf协议。该协议可以传输Object, Array, Date, XML。由于AMF采用二进制编码,这种方式可以高度压缩数据,因此非常适合用来传递大量的资料。数据量越大,Flash Remoting的传输效能就越高,远远超过Web Service。至于XML, LoadVars和loadVariables() ,它们使用纯文本的传输方式,效能就更不能与Flash Remoting相提并论了。
五.Java与Flex交互(对象)
然后创建一个ActionScript类:Bus.as,用于接受实体类Bus.java的返回值,这里的[Bindable][RemoteClass]是和java代码中的 Bus.java类关联起来。这样利用类型转换将java对象转换成AS对象。代码如下:
package vo
{
[Bindable][RemoteClass(alias="com.test.jms.flex.BusInfo")]
public class BusInfo
{
public function BusInfo()
{
}
public var platenum:String;
public var speed:String;
public var direction:String;
public var lon:String;
public var lat:String;
public var receivetime:String;
public var routenum:String
}
}
六.订阅信息的筛选(消息过滤)
后台通过AsyncMessage的setHeader()方法来确定筛选条件。
前台flex通过Consumer.selector方式来进行消息的过滤。
七.详细代码
1.ActiveMQ 的activemq.xml配置文件
加入UDP传输方式(<transportConnector name="udp" uri="udp://0.0.0.0:8123" /> )
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- START SNIPPET: example -->
<beans
xmlns="http://www.springframework.org/schema/beans"
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.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<!-- Allows us to use system properties as variables in this configuration file -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>file:${activemq.conf}/credentials.properties</value>
</property>
</bean>
<!-- Allows log searching in hawtio console -->
<bean id="logQuery" class="org.fusesource.insight.log.log4j.Log4jLogQuery"
lazy-init="false" scope="singleton"
init-method="start" destroy-method="stop">
</bean>
<!--
The <broker> element is used to configure the ActiveMQ broker.
-->
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}">
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" >
<!-- The constantPendingMessageLimitStrategy is used to prevent
slow topic consumers to block producers and affect other consumers
by limiting the number of messages that are retained
For more information, see:
http://activemq.apache.org/slow-consumer-handling.html
-->
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
<!--
The managementContext is used to configure how ActiveMQ is exposed in
JMX. By default, ActiveMQ uses the MBean server that is started by
the JVM. For more information, see:
http://activemq.apache.org/jmx.html
-->
<managementContext>
<managementContext createConnector="false"/>
</managementContext>
<!--
Configure message persistence for the broker. The default persistence
mechanism is the KahaDB store (identified by the kahaDB tag).
For more information, see:
http://activemq.apache.org/persistence.html
-->
<persistenceAdapter>
<kahaDB directory="${activemq.data}/kahadb"/>
</persistenceAdapter>
<!--
The systemUsage controls the maximum amount of space the broker will
use before disabling caching and/or slowing down producers. For more information, see:
http://activemq.apache.org/producer-flow-control.html
-->
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage percentOfJvmHeap="70" />
</memoryUsage>
<storeUsage>
<storeUsage limit="100 gb"/>
</storeUsage>
<tempUsage>
<tempUsage limit="50 gb"/>
</tempUsage>
</systemUsage>
</systemUsage>
<!--
The transport connectors expose ActiveMQ over a given protocol to
clients and other brokers. For more information, see:
http://activemq.apache.org/configuring-transports.html
-->
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="udp" uri="udp://0.0.0.0:8123"/>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
</transportConnectors>
<!-- destroy the spring context on shutdown to stop jetty -->
<shutdownHooks>
<bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" />
</shutdownHooks>
</broker>
<!--
Enable web consoles, REST and Ajax APIs and demos
The web consoles requires by default login, you can disable this in the jetty.xml file
Take a look at ${ACTIVEMQ_HOME}/conf/jetty.xml for more details
-->
<import resource="jetty.xml"/>
</beans>
<!-- END SNIPPET: example -->
2. web.xml
在web.xml中加入 org.springframework.web.context.ContextLoaderListener
<?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">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>
<servlet>
<servlet-name>flex</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>flex</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ControlServlet1</servlet-name>
<servlet-class>com.test.jms.servlet.DelegatingServletProxy</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ControlServlet1</servlet-name>
<url-pattern>/ControlServlet1</url-pattern>
</servlet-mapping>
</web-app>
3. 工程WebRoot\WEB-INF下flex文件夹里的四个配置文件
(1) messaging-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<service id="message-service"
class="flex.messaging.services.MessageService">
<adapters>
<adapter-definition id="actionscript" class="flex.messaging.services.messaging.adapters.ActionScriptAdapter" default="true" />
<!-- <adapter-definition id="jms" class="flex.messaging.services.messaging.adapters.JMSAdapter"/> -->
</adapters>
<default-channels>
<channel ref="my-polling-amf" />
<channel ref="my-streaming-amf" />
</default-channels>
</service>
(
2) proxy-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<service id="proxy-service"
class="flex.messaging.services.HTTPProxyService">
<properties>
<connection-manager>
<max-total-connections>100</max-total-connections>
<default-max-connections-per-host>2</default-max-connections-per-host>
</connection-manager>
<allow-lax-ssl>true</allow-lax-ssl>
</properties>
<adapters>
<adapter-definition id="http-proxy" class="flex.messaging.services.http.HTTPProxyAdapter" default="true"/>
<adapter-definition id="soap-proxy" class="flex.messaging.services.http.SOAPProxyAdapter"/>
</adapters>
<default-channels>
<channel ref="my-amf"/>
</default-channels>
<destination id="DefaultHTTP">
</destination>
</service>
(
3) remoting-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service"
class="flex.messaging.services.RemotingService">
<adapters>
<adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
</adapters>
<default-channels>
<channel ref="my-amf"/>
</default-channels>
</service>
(
4) services-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service-include file-path="remoting-config.xml" />
<service-include file-path="proxy-config.xml" />
<service-include file-path="messaging-config.xml" />
</services>
<services>
<default-channels>
<channel ref="my-amf" />
</default-channels>
</services>
<security>
<login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/>
<!-- Uncomment the correct app server
<login-command class="flex.messaging.security.TomcatLoginCommand" server="JBoss">
<login-command class="flex.messaging.security.JRunLoginCommand" server="JRun"/>
<login-command class="flex.messaging.security.WeblogicLoginCommand" server="Weblogic"/>
<login-command class="flex.messaging.security.WebSphereLoginCommand" server="WebSphere"/>
-->
<!--
<security-constraint id="basic-read-access">
<auth-method>Basic</auth-method>
<roles>
<role>guests</role>
<role>accountants</role>
<role>employees</role>
<role>managers</role>
</roles>
</security-constraint>
-->
</security>
<channels>
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
<channel-definition id="my-secure-amf" class="mx.messaging.channels.SecureAMFChannel">
<endpoint url="https://{server.name}:{server.port}/{context.root}/messagebroker/amfsecure" class="flex.messaging.endpoints.SecureAMFEndpoint"/>
<properties>
<add-no-cache-headers>false</add-no-cache-headers>
</properties>
</channel-definition>
<channel-definition id="my-polling-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amfpolling" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<polling-enabled>true</polling-enabled>
<polling-interval-seconds>4</polling-interval-seconds>
</properties>
</channel-definition>
<channel-definition id="my-streaming-amf" class="mx.messaging.channels.StreamingAMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/streamingamf" class="flex.messaging.endpoints.StreamingAMFEndpoint"/>
<properties>
<idle-timeout-minutes>0</idle-timeout-minutes>
<max-streaming-clients>100</max-streaming-clients>
<server-to-client-heartbeat-millis>5000
</server-to-client-heartbeat-millis>
<user-agent-settings>
<user-agent match-on="MSIE" kickstart-bytes="2048" max-streaming-connections-per-session="100" />
<user-agent match-on="Firefox" kickstart-bytes="2048" max-streaming-connections-per-session="100" />
</user-agent-settings>
</properties>
</channel-definition>
</channels>
<logging>
<target class="flex.messaging.log.ConsoleTarget" level="Error">
<properties>
<prefix>[BlazeDS] </prefix>
<includeDate>false</includeDate>
<includeTime>false</includeTime>
<includeLevel>false</includeLevel>
<includeCategory>false</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>
</logging>
<system>
<redeploy>
<enabled>false</enabled>
</redeploy>
</system>
</services-config>
4.Spring的配置文件applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:flex="http://www.springframework.org/schema/flex"
xmlns:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/flex
http://www.springframework.org/schema/flex/spring-flex-1.0.xsd
http://activemq.apache.org/schema/core
http://activemq.apache.org/schema/core/activemq-core-5.2.0.xsd
">
<!--%%%%%%%%%%%%%%%%%%*********************消息处理 ACTIVEMQ***************************%%%%%%%%%%%%% -->
<!-- JMS TOPIC MODEL -->
<!-- TOPIC链接工厂 -->
<bean id="topicSendConnectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
<property name="brokerURL" value="udp://localhost:8123" />
<property name="useAsyncSend" value="true" />
</bean>
<bean id="topicListenConnectionFactory" class="org.apache.activemq.spring.ActiveMQConnectionFactory">
<property name="brokerURL" value="udp://localhost:8123" />
</bean>
<!-- 定义主题 -->
<bean id="myTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg value="normandy.topic"/>
</bean>
<bean id="messageConvertForSys" class="com.test.jms.util.MessageConvertForSys"></bean>
<!-- TOPIC send jms模板 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="topicSendConnectionFactory"></property>
<property name="defaultDestination" ref="myTopic" />
<property name="messageConverter" ref="messageConvertForSys" />
<property name="deliveryMode" value="1" /> <!-- 发送模式 DeliveryMode.NON_PERSISTENT=1:非持久 ; DeliveryMode.PERSISTENT=2:持久-->
<property name="pubSubDomain" value="true"/> <!-- 开启订阅模式 -->
</bean>
<!-- 消息发送方 -->
<bean id="topicMessageSender" class="com.test.jms.util.MessageSender">
<property name="jmsTemplate" ref="jmsTemplate"></property>
</bean>
<!-- 消息接收方 -->
<bean id="topicMessageReceiver" class="com.test.jms.util.MessageReceiver"> </bean>
<!-- 主题消息监听容器 -->
<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="topicListenConnectionFactory" />
<property name="pubSubDomain" value="true"/><!-- 订阅模式 -->
<property name="destination" ref="myTopic" /> <!-- 目的地 myTopic -->
<property name="pubSubNoLocal" value="false"></property>
<property name="messageListener" ref="topicMessageReceiver" />
<property name="receiveTimeout" value="5000" />
<!-- <property name="clientId" value="clientId_001"/>-这里是设置接收客户端的ID,在持久化时,但这个客户端不在线时,消息就存在数据库里,知道被这个ID的客户端消费掉 -->
<!-- <property name="messageListener" ref="topicMessageReceiver" /> -->
</bean>
</beans>
5.Java后台代码
(1) Sender.java
package com.test.jms.util;
import java.text.ParseException;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import com.test.jms.model.Bus;
public class Sender {
private MessageSender topicMessageSender;
public MessageSender getTopicMessageSender() {
return topicMessageSender;
}
public void setTopicMessageSender(MessageSender topicMessageSender) {
this.topicMessageSender = topicMessageSender;
}
public void send(String s) {
String [] points ={"111.62618840,29.07165395","111.62657105,29.07158371","111.62696581,29.07151106","111.62744049,29.07145051","111.62762940,29.07147231","111.62792970,29.07169270","111.62816705,29.07186949","111.62848189,29.07209472","111.62876040,29.07233691","111.62906427,29.07262604","111.62941786,29.07296510","111.62963824,29.07317096","111.62982957,29.07335986","111.63007175,29.07359478","111.63025097,29.07375946","111.63054401,29.07403071","111.63066995,29.07420024","111.63080800,29.07441336","111.63093393,29.07459984","111.63107924,29.07479844","111.63117369,29.07501398","111.63124393,29.07517382","111.63135049,29.07543054","111.63145568,29.07564685","111.63145568,29.07599196","111.63145810,29.07635282","111.63145689,29.07672336","111.63145083,29.07684203","111.63143872,29.07692679","111.63144599,29.07705999","111.63144114,29.07717624","111.63142177,29.07726827","111.63141693,29.07735425","111.63141693,29.07735425","111.63143993,29.07746081","111.63144599,29.07767030","111.63144599,29.07767030","111.63144962,29.07812440","111.63144841,29.07834357","111.63145689,29.07859666","111.63144841,29.07901200","111.63144599,29.07922391","111.63145204,29.07952664","111.63144114,29.07964168","111.63143872,29.07975914","111.63143872,29.07975914","111.63143872,29.07975914","111.63143872,29.07975914","111.63146657,29.07979910","111.63146657,29.07985965","111.63158167,29.07985129","111.63168338,29.07985371","111.63181174,29.07984402","111.63225736,29.07982223","111.63280228,29.07979801","111.63337383,29.07978105","111.63389211,29.07975684","111.63417546,29.07974957","111.63441765,29.07973988","111.63462351,29.07973988","111.63502553,29.07974230","111.63520717,29.07973504","111.63542998,29.07965754","111.63554623,29.07961879","111.63597732,29.07949528","111.63660852,29.07926122","111.63720429,29.07904568","111.63744405,29.07895607","111.63759663,29.07888584","111.63759663,29.07888584","111.63759663,29.07888584","111.63780245,29.07881411","111.63796350,29.07877536","111.63812697,29.07872450","111.63854595,29.07859856","111.63885837,29.07850774","111.63920348,29.07840118","111.63933547,29.07833337","111.63933547,29.07833337","111.63933547,29.07833337","111.63947594,29.07830552","111.63965644,29.07824570","111.63996160,29.07815851","111.64019652,29.07807980","111.64044475,29.07800594","111.64087100,29.07787273","111.64114830,29.07778313","111.64138927,29.07770442","111.64158665,29.07763418","111.64182884,29.07754700","111.64192208,29.07751188","111.64192208,29.07751188","111.64192208,29.07751188","111.64192208,29.07751188"};
try {
for(int i =0;i<points.length;i++){
String currentTime ="";
Thread.sleep(3000);
currentTime = DateTimeUtil.getCurrTimeToStr();
String [] point = points[i].split(",");
String lon = point[0];
String lat = point[1];
Bus bus = new Bus();
bus.setPlatenum("A88403");
bus.setLon(lon);
bus.setLat(lat);
bus.setDirection("上行");
bus.setReceivetime(currentTime);
bus.setRoutenum("205");
bus.setSpeed(Integer.toString((int) Math.round(Math.random() *(30)*0.9)+30));
topicMessageSender.sendMessage(bus);
}
} catch (ParseException e) {
e.printStackTrace();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
(2) MessageSender.java
package com.test.jms.util;
import org.springframework.jms.core.JmsTemplate;
import com.test.jms.model.Bus;
public class MessageSender {
private JmsTemplate jmsTemplate;
public void sendMessage(Bus bus){
jmsTemplate.convertAndSend(bus);
}
public JmsTemplate getJmsTemplate() {
return jmsTemplate;
}
public void setJmsTemplate(JmsTemplate jmsTemplate) {
this.jmsTemplate = jmsTemplate;
}
}
(3) MessageConvertForSys.java //消息转化
package com.test.jms.util;
import java.io.Serializable;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.jms.TopicPublisher;
import org.apache.activemq.command.ActiveMQObjectMessage;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;
import com.test.jms.model.Bus;
public class MessageConvertForSys implements MessageConverter {
public Message toMessage(Object object, Session session)
throws JMSException, MessageConversionException {
System.out.println("sendMessage:"+object.toString());
ActiveMQObjectMessage msg = (ActiveMQObjectMessage) session.createObjectMessage();
msg.setObject((Serializable) object);
return msg;
}
public Object fromMessage(Message message) throws JMSException,
MessageConversionException {
Bus bus = null;
if(message instanceof ActiveMQObjectMessage){
ActiveMQObjectMessage aMsg = (ActiveMQObjectMessage) message;
bus=(Bus) aMsg.getObject();
}
return bus;
}
}
(4) MessageReceiver.java
package com.test.jms.util;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import com.test.jms.flex.BusInfo;
import com.test.jms.model.Bus;
import flex.messaging.MessageBroker;
import flex.messaging.messages.AsyncMessage;
import flex.messaging.util.UUIDUtils;
public class MessageReceiver implements MessageListener {
public void onMessage(Message m) {
System.out.println("[receive message]");
String my = "";
String x = "";
Bus bus= new Bus();
BusInfo sendBus = new BusInfo();
if(m instanceof ObjectMessage){
ObjectMessage objectMessage=(ObjectMessage) m;
try {
bus=(Bus) objectMessage.getObject();
my = bus.getPlatenum();
x = bus.getLat();
sendBus.setDirection(bus.getDirection()) ;
sendBus.setLat(bus.getLat());
sendBus.setLon(bus.getLon());
sendBus.setPlatenum(bus.getPlatenum());
sendBus.setReceivetime(bus.getReceivetime());
sendBus.setRoutenum(bus.getRoutenum());
sendBus.setSpeed(bus.getSpeed());
} catch (JMSException e) {
}
}
System.out.println("公交车编号:"+my +" X:"+x);
MessageBroker messageBroker = MessageBroker.getMessageBroker("_messageBroker");
String clientID = UUIDUtils.createUUID();
//创建AsyncMessage类的对象是为了Flex端用Messaging模式接收消息
AsyncMessage asynMsg = new AsyncMessage();
// 设置消息的地址,这个必须跟Spring配置文件中信道的destination一致
asynMsg.setDestination("market-data-feed");
asynMsg.setHeader("platenum",my);
asynMsg.setClientId(clientID);
asynMsg.setMessageId(UUIDUtils.createUUID());
asynMsg.setTimestamp(System.currentTimeMillis());
asynMsg.setBody(sendBus);
messageBroker.routeMessageToService(asynMsg, null);
}
}
(5) DateTimeUtil.java //时间工具类
package com.test.jms.util;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
*
* @author
*
*/
public class DateTimeUtil {
/**
* 获取当前时间
*
*/
public static Date currentTime() throws ParseException {
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = df.format(date);
Date currTime = df.parse(time);
return currTime;
}
/**
* 获取当前日期
*
*/
public static Date currentDate() throws ParseException {
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String time = df.format(date);
Date currTime = df.parse(time);
return currTime;
}
/**
* 获取当前时间
*
*/
public static String getCurrTimeToStr() throws ParseException {
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currTime = df.format(date);
return currTime;
}
/**
* 获取当前日期
*
*/
public static String getCurrDateToStr() throws ParseException {
Date date = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String currTime = df.format(date);
return currTime;
}
/**
* 获取相隔当前时间n秒的时间
*
* @param n
* 相差n秒
* @return
*/
public static String getTime_PrevSecond(int n) {
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, n);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String prevTime = df.format(calendar.getTime());
return prevTime;
}
/**
* 时间变为字符串形式(yyyy-MM-dd HH:mm:ss)
*
*/
public static String getTimeToString(Date date) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String strTime = df.format(date);
return strTime;
}
/**
* 获取现在时间
*
* @return返回字符串格式 yyyy-MM-dd HH:mm:ss
*/
public static String getStringDate() {
Calendar currentTime = Calendar.getInstance();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(currentTime.getTime());
return dateString;
}
/**
* 将短时间格式时间转换为字符串 yyyy-MM-dd
*
* @param dateDate
* @param k
* @return
*/
public static String dateToStr(java.util.Date dateDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
String dateString = "";
if (dateDate != null) {
dateString = formatter.format(dateDate);
}
return dateString;
}
/**
* 将短时间格式时间转换为字符串 yyyy-MM-dd
*
* @param dateDate
* @param k
* @return
*/
public static String dateToStrMMDD(java.util.Date dateDate) {
SimpleDateFormat formatter = new SimpleDateFormat("MM-dd");
String dateString = "";
if (dateDate != null) {
dateString = formatter.format(dateDate);
}
return dateString;
}
/**
* 将短时间格式字符串转换为时间 yyyy-MM-dd
*
* @param strDate
* @return
*/
public static Date strToDate(String strDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(strDate, pos);
return strtodate;
}
}
(6) BusInfo.java
package com.test.jms.flex;
import java.io.Serializable;
public class BusInfo {
public String platenum;
public String speed;
public String direction;
public String lon;
public String lat;
public String receivetime;
public String routenum;
public String getPlatenum() {
return platenum;
}
public void setPlatenum(String platenum) {
this.platenum = platenum;
}
public String getSpeed() {
return speed;
}
public void setSpeed(String speed) {
this.speed = speed;
}
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getReceivetime() {
return receivetime;
}
public void setReceivetime(String receivetime) {
this.receivetime = receivetime;
}
public String getRoutenum() {
return routenum;
}
public void setRoutenum(String routenum) {
this.routenum = routenum;
}
}
(7)
package com.test.jms.model;
import java.io.Serializable;
public class Bus implements Serializable{
public String platenum;
public String speed;
public String direction;
public String lon;
public String lat;
public String receivetime;
public String routenum;
public String getPlatenum() {
return platenum;
}
public void setPlatenum(String platenum) {
this.platenum = platenum;
}
public String getSpeed() {
return speed;
}
public void setSpeed(String speed) {
this.speed = speed;
}
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getReceivetime() {
return receivetime;
}
public void setReceivetime(String receivetime) {
this.receivetime = receivetime;
}
public String getRoutenum() {
return routenum;
}
public void setRoutenum(String routenum) {
this.routenum = routenum;
}
}
(8)ControlServlet1.java
package com.test.jms.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class ControlServlet1 extends HttpServlet {
public void init() throws ServletException {
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request,response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
}
(9) DelegatingServletProxy.java
package com.test.jms.servlet;
import java.io.IOException;
import javax.servlet.GenericServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class DelegatingServletProxy extends GenericServlet{
private String targetBean;
private Servlet proxy;
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
proxy.service(req, res);
}
public void init() throws ServletException {
this.targetBean = getServletName();
getServletBean();
proxy.init(getServletConfig());
}
private void getServletBean() {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
this.proxy = (Servlet) wac.getBean(targetBean);
}
}
6.前台Flex的代码
(1) bus.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="955" minHeight="600" creationComplete="init();">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.messaging.ChannelSet;
import mx.messaging.channels.AMFChannel;
import mx.messaging.channels.SecureStreamingAMFChannel;
import mx.messaging.channels.StreamingAMFChannel;
import mx.messaging.events.MessageEvent;
import mx.messaging.events.MessageFaultEvent;
import mx.rpc.events.FaultEvent;
import vo.BusInfo;
protected function init():void{
//消息过滤 只订阅公交车编号为A88403 和A88404。
consumer.selector="platenum in ('A88403','A88404')";
//通过我们定义的consumer对象的订阅方法来订阅消息服务
consumer.subscribe();
}
//按钮点击触发的操作
protected function btnSendMessage_clickHandler(event:MouseEvent):void
{
}
//点击按钮后操作失败的处理
protected function Send_faultHandler(event:FaultEvent):void
{
Alert.show("send is fail,because:"+ event.fault.toString());
}
//收到消息的失败处理
protected function ReceiveMessage_faultHandler(event:FaultEvent):void
{
Alert.show("receive is fail,because:"+ event.fault.toString());
}
//生产者收到消息的错误处理
protected function consumer_faultHandler(event:MessageFaultEvent):void
{
txtMessage.text =" 订阅失败";
}
//生产者收到消息后的处理
protected function consumer_messageHandler(event:MessageEvent):void
{
var bus:BusInfo=BusInfo(event.message.body);
txtMessage.text =txtMessage.text+ "编号:"+bus.platenum+" 方向:"+ bus.direction.toString()+" 坐标"+bus.lon+","+bus.lat+"时间:"+bus.receivetime+" 速度:"+bus.speed+"\n";
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
<!--此处定义一个consumer,需要使用它来订阅消息,订阅了以后才能接收到后台发来的数据。这里的关键是要定义destination,destination的值和后台messaging-config.xml定义的 destination的值相同-->
<s:Consumer channelSet="{cs}" id="consumer" destination="market-data-feed" fault="consumer_faultHandler(event)" message="consumer_messageHandler(event)" />
<!--此处定义个发送消息的类,与后台的发送消息的POJO对应,通过它向ActiveMQ发送消息-->
<s:RemoteObject id="Send" channelSet="{amf_channel}" destination="Sender"
fault="Send_faultHandler(event)"/>
<s:AMFChannel id="myamfChannel"
url="http://192.168.1.22:8088/SpringFlexMQ/messagebroker/amf"/>
<mx:ChannelSet id="amf_channel" channels="{[myamfChannel]}"/>
<s:ChannelSet id="cs">
<s:StreamingAMFChannel url="http://192.168.1.22:8088/SpringFlexMQ/messagebroker/streamingamf"/>
</s:ChannelSet>
</fx:Declarations>
<mx:VBox height="100%" horizontalAlign="center" width="100%" verticalAlign="middle" chromeColor="#9F9F9F" dropShadowVisible="true" backgroundColor="#6A232F" backgroundAlpha="0.6">
<mx:VBox width="438" verticalAlign="middle" horizontalAlign="center" paddingBottom="5" paddingTop="5" paddingLeft="5" paddingRight="5" backgroundColor="#87194D" focusColor="#6C1D2A" cornerRadius="10">
<s:VGroup horizontalAlign="center" gap="11" paddingBottom="5" paddingTop="5" paddingLeft="5" paddingRight="5" contentBackgroundColor="#EDEDED">
<mx:TextArea id="txtMessage" x="62" y="100" width="408" height="249" dropShadowVisible="true" text="" borderColor="#97515D" chromeColor="#F0BABA" contentBackgroundColor="#F2FCFA"/>
<mx:Button id="btnSendMessage" x="0" y="302" label="开始订阅" click="btnSendMessage_clickHandler(event)" chromeColor="#97D2EB" paddingBottom="0"/>
</s:VGroup>
</mx:VBox>
</mx:VBox>
</s:Application>
(2) BusInfo.as
package vo
{
[Bindable][RemoteClass(alias="com.test.jms.flex.BusInfo")]
public class BusInfo
{
public function BusInfo()
{
}
public var platenum:String;
public var speed:String;
public var direction:String;
public var lon:String;
public var lat:String;
public var receivetime:String;
public var routenum:String
}
}
八. 运行程序
1. 启动ActiveMQ
九. 总结
1.通过这样的配置可以将Spring和servlet进行整合。
2.前台接受到了公交车的基本信息就可以在地图上进行展示了,通过坐标点可以在地图上画行车轨迹了。
3.我们可以对信息进行筛选,查看特定的公交信息。
4.jar包下载地址http://download.csdn.net/detail/allen_gang/6688499