Spring基于JMS实现远程访问

使用JMS作为底层通信协议,spring提供了很好的支持。我们可以基于JMS将服务暴露给外部,这一切对于外部完全透明。这里我们基于开源消息中间件ActiveMQ作为中间代理,通过在服务端将服务以消息的形式发布到代理服务器上,然后客户端通过代理服务器实现对服务的远程调用。

ActiveMQ的BrokerService可以非常容易地实现服务端与客户端进行通信的中间代理,Spring配置broker.xml内容如下所示:

[xhtml]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
  5.   
  6.     <bean id="broker" class="org.apache.activemq.broker.BrokerService" />  
  7.   
  8. </beans>  

通过Spring的IOC容器来管理BrokerService。实现一个基于ActiveMQ的消息代理服务,如下所示:

[java]  view plain  copy
  1. package org.shirdrn.spring.remote.jms;  
  2.   
  3. import org.apache.activemq.broker.BrokerService;  
  4. import org.apache.log4j.Logger;  
  5. import org.springframework.context.ApplicationContext;  
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  7.   
  8. public class Broker {  
  9.       
  10.     private static final Logger LOG = Logger.getLogger(Broker.class);  
  11.     private static final String CONNECTOR_ADDRESS = "tcp://192.168.1.103:61616";  
  12.       
  13.     public static void main(String[] args) {  
  14.         ApplicationContext ctx = new ClassPathXmlApplicationContext(  
  15.                 new String[] { "org/shirdrn/spring/remote/jms/broker.xml" });  
  16.         BrokerService broker = (BrokerService) ctx.getBean("broker");  
  17.         try {  
  18.             broker.setBrokerName("myBroker");  
  19.             broker.setUseJmx(true);  
  20.             broker.addConnector(CONNECTOR_ADDRESS);  
  21.             broker.start();  
  22.             LOG.info("Broker service started.");  
  23.               
  24.             Object lock = new Object();  
  25.             synchronized (lock) {  
  26.                 lock.wait();  
  27.             }  
  28.         } catch (InterruptedException e) {  
  29.             e.printStackTrace();  
  30.         } catch (Exception e) {  
  31.             e.printStackTrace();  
  32.         }  
  33.     }  
  34. }  

启动后,代理监听61616,等待服务端发布服务,以及远程客户端调用服务。

看一下,服务端如何进行实现。

定义服务接口和服务实现。服务接口,代码如下所示:

[java]  view plain  copy
  1. package org.shirdrn.spring.remote.jms;  
  2.   
  3. public interface AccountService {  
  4.     int queryBalance(String mobileNo);  
  5.     String shoopingPayment(String mobileNo, byte protocol);  
  6. }  

实现上述接口,示例代码如下所示:

[java]  view plain  copy
  1. package org.shirdrn.spring.remote.jms;  
  2.   
  3. import org.apache.log4j.Logger;  
  4.   
  5. public class MobileAccountServiceImpl implements AccountService {  
  6.   
  7.     private static final Logger LOG = Logger.getLogger(MobileAccountServiceImpl.class);  
  8.   
  9.     public int queryBalance(String mobileNo) {  
  10.         if (mobileNo != null)  
  11.             return 100;  
  12.         return 0;  
  13.     }  
  14.   
  15.     public String shoopingPayment(String mobileNo, byte protocol) {  
  16.         StringBuffer sb = new StringBuffer().append("Your mobile number is /"")  
  17.                 .append(mobileNo).append("/", protocol type is /"").append(  
  18.                         protocol).append("/".");  
  19.         LOG.info(sb.toString());  
  20.         return sb.toString();  
  21.     }  
  22. }  

然后,服务端的配置server.xml,内容如下所示:

[xhtml]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
  5.   
  6.     <bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">  
  7.         <property name="connectionFactory" ref="connectionFactory" />  
  8.         <property name="destination" ref="myQueue" />  
  9.         <property name="concurrentConsumers" value="3" />  
  10.         <property name="messageListener" ref="myAccountService" />  
  11.         <property name="taskExecutor" ref="threadPool" />  
  12.     </bean>  
  13.       
  14.     <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">  
  15.         <property name="brokerURL" value="tcp://192.168.1.103:61616" />  
  16.     </bean>  
  17.   
  18.     <bean id="myQueue" class="org.apache.activemq.command.ActiveMQQueue">  
  19.         <constructor-arg value="shirdrnQ" />  
  20.     </bean>  
  21.   
  22.     <bean id="myAccountService"  
  23.         class="org.springframework.jms.remoting.JmsInvokerServiceExporter">  
  24.         <property name="serviceInterface" value="org.shirdrn.spring.remote.jms.AccountService" />  
  25.         <property name="service">  
  26.             <bean class="org.shirdrn.spring.remote.jms.MobileAccountServiceImpl" />  
  27.         </property>  
  28.     </bean>  
  29.       
  30.     <bean id="threadPool" class="org.springframework.core.task.SimpleAsyncTaskExecutor">  
  31.         <property name="daemon" value="true" />  
  32.         <property name="concurrencyLimit" value="300" />  
  33.         <property name="threadNamePrefix" value="SERVICE" />  
  34.     </bean>  
  35.   
  36. </beans>  

通过Spring的org.springframework.jms.listener.SimpleMessageListenerContainer实现服务的发布,可以配置的属性有:

connectionFactory         连接工厂

destination                    消息目的地,基于ActiveMQ则是一个消息队列

concurrentConsumers   并发消息消费者数量

messageListener           消息监听器

taskExecutor                 线程池

通过上面配置可以看到,连接工厂指定了代理监听服务的端口,我们通过服务端发布服务,作为消息生产者将服务以消息的形式发布,然后客户端作为服务的消费者,通过代理来实现对远程发布服务的调用。

服务端启动的实现,如下所示:

[java]  view plain  copy
  1. package org.shirdrn.spring.remote.jms;  
  2.   
  3. import org.apache.log4j.Logger;  
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  5.   
  6. public class Server {  
  7.   
  8.     private static final Logger LOG = Logger.getLogger(Server.class);  
  9.       
  10.     public static void main(String[] args) throws Exception {  
  11.         new ClassPathXmlApplicationContext(  
  12.                 new String[] { "org/shirdrn/spring/remote/jms/server.xml" });  
  13.         LOG.info("Server started.");  
  14.     }  
  15. }  

再看一下,客户端如何进行远程访问。

对应的客户端的配置client.xml,内容如下所示:

[xhtml]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">  
  5.   
  6.     <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">  
  7.         <property name="brokerURL" value="tcp://192.168.1.103:61616" />  
  8.     </bean>  
  9.   
  10.     <bean id="myQueue" class="org.apache.activemq.command.ActiveMQQueue">  
  11.         <constructor-arg value="shirdrnQ" />  
  12.     </bean>  
  13.   
  14.     <bean id="myAccountService"  
  15.         class="org.springframework.jms.remoting.JmsInvokerProxyFactoryBean">  
  16.         <property name="serviceInterface" value="org.shirdrn.spring.remote.jms.AccountService" />  
  17.         <property name="connectionFactory" ref="connectionFactory" />  
  18.         <property name="queue" ref="myQueue" />  
  19.     </bean>  
  20.   
  21. </beans>  

主要是基于Spring提供的org.springframework.jms.remoting.JmsInvokerProxyFactoryBean来实现,通过消息中间件代理,调用远程发布的服务。

需要注意的是,客户端是通过消息队列(org.apache.activemq.command.ActiveMQQueue)的名称(如上述为shirdrnQ)来获取消息(远程服务),如果无法识别消息队列是无法实现服务的远程访问的。

客户端实现远程访问,示例代码如下所示:

[java]  view plain  copy
  1. package org.shirdrn.spring.remote.jms;  
  2.   
  3. import org.apache.log4j.Logger;  
  4. import org.springframework.context.ApplicationContext;  
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  6.   
  7. public class Client {  
  8.       
  9.     private static final Logger LOG = Logger.getLogger(Client.class);  
  10.     static int index = 0;  
  11.       
  12.     private static void invoke(AccountService service) {  
  13.         String mobileNo = "1380013800" + (String.valueOf(index++));  
  14.         String result = service.shoopingPayment(mobileNo, (byte3);  
  15.         LOG.info("Client gets result: " + result);  
  16.     }  
  17.       
  18.     public static void main(String[] args) throws Exception {  
  19.         ApplicationContext ctx = new ClassPathXmlApplicationContext(  
  20.                 new String[] { "org/shirdrn/spring/remote/jms/client.xml" });  
  21.         AccountService service = (AccountService) ctx  
  22.                 .getBean("myAccountService");  
  23.         for(int i=0; i<100; i++) {  
  24.             invoke(service);  
  25.         }  
  26.     }  
  27. }  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值