参考:http://static.springsource.org/spring/docs/3.1.2.RELEASE/spring-framework-reference/html/remoting.html
1.bean
package cmei.spring.integration.remote.dto;
import java.io.Serializable;
public class AccountDto implements Serializable{
private static final long serialVersionUID = -6934673060016735451L;
private String aid;
private int accountType;
public void setAid(String aid){
this.aid=aid;
}
public String getAid(){
return this.aid;
}
public void setAccountType(int type){
this.accountType=type;
}
public int getAccountType(){
return this.accountType;
}
}
package cmei.spring.integration.remote.dto;
public class AccountADto extends AccountDto{
private static final long serialVersionUID = -4493938811608030586L;
private String a;
public void setA(String a){
this.a=a;
}
public String getA(){
return a;
}
}
package cmei.spring.integration.remote.dto;
public class AccountBDto extends AccountDto{
/**
*
*/
private static final long serialVersionUID = -466891496674029640L;
private String b;
public void setB(String b){
this.b=b;
}
public String getB(){
return b;
}
}
2. interface defined on client side
package cmei.spring.integration.remote.api;
import java.util.List;
import cmei.spring.integration.remote.dto.AccountDto;
public interface IAccountService {
List<AccountDto> getAllAccounts();
}
3. implementation on server side
package cmei.spring.integration.remote.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import cmei.spring.integration.remote.api.IAccountService;
import cmei.spring.integration.remote.dto.AccountDto;
import cmei.spring.integration.remote.dto.AccountADto;
import cmei.spring.integration.remote.dto.AccountBDto;
@Service("accountServiceImpl")
public class AccountServiceImpl implements IAccountService{
@Override
public List<AccountDto> getAllAccounts() {
List<AccountDto> accounts=new ArrayList<AccountDto>();
//fake data
AccountADto accountA=new AccountADto();
accountA.setAid("aid1");
accountA.setAccountType(1);
accountA.setA("a");
accounts.add(accountA);
AccountBDto accountB=new AccountBDto();
accountB.setAid("aid2");
accountB.setAccountType(2);
accountB.setB("b");
accounts.add(accountB);
return accounts;
}
}
4. config using RMI
1) config on client side
remote.properties 定义需要连接的sever的host,port 和相应service的url
#remote rmi service
rmi.proxy.host=localhost
rmi.proxy.port=1199
rmi.proxy.path=rmi
rmi.proxy.url=rmi://${rmi.proxy.host}:${rmi.proxy.port}/${rmi.proxy.path}
context config remote-rmi-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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:property-placeholder location="classpath:configs/remote.properties" />
<bean id="accountService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl" value="${rmi.proxy.url}/accountService"/>
<property name="serviceInterface" value="cmei.spring.integration.remote.api.IAccountService"/>
</bean>
</beans>
2) config on server side:
context config remote-rmi-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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="cmei.spring.integration.remote"></context:component-scan>
<bean id="rmiExporter" class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- does not necessarily have to be the same name as the bean to be exported -->
<property name="serviceName" value="rmi/accountService"/>
<property name="service" ref="accountServiceImpl"/>
<property name="serviceInterface" value="cmei.spring.integration.remote.api.IAccountService"/>
<!-- defaults to 1099 -->
<property name="registryPort" value="1199"/>
</bean>
</beans>
3) test cases
start server
package cmei.spring.integration.remote;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class RemoteMain {
public static void main(String args[]){
ApplicationContext context=new ClassPathXmlApplicationContext("contexts/remote-rmi-server.xml");
System.out.println("rmi start...");
}
}
运行结果:
Dec 5, 2012 3:12:31 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2dcb25f1: startup date [Wed Dec 05 15:12:31 CST 2012]; root of context hierarchy
Dec 5, 2012 3:12:31 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [contexts/remote-rmi-server.xml]
Dec 5, 2012 3:12:31 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@7dce784b: defining beans [accountServiceImpl,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,rmiExporter]; root of factory hierarchy
Dec 5, 2012 3:12:31 PM org.springframework.remoting.rmi.RmiServiceExporter getRegistry
INFO: Looking for RMI registry at port '1199'
Dec 5, 2012 3:12:32 PM org.springframework.remoting.rmi.RmiServiceExporter getRegistry
INFO: Could not detect RMI registry - creating new one
Dec 5, 2012 3:12:32 PM org.springframework.remoting.rmi.RmiServiceExporter prepare
INFO: Binding service 'rmi/accountService' to RMI registry: RegistryImpl[UnicastServerRef [liveRef: [endpoint:[ip:1199](local),objID:[0:0:0, 0]]]]
rmi start...
client test
package cmei.spring.integration.remote;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cmei.spring.integration.remote.api.IAccountService;
public class RemoteClientMain {
public static void main(String args[]){
ApplicationContext context=new ClassPathXmlApplicationContext("contexts/remote-rmi-client.xml");
IAccountService accountService=(IAccountService)context.getBean("accountService");
System.out.println(accountService.getAllAccounts().size());
}
}
运行结果:
Dec 5, 2012 3:14:00 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2dcb25f1: startup date [Wed Dec 05 15:14:00 CST 2012]; root of context hierarchy
Dec 5, 2012 3:14:01 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [contexts/remote-rmi-client.xml]
Dec 5, 2012 3:14:01 PM org.springframework.core.io.support.PropertiesLoaderSupport loadProperties
INFO: Loading properties file from class path resource [configs/remote.properties]
Dec 5, 2012 3:14:01 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@4eedf3f6: defining beans [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,accountService]; root of factory hierarchy
2
5. config using HTTP
1)config on client side
remote.properties
#remote http service
service.proxy.host=localhost
service.proxy.port=8080
service.proxy.path=remote
service.proxy.url=http://${service.proxy.host}:${service.proxy.port}/${service.proxy.path}
remote-http-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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:property-placeholder location="classpath:configs/remote.properties" />
<bean id="accountService" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="${service.proxy.url}/account"/>
<property name="serviceInterface" value="cmei.spring.integration.remote.api.IAccountService"/>
</bean>
</beans>
2)config on server side
为测试方便(在容器外测试),使用spring 内建的http server
remote-http-server2.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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="cmei.spring.integration.remote"></context:component-scan>
<bean name="accountService" class="org.springframework.remoting.httpinvoker.SimpleHttpInvokerServiceExporter">
<property name="service" ref="accountServiceImpl" />
<property name="serviceInterface" value="cmei.spring.integration.remote.api.IAccountService" />
</bean>
<!-- servlet:http invoker runing outside of a servlet container-->
<bean id="httpServer" class="org.springframework.remoting.support.SimpleHttpServerFactoryBean">
<property name="contexts">
<util:map>
<entry key="/remote/account" value-ref="accountService"/>
</util:map>
</property>
<property name="port" value="8080" />
</bean>
实际应用中,常使用tomcat作为server,以spring mvc 的DispatcherServlet
来暴露service
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="cmei.spring.integration.remote"></context:component-scan>
<bean id="accountService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="accountServiceImpl" />
<property name="serviceInterface" value="cmei.spring.integration.remote.api.IAccountService" />
</bean>
<!-- servlet:http invoker -->
<bean name="urlHandlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>/remote/account=accountService
</value>
</property>
</bean>
<bean name="httpRequestHandlerAdapter" class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
</beans>
3)test cases
在容器外测试:
start server : 替换RemoteMain中配置文件并运行
运行结果:
Dec 5, 2012 3:15:16 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@742808b3: startup date [Wed Dec 05 15:15:16 CST 2012]; root of context hierarchy
Dec 5, 2012 3:15:16 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [contexts/remote-http-server2.xml]
Dec 5, 2012 3:15:16 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@320cf66b: defining beans [accountServiceImpl,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,accountService,httpServer]; root of factory hierarchy
Dec 5, 2012 3:15:16 PM org.springframework.remoting.support.SimpleHttpServerFactoryBean afterPropertiesSet
INFO: Starting HttpServer at address 0.0.0.0/0.0.0.0:8080
http start...
client:替换RemoteClientMain中配置文件并运行
运行结果:
Dec 5, 2012 3:16:22 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@742808b3: startup date [Wed Dec 05 15:16:22 CST 2012]; root of context hierarchy
Dec 5, 2012 3:16:22 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [contexts/remote-http-client.xml]
Dec 5, 2012 3:16:22 PM org.springframework.core.io.support.PropertiesLoaderSupport loadProperties
INFO: Loading properties file from class path resource [configs/remote.properties]
Dec 5, 2012 3:16:22 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@682bc3f5: defining beans [org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0,accountService]; root of factory hierarchy
2
容器内:
start server: 讲server端context配置加入你的servlet context配置(web.xml)中,打包部署,并启动tomcat
client: 同上