1. 概述
Java 的 遠程方法調用 (Remote Method Invocation, RMI) 允許在不同的 Java 虛擬機 中調用對象。 儘管這是一種成熟的技術,但由於其使用起來有些繁瑣,正如 Oracle 官方的關於該主題的教程 http://docs.oracle.com/javase/tutorial/rmi/index.html 所展示的,但其使用起來有些繁瑣。
在本文中,我們將探討如何通過 Spring Remoting 更輕鬆、更簡潔地利用 RMI。
本文還完成了對 Spring Remoting 的概述。 您可以在之前的章節中找到有關其他支持的技術的詳細信息: HTTP 調用者、JMS、AMQP、Hessian 和 Burlap。
2. Maven 依賴項
正如我們在之前的文章中所做的那樣,我們將設置兩個 Spring Boot 應用程序:一個暴露遠程可調用對象的服務器和一個調用該服務的客户端。
我們需要的一切都包含在 spring-context 庫中——因此我們可以使用我們喜歡的任何 Spring Boot 輔助工具將其引入——因為我們的主要目標只是提供主要庫。
現在,讓我們繼續使用標準的 spring-boot-starter-web,同時記住要刪除 Tomcat 依賴項以排除嵌入式 Web 服務:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>3. 服務器應用程序
我們將聲明一個接口,該接口定義了一個用於預訂出租車行程的服務,該服務最終將暴露給客户端。
public interface CabBookingService {
Booking bookRide(String pickUpLocation) throws BookingException;
}然後,我們將定義一個實現該接口的 Bean。這個 Bean 將實際在服務器端執行業務邏輯:
@Bean
CabBookingService bookingService() {
return new CabBookingServiceImpl();
}讓我們繼續聲明用於向客户端提供服務的 Exporter。在這種情況下,我們將使用 RmiServiceExporter:
@Bean
RmiServiceExporter exporter(CabBookingService implementation) {
Class<CabBookingService> serviceInterface = CabBookingService.class;
RmiServiceExporter exporter = new RmiServiceExporter();
exporter.setServiceInterface(serviceInterface);
exporter.setService(implementation);
exporter.setServiceName(serviceInterface.getSimpleName());
exporter.setRegistryPort(1099);
return exporter;
}通過 setServiceInterface(),我們提供了一個可以遠程調用的接口引用。
我們還應該提供一個引用實際執行方法的對象的引用,通過 setService()。 這樣,如果不想使用默認端口 1099,我們還可以提供服務器運行機器上 RMI 註冊表 的端口。
我們還應該設置一個服務名稱,以便在 RMI 註冊表中識別暴露的服務。
在給定的配置下,客户端將能夠通過以下 URL 聯繫 CabBookingService: rmi://HOST:1199/CabBookingService。
最後,讓我們啓動服務器。 由於 Spring 會自動為我們啓動 RMI 註冊表(如果未找到),因此我們不需要手動啓動它。
4. 客户端應用程序
現在我們來編寫客户端應用程序。
我們首先聲明 RmiProxyFactoryBean,它將創建一個 bean,該 bean 與服務器端運行的服務公開的接口相同,並且它將接收到的所有調用透明地路由到服務器。
@Bean
RmiProxyFactoryBean service() {
RmiProxyFactoryBean rmiProxyFactory = new RmiProxyFactoryBean();
rmiProxyFactory.setServiceUrl("rmi://localhost:1099/CabBookingService");
rmiProxyFactory.setServiceInterface(CabBookingService.class);
return rmiProxyFactory;
}讓我們編寫一段簡單的代碼,啓動客户端應用程序並使用之前步驟中定義的代理:
public static void main(String[] args) throws BookingException {
CabBookingService service = SpringApplication
.run(RmiClient.class, args).getBean(CabBookingService.class);
Booking bookingOutcome = service
.bookRide("13 Seagate Blvd, Key Largo, FL 33037");
System.out.println(bookingOutcome);
}現在只需啓動客户端以驗證它是否調用了服務器端提供的服務。
5. 結論
在本教程中,我們看到了如何使用 Spring Remoting 來簡化 RMI 的使用,否則 RMI 需要執行一系列繁瑣的任務,例如啓動註冊表並使用接口定義服務,這些接口大量使用 checked 異常。