JMS 和 Apache-ActiveMQ 简介
JMS(Java Message Service,Java 消息服务)是一个 Java 面向消息中间件(MOM)的 API,用于 Java 应用程序或分布式系统之间发送信息,异步通信;
JMS 具有以下优势
- 通信的异步性,客户端获取信息不需要主动发送请求,由 JMS 中间件自动推送信息;
- 消息发送的准确性,JMS 中间件可以保证信息只会发送一次,不会发送重复信息;
JMS 的消息传输模型有以下 2 种
1)点对点模型(P2P,queue)
P2P 模型中,应用程序有消息队列(queue),消息发送者,消息接收者组成,每一个消息发送给一个中间件队列,再由队列发送给单个接收者。具有以下的性质:
- 每一个消息只有一个接收者(当多个接收者使用同一个消息队列时,接收消息是竞争式的);
- 发布者和接收者没有时间依赖,当消息发送者发送消息时,即使但是接收者不运行,当只要接收者上线,就可以接收到信息;
- 当接收者接收到消息时,会发送确认通知;
2)发布/订阅模型(topic)
分布/订阅模型,应
用程序有主题(topic),消息发送者,一系列的消息接收者组成,topic 用于保存和传递消息,并且会一直保存到被传递到客户端。具有以下特性:
- 一个消息可以传递给多个消息接收者(当多个接收者接收到同一个消息时,每一个接收者都会接收到一份该消息的拷贝);
- 发布者和接收者有时间依赖,只有当客户端创建订阅后,才可以开始接收到消息(而且是当前开始消息发送者发布的消息),同时订阅者需要一直保持活动状态才可以接收消息;
- JMS 允许发布订阅者创建一个可持久化的订阅,这样即使订阅者没有上线,也可以在上线后接收到消息;
JMS 这是一个平台无关的 Java API,由 MOM 提供商对其进行支持,这里介绍其中比较轻量化,高效的 Apache-ActiveMQ;
ActiveMQ 项目官网:
http://activemq.apache.org
ActiveMQ的安装和部署
由于 JMS 消息中间是独立于客户端,服务端程序的,在运行程序前要先部署好 JMS 服务程序;
Active-MQ 下载地址:
http://activemq.apache.org/download.html
选择合适的系统版本下载,解压后,window 版本X64运行 apache-activemq/bin/win64/activemq.bat,
Unix 版本运行
apache-activemq/bin/activemq.sh,即可启动 ActiveMQ;
ActiveMQ 提供了一个基于内嵌 Jetty 的管理程序,可以在启动 acgtivemq 后访问服务器的
http://127.0.0.1:8161/admin 访问该管理页面(默认密码:admin,admin)
如果要增加、修改 ActiveMQ 的程序用户认证,可以在
apache-activemq/conf/activemq.xml 文件中的<broker>节点下添加:
<broker>
....
<!--增加用户认证-->
<plugins>
<simpleAuthenticationPlugin>
<users>
<authenticationUser username="assad" password="assad123" groups="admins" />
</users>
</simpleAuthenticationPlugin>
</plugins>
</broker>
要增加、修改程序访问的 openwire 路由端口,可以修改<transportConnectors
>中相关的<transportConnector>节点:
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://127.0.0.1:23333?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
......
</transportConnectors>
ActiveMQ 支持 3 种类型的数据传输对象:
- TextMessager:传输文本对象;
- MapMessager:传输 Map 类型对象;
- ObjectMessager:传输其他 Object,调用该 Object 的序列化方法序列化为二进制字节传输;
关于使用 Java 编写基于 ActiveMQ 的 JMS 基本程序,可以参考:
https://www.cnblogs.com/jaycekon/p/6225058.html
但由于直接用 Java 直接编写步骤比较繁琐,可以使用 Spring 的集成,相对简单很多,详见下面:
Spring 集成 JMS(ActiveMQ)
Spring 提供的 org.springframework:spring-jms 包对 JMS 进行了封装,使用 Spring 风格的 JmsTemplate 封装了 Adminstred Object(管理对象)、ConnectionFactory(连接工厂)、Session(会话)、Destination(目的地)等的配置;
以下示例完整代码地址:
https://gitee.com/assad/jms-spring-sample
异步模型快速示例(queue/topic)
示例代码位于以上地址的 basic_sample 路径下;
需要导入的相关依赖包:
//spring_sample 核心依赖
compile 'org.springframework:spring-core:4.3.11.RELEASE'
compile 'org.springframework:spring-beans:4.3.11.RELEASE'
//Apache-ActiveMQ ( JMS API 的一种思想) 依赖,Spring 相关支持依赖
compile 'org.apache.activemq:activemq-all:5.15.3'
compile 'org.apache.activemq:activemq-pool:5.15.3'
compile 'org.springframework:spring-jms:4.3.11.RELEASE'
服务端
在 spring 上下文配置文件中进行 ActiveMQ 相关的配置:
basic_sample/appContext-server.xml
<!--ActiveMQ 相关配置-->
<!--第三方工厂-->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
p:brokerURL="tcp://127.0.0.1:23333"
p:userName="assad"
p:password="assad123"
p:trustAllPackages="true"
p:useAsyncSend="true"/>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop"
p:connectionFactory-ref="targetConnectionFactory"
p:maxConnections="100" />
<!--spring 管理真正 ConnectionFactory 的连接工厂,使用PooledConnectionFactory 封装过的 targetConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"
p:targetConnectionFactory-ref="pooledConnectionFactory"/>
<!--目的地配置: queue(point-to-point模式) -->
<bean id="destinationQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg index="0" value="spring-queue" />
</bean>
<!--目的地配置:Topic(发布/订阅模式)-->
<bean id="destinationTopic" class="org.apache.activemq.command.ActiveMQTopic">
<constructor-arg index="0" value="spring-topic" />
</bean>
<!--配置 Spring jsmTemplate 模板,用于发送和接收消息 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"
p:connectionFactory-ref="connectionFactory">
<!--配置默认目的地(queue 或 topic)-->
<property name="defaultDestination" ref="destinationQueue" />
<!--使用spring提供的默认消息转换器,也可以装载自己实现的消息转化器-->
<property name="messageConverter">
<bean class="org.springframework.jms.support.converter.SimpleMessageConverter" /></