您的位置:首页 > 编程语言 > Java开发

Spring基于JMS实现远程访问

2011-04-24 20:47 405 查看
使用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.");
}
}


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

对应的客户端的配置client.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="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.JmsInvokerProxyFactoryBean">
<property name="serviceInterface" value="org.shirdrn.spring.remote.jms.AccountService" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="queue" ref="myQueue" />
</bean>

</beans>


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

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

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

package org.shirdrn.spring.remote.jms;

import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {

private static final Logger LOG = Logger.getLogger(Client.class);
static int index = 0;

private static void invoke(AccountService service) {
String mobileNo = "1380013800" + (String.valueOf(index++));
String result = service.shoopingPayment(mobileNo, (byte) 3);
LOG.info("Client gets result: " + result);
}

public static void main(String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] { "org/shirdrn/spring/remote/jms/client.xml" });
AccountService service = (AccountService) ctx
.getBean("myAccountService");
for(int i=0; i<100; i++) {
invoke(service);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: