# RMI 支助

## RMI 支持

|   |这个模块从 5.4 开始就不推荐了，不需要替换，将在 6.0 中删除。|
|---|-----------------------------------------------------------------------------------|

本章将解释如何使用特定于 RMI（远程方法调用）的通道适配器在多个 JVM 上分发系统。第一部分涉及通过 RMI 发送消息。第二部分展示了如何通过 RMI 接收消息。最后一节展示了如何通过使用名称空间支持来定义 RMI 通道适配器。

你需要在项目中包含此依赖项：

Maven

```
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-rmi</artifactId>
    <version>5.5.9</version>
</dependency>
```

Gradle

```
compile "org.springframework.integration:spring-integration-rmi:5.5.9"
```

### 出站 RMI

要通过 RMI 从信道发送消息，可以定义`RmiOutboundGateway`。该网关在内部使用 Spring 的`RmiProxyFactoryBean`为远程网关创建代理。请注意，要调用不使用 Spring 集成的远程接口，你应该结合 Spring 的 RmiproxyFactoryBean 使用一个服务激活器。

要配置出站网关，你可以编写一个类似于以下内容的 Bean 定义：

```
<bean id="rmiOutGateway" class=org.spf.integration.rmi.RmiOutboundGateway>
    <constructor-arg value="rmi://host"/>
    <property name="replyChannel" value="replies"/>
</bean>
```

### 入站 RMI

要通过 RMI 接收消息，你需要使用`RmiInboundGateway`。你可以按照下面的示例配置网关：

```
<bean id="rmiInGateway" class=org.spf.integration.rmi.RmiInboundGateway>
    <property name="requestChannel" value="requests"/>
</bean>
```

|   |如果在入站网关上使用`errorChannel`，它的错误流通常返回一个结果或抛出一个异常。<br/>这是因为它很可能有一个相应的出站网关在等待某种响应。<br/>在错误流上消耗消息并且不回复将导致入站网关没有回复。<br/>异常（在主流上没有`errorChannel`时或在错误流上）传播到相应的入站网关。|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|

### RMI 名称空间支持

要配置入站网关，你可以使用对它的名称空间支持。以下代码片段显示了所支持的不同配置选项：

```
<int-rmi:inbound-gateway id="gatewayWithDefaults" request-channel="testChannel"/>

<int-rmi:inbound-gateway id="gatewayWithCustomProperties" request-channel="testChannel"
    expect-reply="false" request-timeout="123" reply-timeout="456"/>

<int-rmi:inbound-gateway id="gatewayWithHost" request-channel="testChannel"
    registry-host="localhost"/>

<int-rmi:inbound-gateway id="gatewayWithPort" request-channel="testChannel"
    registry-port="1234" error-channel="rmiErrorChannel"/>

<int-rmi:inbound-gateway id="gatewayWithExecutorRef" request-channel="testChannel"
    remote-invocation-executor="invocationExecutor"/>
```

你还可以使用名称空间支持来配置出站网关。以下代码片段显示了出站 RMI 网关的不同配置：

```
<int-rmi:outbound-gateway id="gateway"
    request-channel="localChannel"
    remote-channel="testChannel"
    host="localhost"/>
```

### 使用 Java 配置进行配置

下面的示例展示了如何使用 Java 配置入站网关和出站网关：

```
@Bean
public RmiInboundGateway inbound() {
    RmiInboundGateway gateway = new RmiInboundGateway();
    gateway.setRequestChannel(requestChannel());
    gateway.setRegistryHost("host");
    gateway.setRegistryPort(port);
    return gateway;
}

@Bean
@ServiceActivator(inputChannel="inChannel")
public RmiOutboundGateway outbound() {
    RmiOutboundGateway gateway = new RmiOutboundGateway("rmi://host:port/"
        + RmiInboundGateway.SERVICE_NAME_PREFIX + "remoteChannelName");
    return gateway;
}
```

从版本 4.3 开始，出站网关有第二个构造函数，它接受`RmiProxyFactoryBeanConfigurer`实例以及服务 URL 参数。它允许在创建代理之前进行进一步的配置——例如，注入 Spring 安全性`ContextPropagatingRemoteInvocationFactory`，如下例所示：

```
@Bean
@ServiceActivator(inputChannel="inChannel")
public RmiOutboundGateway outbound() {
    RmiOutboundGateway gateway = new RmiOutboundGateway("rmi://host:port/"
                + RmiInboundGateway.SERVICE_NAME_PREFIX + "remoteChannelName",
        pfb -> {
            pfb.setRemoteInvocationFactory(new ContextPropagatingRemoteInvocationFactory());
        });
    return gateway;
}
```

从版本 5.0 开始，你可以使用`configurer`属性在 XML 命名空间中设置此项。