Java RMI使用

1. Java RMI介紹

RMI:遠程方法調用(Remote Method Invocation)。可以讓在某個java虛擬機上的對象像調用本地對象方法同樣調用另外一個java 虛擬機中的對象上的方法。html

1.RMI遠程調用步驟

  1. 客戶對象調用客戶端輔助對象上的方法
  2. 客戶端輔助對象打包調用信息(變量,方法名),經過網絡發送給服務端輔助對象
  3. 服務端輔助對象將客戶端輔助對象發送來的信息解包,找出真正被調用的方法以及該方法所在對象
  4. 調用真正服務對象上的真正方法,並將結果返回給服務端輔助對象
  5. 服務端輔助對象將結果打包,發送給客戶端輔助對象
  6. 客戶端輔助對象將返回值解包,返回給客戶對象
  7. 客戶對象得到返回值

2.RMI優缺點

  • 優勢: 移植性好,服務器代碼可移植到客戶端;
  • 缺點: 服務端和客戶端都須要是Java。

對於客戶對象來講,步驟2-6是徹底透明的。
以上簡明扼要的介紹了什麼是RMI和調用步驟,接下來,說說在程序中是如何使用rmi的。java

2. 僅在jdk下程序中的使用

1. RMI服務端

1.建立一個服務端項目rmi-server
2.建立遠程方法接口,該接口須要實現Remote接口git

public interface IHelloService extends Remote {

    public String sayHello(String name) throws RemoteException;

    public int sum(int a, int b) throws RemoteException;
}

3.建立遠程方法接口實現類,而後執行main方法就等於啓動了rmi服務端了spring

public class HelloServiceImpl extends UnicastRemoteObject implements IHelloService {

    public HelloServiceImpl() throws RemoteException {
        super();
    }
    @Override
    public String sayHello(String name) throws RemoteException {
        return "hello: " + name;
    }

    @Override
    public int sum(int a, int b) throws RemoteException {
        return a + b;
    }

    public static void main(String args[]) {
        try {
            //建立一個遠程對象
            IHelloService helloService = new HelloServiceImpl();
            //生成遠程對象註冊表Registry的實例,並指定端口爲8888(默認端口是1099)
            LocateRegistry.createRegistry(8888);

            //把遠程對象註冊到RMI註冊服務器上,並命名爲RHello
            //綁定的URL標準格式爲:rmi://host:port/name(協議名能夠省略,下面兩種寫法均可以)
            Naming.bind("rmi://127.0.0.1:8888/HelloService", helloService);

            System.out.println(">>INFO:遠程IHello對象綁定成功!");
        } catch (RemoteException e) {
            System.out.println("建立遠程對象發生異常!");
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            System.out.println("發生重複綁定對象異常!");
            e.printStackTrace();
        } catch (MalformedURLException e) {
            System.out.println("發生URL畸形異常!");
            e.printStackTrace();
        }
    }
}

2. RMI客戶端

1.新建一個客戶端項目rmi-client
2.複製服務端的遠程方法接口IHelloService,注意,包名要一致
3.測試類調用RMI服務springboot

public class HelloServiceClientTest {
    @Test
    public void testSayHello() {
        try {
            // 在RMI服務註冊表中查找名稱爲RHello的對象,並調用其上的方法
            IHelloService rhello = (IHelloService) Naming.lookup("rmi://127.0.0.1:8888/HelloService");
            System.out.println(rhello.sayHello("world"));
            System.out.println(rhello.sum(454, 5457));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 在spring封裝下程序中的使用

1. RMI服務端

1.建立一個基於Sringboot的項目rmi-server
2.建立一個遠程方法接口服務器

package com.wp.learn.spring.remoting;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IHelloService extends Remote {

    public String sayHello(String name) throws RemoteException;

    public int sum(int a, int b) throws RemoteException;
}

3.實現遠程方法接口網絡

package com.wp.learn.spring.remoting.impl;

import com.wp.learn.jdk.remoting.IHelloService;
import org.springframework.stereotype.Service;

import java.rmi.RemoteException;


@Service
public class HelloServiceImpl implements IHelloService {

    @Override
    public String sayHello(String name) throws RemoteException {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "hello: " + name;
    }

    @Override
    public int sum(int a, int b) throws RemoteException {
        return a + b;
    }
}

4.rmi相關配置app

@Configuration
public class RMIConfig {

    @Autowired
    @Qualifier("helloServiceImpl")
    private HelloServiceImpl helloService;

    @Bean
    public RmiServiceExporter initRmiServiceExporter(){
        RmiServiceExporter exporter=new RmiServiceExporter();
        exporter.setServiceInterface(IHelloService.class);
        exporter.setServiceName("HelloService");
        exporter.setService(helloService);
        exporter.setRegistryPort(10086);
        return exporter;
    }
}

2. RMI客戶端

1.建立一個基於springboot的項目rmi-client
2.建立和服務端同樣的遠程方法接口,注意包名一致
3.rmi配置ide

@Configuration
public class RMIClientConfig {

    @Bean(name = "helloService")
    public RmiProxyFactoryBean initRmiProxyFactoryBean() {
        RmiProxyFactoryBean factoryBean = new RmiProxyFactoryBean();
        factoryBean.setServiceUrl("rmi://127.0.0.1:10086/HelloService");
        factoryBean.setServiceInterface(IHelloService.class);
        factoryBean.setLookupStubOnStartup(false);
        factoryBean.setRefreshStubOnConnectFailure(true);
//        lookupStubOnStartup : 這個屬性是表示,不在容器啓動的時候建立與Server端的鏈接;
//        refreshStubOnConnectFailure : 這個屬性是表示是否鏈接出錯時自動重連;
//        registryClientSocketFactory : 這個是客戶端與服務端建立SOCKECT的一個工廠。
        return factoryBean;
    }
}

4.調用接口測試測試

@RestController
@RequestMapping(value = "/v1/")
public class RMIClientController {

//    @Autowired
//    @Qualifier(value = "helloService")
//    IHelloService helloService;

    @Autowired
    IHelloService helloService;

    @RequestMapping(value = "/test")
    public String test1() {
//        IHelloService helloService = (IHelloService) factoryBean.getObject();
        try {
            System.out.println(helloService.sayHello("小青"));
            System.out.println("----------------------------------");
            System.out.println(helloService.sum(132, 355));
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return "123";
    }
}

大功告成!源碼地址: https://gitee.com/wangpinggs/learn/tree/master 相關博客: http://www.blogjava.net/zhenyu33154/articles/320245.html http://elf8848.iteye.com/blog/1961205

相關文章
相關標籤/搜索