SpringBoot的开发确实及其快速,但是其中也不免有一些需要注意的地方,此次使用SpringBoot进行RMI调用完全是相适应当下的Spring发展趋势。代码的git地址,拷贝吧少年:https://github.com/singgel/Spring-SkillTree
此次写的比较简单,首先从服务端的创建开始:
1、首先建立一个服务接口类,里面的方法什么的随便定义,此处附上我的代码
package com.hks.springrmi.service;
public interface RMIExService {
String invokingRemoteService();
}
然后定义一个实现该接口的类:
package com.hks.springrmi.service.impl;
import com.hks.springrmi.service.RMIExService;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
/**
* @Author: hekuangsheng
* @Date: 2018/10/10
*/
@Service(value="rmiExServiceImpl")
public class RMIExServiceImpl implements RMIExService{
@PostConstruct
public void initMethod(){
System.out.println("我是初始化方法时调用的");
}
@Override
public String invokingRemoteService() {
// TODO Auto-generated method stub
String result="欢迎你调用远程接口";
return result;
}
}
接下来是配置bean,之前这块是配置在xml文件中的,但是SpringBoot推荐使用全注解,完全按照java自有的方式去调用,所以咱们也不能对着干,按照人家的约定来,其实也还是挺方便的
配置类代码:
package com.hks.springrmi.config;
import com.hks.springrmi.service.RMIExService;
import com.hks.springrmi.service.impl.RMIExServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.remoting.rmi.RmiServiceExporter;
/**
* @Author: hekuangsheng
* @Date: 2018/10/10
*/
@Configuration
public class RMIConfig {
@Autowired
@Qualifier("rmiExServiceImpl")
private RMIExServiceImpl serviceImpl;
/**
* 方法描述:
* 注意事项:
*
* @return
* @Exception 异常对象
*/
@Bean
public RmiServiceExporter initRmiServiceExporter() {
RmiServiceExporter exporter = new RmiServiceExporter();
exporter.setServiceInterface(RMIExService.class);
exporter.setServiceName("rmiService");
exporter.setService(serviceImpl);
exporter.setServicePort(6666);
return exporter;
}
}
调试这块的时候有坑,就是你设定了exporter.setServicePort(6666);这块代码之后,却并不起作用,RMI本身就是端口绑定不固定,此处虽然显视的定义了该接口但是却并没有起作用,通过查看服务端启动日志,我可以看到如下的一段话:
2018-10-10 10:24:56.707 INFO 10918 --- [ main] o.s.remoting.rmi.RmiServiceExporter : Looking for RMI registry at port '1099'
2018-10-10 10:24:56.714 INFO 10918 --- [ main] o.s.remoting.rmi.RmiServiceExporter : Could not detect RMI registry - creating new one
2018-10-10 10:24:56.743 INFO 10918 --- [ main] o.s.remoting.rmi.RmiServiceExporter : Binding service 'rmiService' to RMI registry: RegistryImpl[UnicastServerRef [liveRef: [endpoint:[127.0.0.1:1099](local),objID:[0:0:0, 0]]]]
2018-10-10 10:24:56.974 INFO 10918 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
这里说明这个远程服务被绑定到了127.0.0.1:1099这个地址上。此处主要是针对客户端报地址找不到的错误。到这里基本上配置算是完成了,但是有一点需要注意,就是在你的Bootstrap类中需要声明下扫描注解类的注解@ComponentScan。我遇到了我的服务实现类没有自动加载到容器中的错误,所以此处需要注意下。
下面就是我们的客户端了,客户端的配置很简单,大环境还是Springboot下。
你首先还是需要将服务端的接口类打成jar包放入你的客户端。
<dependency>
<groupId>com.hks</groupId>
<artifactId>spring-rmi</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
然后配置一个RMI的配置类,此处需要注入Bean,RmiProxyFactoryBean这个类是Spring提供的管理RMI远程服务的工厂类,避免了原使使用Naming.lookup(),违反Spring依赖注入原则的形式。下面是配置的客户端类:
package com.hks.springrmiclient.config;
import com.hks.springrmi.service.RMIExService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
/**
* @Author: hekuangsheng
* @Date: 2018/10/10
*/
@Configuration
public class RMIClientConfig {
@Bean(name = "rmiService")
public RmiProxyFactoryBean initRmiProxyFactoryBean() {
RmiProxyFactoryBean factoryBean = new RmiProxyFactoryBean();
factoryBean.setServiceUrl("rmi://127.0.0.1:1099/rmiService");
factoryBean.setServiceInterface(RMIExService.class);
return factoryBean;
}
}
调用方式是:
package com.hks.springrmiclient;
import com.hks.springrmi.service.RMIExService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringRmiClientApplicationTests {
@Autowired
@Qualifier("rmiService")
private RmiProxyFactoryBean factoryBean;
@Test
public void contextLoads() {
RMIExService service=(RMIExService)factoryBean.getObject();
System.out.println(service.invokingRemoteService());
}
}
之前在类中已经注入了属性,到这里完整的例子已经完成了,很简单,对于传输对象来说,需要对对象进行序列化。