基于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();
}