作者:仙走壹步 | 来源:互联网 | 2017-11-02 13:17
使用JMS作为底层通信协议,Spring提供了很好的支持。我们可以基于JMS将服务暴露给外部,这一切对于外部完全透明。这里我们基于开源消息中间件ActiveMQ作为中间代理,通过在服务端将服务以消息的形式发布到代理服务器上,然后客户端通过代理服务器实现对服务
使用JMS作为底层通信协议,Spring提供了很好的支持。我们可以基于JMS将服务暴露给外部,这一切对于外部完全透明。这里我们基于开源消息中间件ActiveMQ作为中间代理,通过在服务端将服务以消息的形式发布到代理服务器上,然后客户端通过代理服务器实现对服务的远程调用。
ActiveMQ的BrokerService可以非常容易地实现服务端与客户端进行通信的中间代理,Spring配置broker.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:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
- <bean id="broker" class="org.apache.activemq.broker.BrokerService" />
-
- beans>
通过Spring的IOC容器来管理BrokerService。实现一个基于ActiveMQ的消息代理服务,如下所示:
- package org.shirdrn.spring.remote.jms;
-
- import org.apache.activemq.broker.BrokerService;
- import org.apache.log4j.Logger;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class Broker {
-
- private static final Logger LOG = Logger.getLogger(Broker.class);
- private static final String CONNECTOR_ADDRESS = "tcp://192.168.1.103:61616";
-
- public static void main(String[] args) {
- ApplicationContext ctx = new ClassPathXmlApplicationContext(
- new String[] { "org/shirdrn/spring/remote/jms/broker.xml" });
- BrokerService broker = (BrokerService) ctx.getBean("broker");
- try {
- broker.setBrokerName("myBroker");
- broker.setUseJmx(true);
- broker.addConnector(CONNECTOR_ADDRESS);
- broker.start();
- LOG.info("Broker service started.");
-
- Object lock = new Object();
- synchronized (lock) {
- lock.wait();
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
启动后,代理监听61616,等待服务端发布服务,以及远程客户端调用服务。
看一下,服务端如何进行实现。
定义服务接口和服务实现。服务接口,代码如下所示:
- package org.shirdrn.spring.remote.jms;
-
- public interface AccountService {
- int queryBalance(String mobileNo);
- String shoopingPayment(String mobileNo, byte protocol);
- }
实现上述接口,示例代码如下所示:
- package org.shirdrn.spring.remote.jms;
-
- import org.apache.log4j.Logger;
-
- public class MobileAccountServiceImpl implements AccountService {
-
- private static final Logger LOG = Logger.getLogger(MobileAccountServiceImpl.class);
-
- public int queryBalance(String mobileNo) {
- if (mobileNo != null)
- return 100;
- return 0;
- }
-
- public String shoopingPayment(String mobileNo, byte protocol) {
- StringBuffer sb = new StringBuffer().append("Your mobile number is /"")
- .append(mobileNo).append("/", protocol type is /"").append(
- protocol).append("/".");
- LOG.info(sb.toString());
- return sb.toString();
- }
- }
然后,服务端的配置server.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:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
-
- <bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">
- <property name="connectionFactory" ref="connectionFactory" />
- <property name="destination" ref="myQueue" />
- <property name="concurrentConsumers" value="3" />
- <property name="messageListener" ref="myAccountService" />
- <property name="taskExecutor" ref="threadPool" />
- bean>
-
- <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
- <property name="brokerURL" value="tcp://192.168.1.103:61616" />
- bean>
-
- <bean id="myQueue" class="org.apache.activemq.command.ActiveMQQueue">
- <constructor-arg value="shirdrnQ" />
- bean>
-
- <bean id="myAccountService"
- class="org.springframework.jms.remoting.JmsInvokerServiceExporter">
- <property name="serviceInterface" value="org.shirdrn.spring.remote.jms.AccountService" />
- <property name="service">
- <bean class="org.shirdrn.spring.remote.jms.MobileAccountServiceImpl" />
- property>
- bean>
-
- <bean id="threadPool" class="org.springframework.core.task.SimpleAsyncTaskExecutor">
- <property name="daemon" value="true" />
- <property name="concurrencyLimit" value="300" />
- <property name="threadNamePrefix" value="SERVICE" />
- bean>
-
- beans>
通过Spring的org.springframework.jms.listener.SimpleMessageListenerContainer实现服务的发布,可以配置的属性有:
connectionFactory 连接工厂
destination 消息目的地,基于ActiveMQ则是一个消息队列
concurrentConsumers 并发消息消费者数量
messageListener 消息监听器
taskExecutor 线程池
通过上面配置可以看到,连接工厂指定了代理监听服务的端口,我们通过服务端发布服务,作为消息生产者将服务以消息的形式发布,然后客户端作为服务的消费者,通过代理来实现对远程发布服务的调用。
服务端启动的实现,如下所示:
- package org.shirdrn.spring.remote.jms;
-
- import org.apache.log4j.Logger;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- public class Server {
-
- private static final Logger LOG = Logger.getLogger(Server.class);
-
- public static void main(String[] args) throws Exception {
- new ClassPathXmlApplicationContext(
- new String[] { "org/shirdrn/spring/remote/jms/server.xml" });
- LOG.info("Server started.");
- }
- }