发表时间:2007-07-18
最后修改:2009-06-08
使用Spring进行远程访问与Web服务
17.1. 简介
Spring为各种远程访问技术的集成提供了工具类。Spring远程支持是由普通(Spring)POJO实现的,这使得开发具有远程访问功能的服务变得相当容易。目前,Spring支持四种远程技术:
• 远程方法调用(RMI)。通过使用 RmiProxyFactoryBean 和 RmiServiceExporter,Spring同时支持传统的RMI(使用java.rmi.Remote接口和java.rmi.RemoteException)和通过RMI调用器实现的透明远程调用(支持任何Java接口)。
• Spring的HTTP调用器。Spring提供了一种特殊的允许通过HTTP进行Java串行化的远程调用策略,支持任意Java接口(就像RMI调用器)。相对应的支持类是 HttpInvokerProxyFactoryBean 和 HttpInvokerServiceExporter。
• Hessian。通过 HessianProxyFactoryBean 和 HessianServiceExporter,可以使用Caucho提供的基于HTTP的轻量级二进制协议来透明地暴露服务。
• Burlap。 Burlap是Caucho的另外一个子项目,可以作为Hessian基于XML的替代方案。Spring提供了诸如 BurlapProxyFactoryBean 和 BurlapServiceExporter 的支持类。
• JAX RPC。Spring通过JAX-RPC为远程Web服务提供支持。
• JMS(待实现)。
在讨论Spring对远程访问的支持时,我们将使用下面的域模型和对应的服务:
package com.test.spring;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
/**
* 用户和服务层交互的对象,即用来传递数据的对象
*
* @author test
*
*/
public class Account implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2151697717808881589L;
private String name;
private int amount;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
public Account(String name, int amount) {
super();
this.name = name;
this.amount = amount;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}
package com.test.spring;
import java.util.List;
/**
* 服务层接口,对外公布的接口
*
* @author test
*
*/
public interface AccountService {
/**
* 插入帐户信息
* @param account
*/
public void insertAccount(Account account);
/**
*
* 根据帐户名称取对应帐户信息集合
* @param name
* @return
*/
public List getAccounts(String name);
}
package com.test.spring;
import java.util.ArrayList;
import java.util.List;
/**
* 服务端实现发布的服务的实现类
* @author test
*
*/
public class AccountServiceImpl implements AccountService {
private List list=new ArrayList();
@SuppressWarnings("unchecked")
public void insertAccount(Account acc) {
this.list.add(acc);
}
@SuppressWarnings("unchecked")
public List getAccounts(String name) {
List tempList=new ArrayList();
for(int i=0;i if (((Account)list.get(i)).getName().equals(name)){
tempList.add(list.get(i));
}
}
return tempList;
}
}
在eclipse 中建立一个 java_web工程,
Web-inf/lib下加入以下包:
Commons-lang.jar
Connons-logging.jar
Hessian.jar
Spring.jar
Spring-aspects.jar
将上面的代码放到src下
Web.xml中加入:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/remoting-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
remoting-servlet.xml的内容:
<bean class="com.liuxt.spring.AccountServiceImpl" id="accountService"></bean><beans>
<bean id="accountService" class="com.liuxt.spring.AccountServiceImpl">
<!-- any additional properties, maybe a DAO? -->
</bean>
<!--httpinvoker config -->
<bean name="/AccountService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter" singleton="false">
<property name="service" ref="accountService"/>
<property name="serviceInterface" value="com.liuxt.spring.AccountService"/>
</bean>
在eclpse中启动 tomcat
确保没有错误,正常启动
以上服务端的程序建立完毕
下面是客户端的程序的建立
建立一个普通的java工程
将服务端的类:Account和AccountService复制到该工程的src下,确保包名不变
正常的工程是需要服务端把发布的接口和数据对象bean,打成jar包,发给客户端
客户端也需要上面的服务器倒入的jar包
package spring.client;
import com.test.spring.AccountService;
/**
* 该类主要在客户端用于调用服务器的发布的服务
* @author test
*
*/
public class SimpleObject {
private AccountService accountService;
public void setAccountService(AccountService accountService) {
this.accountService = accountService;
}
public AccountService getAccountService() {
return accountService;
}
}
Src 目录下建立BeanHttpInvoker.xml
内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean class="spring.client.SimpleObject">
<property name="accountService" ref="httpInvokerProxy"/>
</bean>
<bean id="httpInvokerProxy" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8080/SpringWebRomote/remoting/AccountService"/>
<property name="serviceInterface" value="com.liuxt.spring.AccountService"/>
</bean>
</beans>
注意url的填写,需要用你的web工程的名字替换
客户测试程序;
package spring.client;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.test.spring.Account;
public class HttpInvokerClient {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
"BeanHttpInvoker.xml");
SimpleObject simpleObject = (SimpleObject) applicationContext
.getBean("spring.client.SimpleObject");
Account account = new Account("cccc", 30);
simpleObject.getAccountService().insertAccount(account);
System.out.println("dddd"
+ simpleObject.getAccountService().getAccounts("cccc"));
}
}
当然可以用其他的方法,文档最开头介绍的几个部分
具体参考spring2.0的官方在线文档