基于JBOSS,用JMS实现多服务器同步业务数据的方法示例,小结供查。
 
1、配置JBOSS的JMS管理器,提供需要的队列名服务。配置文件是$JBOSS_HOME/server/all(default/minal)/deploy/jms/jbossmq-destinations-service.xml,可以参考ExampleTopic构造
MBEAN。
<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=com.companya.projectb.Topic1">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
<depends optional-attribute-name="SecurityManager">jboss.mq:service=SecurityManager</depends>
<attribute name="SecurityConf">
<security>
  <role name="guest" read="true" write="true"/>
  <role name="publisher" read="true" write="true" create="false"/>
  <role name="durpublisher" read="true" write="true" create="true"/>
</security>
</attribute>
</mbean>

2、配置JMS服务的队列名的配置文件:jms-topic.xml <!--/WEB-INF/classes目录下,方便CLASSPATH方式读取-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties version="1.0">
<entry key="topic">topic/com.companya.projectb.Topic1</entry> <!--跟JMS部署配置文件deployed-jms.xml中的destination bean的jndiName一致。-->
</properties>
3、配置JMS服务的多服务器目标的配置文件:jms-server.xml <!--/WEB-INF/classes目录下,方便CLASSPATH方式读取-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties version="1.0">
<entry key="server1">localhost</entry>
<entry key="server2">192.168.1.1</entry>
</properties>
4、web.xml中需加载用于JBOSS/TOMCAT部署的配置文件:deployed-jms.xml(用于加载收听器)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//Spring//DTD Bean//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- JMS Spring Beans -->
<!-- JMS JNDI template config -->
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<prop key="java.naming.provider.url">localhost</prop>
<prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming</prop>
</props>
</property>
</bean>
<!-- JMS Connection Factory -->
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>UIL2ConnectionFactory</value>
</property>
</bean>
<!-- JMS Topic Destination -->
<bean id="destination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>topic/com.companya.projectb.Topic1</value>
</property>
</bean>
<!-- JMS Topic Template -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref bean="connectionFactory"/>
</property>
<property name="defaultDestination">
<ref bean="destination"/>
</property>
<property name="receiveTimeout">
<value>3000</value>
</property>
</bean>
<bean id="jbossConnectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory">
<ref bean="connectionFactory" />
</property>
<property name="reconnectOnException">
<value>true</value>
</property>
</bean>
<!-- localhost receiver -->
<bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<bean class="com.companya.projectb.jms.DefaultMessageDelegate"> <!-- 你的message listener具体实现(实现MessageDelegate接口,方法有processMessage(ObjectA),
Object可以是Object的派生类,所以可以是任何数据对象)-->
<property name="prop1" ref="beanA" />
<property name="prop2" ref="beanB" /> <!--任何你要引入的类对象-->
</bean>
</constructor-arg>
</bean>
<!-- and this is the attendant message listener container -->
<bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="concurrentConsumers" value="1" />
<property name="connectionFactory" ref="jbossConnectionFactory" />
<property name="destination" ref="destination" />
<property name="subscriptionDurable" value="false" />
<property name="messageListener" ref="messageListener" />
<property name="exposeListenerSession" value="false" />
</bean>
</beans>
5、发送类的主要函数:
class JMSSimpleSender {
 private TopicSession session;
 private TopConnection conn;
 private InitialContext initCtx;
 
 public boolean setup(String targetServer)
  throws JMSException, NamingException
 {
  
   
   Hasttable env = new Hashtable();
   env.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
   env.put("java.naming.factory.url.pkgs.preffixes", "org.jnp.interfaces");
   env.put(Context.PROVIDER_URL, targetServer);
  
   initCtx = new InitialContext(env);
   TopicConnectionFactory tcf = (TopicConnectionFactory) initCtx.lookup("ConnectionFactory");
   conn = tcf.createTopicConnection();
   session = conn.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
   conn.start();
   // topic = (Topic) iniCtx.lookup(strtopic);
   return true;
  } catch (Exception ex) {
   return false;
  }
 }
 
 public void tearDown() {
  try {
   if (session != null) {
    session.close();
   }
   
   if (conn != null) {
    conn.close();
   }
  } catch (JMSException e) {
   e.printStackTrace();
  }
 }
 public synchronized void sendMessage(Object param1,Object  param2) {
  try {
   //得到每个目标JMS服务器
   Map.Entry entry;
   Properties prop = new Properties();
   FileInputStream fis = new FileInputStream("jms-server.xml");
   prop.loadFromXML(fis);
 
   Iterator it = prop.entrySet().iterator();
   while (it.hasNext()) {
    if (setup(it.next().getValue())) {
     send(Object param1,Object  param2);
    } else {
     tearDown();
    }
   }
  } catch (Exception ex) {
   e.printStackTrace();
  }
 }

 private void send(Object param1,Object  param2) {
  try {
   Map.Entry entry;
   String strtopic = "";
   Properties prop = new Properties();
   FileInputStream fis = new FileInputStream("jms-topic.xml");
   prop.loadFromXML(fis);
   Iterator it = prop.entrySet().iterator();
   while (it.hasNext()) { //投递到每个队列
    entry = (Map.Entry) it.next();
    strtopic = (String) entry.getValue();
    Topic topic = (Topic) iniCtx.lookup(strtopic);
     TopicPublisher send = session.createPublisher(topic);
    MapMessage mm = session.createMapMessage(); //other Object besides Map too.
    mm.setObject(param1, param2);
    send.publish(mm);
    send.close();
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   tearDown();
  }