【Spring集成】-spring配置RMI

1.RMI

远程方法调用(Remote Method Invocation)。能够让在客户端Java虚拟机上的对象像调用本地对象一样调用服务端中的对象上的方法.

当然你可以通过编写java代码,自己实现RMI,但是这过程比较繁琐,而且会抛出相当多的RemoteException和

MalformedURLException异常。虽然这些异常意味着一个无法从catch代码块中恢复 的致命错误,但是我们仍然需要编写样式代码来捕获并处理这些异常--即使我们不能修复他们。

2.Spring中配置RMI服务

幸运的是,Spring提供了更简单的方式来发布RMI服务,不用在编写那些需要抛出的RemoteException异常的特定RMI类,只需要简单的编写服务功能的POJO就可以了,Spring会处理剩余的其他事项。

【Spring集成】-spring配置RMI_第1张图片

项目结构如上图

第一步先创建实体类 JinNang.java

package chapter15.spittr.domain;

import java.io.Serializable;

public class JinNang implements Serializable{
	private static final long serialVersionUID = 1L; 	
	private String jice;//计策
	private String people;//计策实施者
	
	public JinNang(String jice,String people){
		this.jice=jice;
		this.people=people;
	}

	public String getJice() {
		return jice;
	}

	public void setJice(String jice) {
		this.jice = jice;
	}

	public String getPeople() {
		return people;
	}

	public void setPeople(String people) {
		this.people = people;
	}


}

说明:该实体类必须实现Serializable接口,因为RMI使用了Java对象序列化。对象序列化参考我的另一篇文章

https://blog.csdn.net/fxkcsdn/article/details/80908634

第二步:创建服务接口JinNangService和接口实现类JinNangServiceImpl

package chapter15.spittr.service.interfaces;

import chapter15.spittr.domain.JinNang;
public interface JinNangService {
	public abstract JinNang getJinNang();

}
package chapter15.spittr.service;

import chapter15.spittr.domain.JinNang;
import chapter15.spittr.service.interfaces.JinNangService;

public class JinNangServiceImpl implements JinNangService{

	@Override
	public JinNang getJinNang() {
		JinNang j=new JinNang("苦肉计","黄盖");
		return j;
	}
}

第三部:最重要的一步:使用RmiServiceExpoter发布服务

如果我们使用传统的RMI来发布此服务,JinNangService合同JinNangServiceImpl中的所有方法都要抛出

java.rmi.RemoteException。但是如果我们使用Spring的RmiServiceExpoter把该类转变为RMI服务,那现有的实现不需要做任何改变。RmiServiceExpoter可以把任意的Spring管理的bean发布为RMI服务。如下图所示,RmiServiceExpoter把bean包装在一个适配器类中,然后适配器类就被绑定到RMI注册表中,并且代理服务类的请求--在本例中服务类就是JinNangServiceImpl


【Spring集成】-spring配置RMI_第2张图片

package chapter15.spittr.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.remoting.rmi.RmiServiceExporter;

import chapter15.spittr.service.JinNangServiceImpl;
import chapter15.spittr.service.interfaces.JinNangService;

@Configuration
@ComponentScan
public class RootConfig {	
	@Bean
	  public JinNangService jinNangService(){
		  return new JinNangServiceImpl();
	  }
	
	@Bean(name="JinNangServiceExpoter")
	  public RmiServiceExporter rmiExporter2(JinNangService jinNangService){
		  RmiServiceExporter rmiServiceExporter=new RmiServiceExporter();
		  rmiServiceExporter.setService(jinNangService);
		  rmiServiceExporter.setServiceName("JinNangService");
		  rmiServiceExporter.setServiceInterface(JinNangService.class);
		  return rmiServiceExporter;
	  }
}

这里会把JinNangService bean设置到service属性中,表明RmiServiceExpoter要把该bean发布为一个Rmi服务。serviceName属性命名了RMI服务,serviceInterface属性指定了此服务所实现的接口。在客户端可以通过该接口直接调用服务端服务,就像该服务就在客户端一样。

最后:创建SpitterWebInitializer启动服务。

package common;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import chapter15.spittr.config.RootConfig;
public class SpitterWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
  
  @Override
  protected Class[] getRootConfigClasses() {
    return new Class[] { RootConfig.class };
  }

  @Override
  protected Class[] getServletConfigClasses() {
    return null;
  }

  @Override
  protected String[] getServletMappings() {
    return new String[] { "/" };
  }

}

到此服务端就已经搞好了,启动tomcat就可以了。

下面编写客户端代码,来使用该服务。

二:编写客户端

使用Spring的RmiProxyFactoryBean,该bean可以为RMI服务创建代理,使用RmiProxyFactoryBean引用JinNangService的RMI服务是非常简单的,只需要在客户端的spring配置增加如下的@bean方法:

package chapter15.spittr.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;

import chapter15.spittr.service.interfaces.JinNangService;

@Configuration
@ComponentScan(basePackages={"chapter15.spittr"})
public class RootConfig {
	@Bean
	  public RmiProxyFactoryBean jinNangService(){
		  RmiProxyFactoryBean rmiProxy=new RmiProxyFactoryBean();
		  rmiProxy.setServiceUrl("rmi://localhost/JinNangService");
	          rmiProxy.setServiceInterface(JinNangService.class);
		  return rmiProxy;
	  }

}

服务的URL是通过RmiProxyFactoryBean的serviceUrl属性设置的,在这里,服务名被设置为JinNangService,并且生命服务实在本地机器上的;同时,服务提供的接口由serviceInterface属性来指定。

现在我们已经把RMI服务声明为Spring管理的bean,我们可以把它作为依赖装配进另一个bean中,就像任意非远程的bean那样。例如,我们可以使用JinNangService来获得一条锦囊妙计:

package chapter15.spittr.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import chapter15.spittr.config.RootConfig;
import chapter15.spittr.domain.JinNang;
import chapter15.spittr.service.interfaces.JinNangService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=RootConfig.class)
public class JaxwsTest {

	@Autowired
	JinNangService jinNangService;
	
	@Test
	public void getJinNang(){
		JinNang jinnang=jinNangService.getJinNang();
		System.out.println("获得的计策是:让"+jinnang.getPeople()+"实施"+jinnang.getJice());
	}
	
}

客户端就会得到如下输出:

        获得的计策是:让黄盖实施苦肉计

至此,服务端客户端代码已经全部写完了,怎么样,很简单吧!

总结:

    RMI是一种实现远程服务交互的好办法,但是它存在某些限制。首先RMI很难穿越防火墙,这是因为RMI使用任意的端口来进行交互,这是防火墙通常所不允许的。如果在企业内部网络环境中,我们通常不需要担心这个问题。但是如果在互联网上运行,我们用RMI可能会遇到麻烦。即使RMI提供了对HTTP通道的支持,但是建立这个通道也不是件容易的事情。

    Caucho Technology开发了一套应对RMI限制的远程调用解决方案。实际上,Caucho提供了两种解决方案:Hessian和Burlap.这里就不再赘述了,因为这两种配置和RMI几乎一模一样,如果有需要,可以再写两篇关于Hessian和Burlap的远程调用。

以上全是作者纯手打,欢迎提出改进意见,谢谢!





你可能感兴趣的:(spring)