24.6 JMS

使用JMS来作为底层的通信协议透明暴露服务也是可能的。Spring框架中对JMS的远程支持也很基础 – 它在同一线程和同一个非事务 Session上发送和接收,这些吞吐量将非常依赖于实现。需要注意的是这些单线程和非事务的约束仅适用于Spring的JMS远程处理支持。请参见 第26章, JMS (Java消息服务),Spring对基于JMS的消息的丰富支持。 下面的接口可同时用在服务端和客户端。

  1. package com.foo;
  2. public interface CheckingAccountService {
  3. public void cancelAccount(Long accountId);
  4. }

对于上面接口的使用在服务的端简单实现如下:

  1. package com.foo;
  2. public class SimpleCheckingAccountService implements CheckingAccountService {
  3. public void cancelAccount(Long accountId) {
  4. System.out.println("Cancelling account [" + accountId + "]");
  5. }
  6. }

这个包含JMS设施的bean的配置文件可同时用在客户端和服务端: <?xml version=”1.0″ encoding=”UTF-8″?>

  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"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
  7. <property name="brokerURL" value="tcp://ep-t43:61616"/>
  8. </bean>
  9. <bean id="queue" class="org.apache.activemq.command.ActiveMQQueue">
  10. <constructor-arg value="mmm"/>
  11. </bean>
  12. </beans>

24.6.1 服务端配置

在服务端你只需要使用JmsInvokerServiceExporter来暴露服务对象。

  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"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <bean id="checkingAccountService"
  7. class="org.springframework.jms.remoting.JmsInvokerServiceExporter">
  8. <property name="serviceInterface" value="com.foo.CheckingAccountService"/>
  9. <property name="service">
  10. <bean class="com.foo.SimpleCheckingAccountService"/>
  11. </property>
  12. </bean>
  13. <bean class="org.springframework.jms.listener.SimpleMessageListenerContainer">
  14. <property name="connectionFactory" ref="connectionFactory"/>
  15. <property name="destination" ref="queue"/>
  16. <property name="concurrentConsumers" value="3"/>
  17. <property name="messageListener" ref="checkingAccountService"/>
  18. </bean>
  19. </beans>
  1. package com.foo;
  2. import org.springframework.context.support.ClassPathXmlApplicationContext;
  3. public class Server {
  4. public static void main(String[] args) throws Exception {
  5. new ClassPathXmlApplicationContext(new String[]{"com/foo/server.xml", "com/foo/jms.xml"});
  6. }
  7. }

24.6.2 客户端配置

客户端只需要创建一个客户端代理来实现上面的接口(CheckingAccountService)。根据后面的bean定义创建的结果对象可以被注入到其它客户端对象中,而这个代理会负责通过JMS将调用转发到服务端。

  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"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <bean id="checkingAccountService"
  7. class="org.springframework.jms.remoting.JmsInvokerProxyFactoryBean">
  8. <property name="serviceInterface" value="com.foo.CheckingAccountService"/>
  9. <property name="connectionFactory" ref="connectionFactory"/>
  10. <property name="queue" ref="queue"/>
  11. </bean>
  12. </beans>
  1. package com.foo;
  2. import org.springframework.context.ApplicationContext;
  3. import org.springframework.context.support.ClassPathXmlApplicationContext;
  4. public class Client {
  5. public static void main(String[] args) throws Exception {
  6. ApplicationContext ctx = new ClassPathXmlApplicationContext(
  7. new String[] {"com/foo/client.xml", "com/foo/jms.xml"});
  8. CheckingAccountService service = (CheckingAccountService) ctx.getBean("checkingAccountService");
  9. service.cancelAccount(new Long(10));
  10. }
  11. }