高级技术
本节涵盖了在某些情况下你可能会发现有帮助的高级技术。
策略接口
在许多情况下,前面描述的配置已经足以启用 TCP/IP 上的安全通信。然而,Spring Integration 提供了许多策略接口,以允许自定义和修改套接字工厂和套接字:
- 
TcpSSLContextSupport
- 
TcpSocketFactorySupport
- 
TcpSocketSupport
- 
TcpNetConnectionSupport
- 
TcpNioConnectionSupport
TcpSSLContextSupport 策略接口
以下列表显示了 TcpSSLContextSupport 策略接口:
public interface TcpSSLContextSupport {
    SSLContext getSSLContext() throws Exception;
}
TcpSSLContextSupport 接口的实现负责创建一个 SSLContext 对象。框架提供的实现是 DefaultTcpSSLContextSupport,之前已经描述过。如果你需要不同的行为,请实现此接口,并为连接工厂提供一个指向你类实现的bean的引用。
TcpSocketFactorySupport 策略接口
在上述标题中,TcpSocketFactorySupport 是一个专有名词,因此保留了英文原样,同时按照要求在英文和中文之间加了一个空格。
以下列表显示了 TcpSocketFactorySupport 策略接口的定义:
public interface TcpSocketFactorySupport {
    ServerSocketFactory getServerSocketFactory();
    SocketFactory getSocketFactory();
}
此接口的实现负责获取 ServerSocketFactory 和 SocketFactory 的引用。提供了两种实现。第一种是用于非 SSL 套接字的 DefaultTcpNetSocketFactorySupport(当未定义 ssl-context-support 属性时)。这使用 JDK 的默认工厂。第二种实现是 DefaultTcpNetSSLSocketFactorySupport。默认情况下,当定义了 ssl-context-support 属性时使用它。它使用由该 bean 创建的 SSLContext 来创建套接字工厂。
此接口仅在 using-nio 为 false 时适用。NIO 不使用套接字工厂。
TcpSocketSupport 策略接口
以下列表显示了 TcpSocketSupport 策略接口的定义:
public interface TcpSocketSupport {
    void postProcessServerSocket(ServerSocket serverSocket);
    void postProcessSocket(Socket socket);
}
此接口的实现可以在套接字创建后以及所有配置的属性应用后但在套接字被使用之前修改套接字。这无论你是否使用 NIO 都适用。例如,你可以使用此接口的一个实现来修改 SSL 套接字上支持的密码套件,或者你可以添加一个监听器,在 SSL 握手完成之后收到通知。框架提供的唯一实现是 DefaultTcpSocketSupport,它不会以任何方式修改套接字。
要提供您自己的 TcpSocketFactorySupport 或 TcpSocketSupport 实现,请通过设置 socket-factory-support 和 socket-support 属性,分别为连接工厂提供对自定义类型 bean 的引用。
TcpNetConnectionSupport 策略接口
以下列表显示了 TcpNetConnectionSupport 策略接口的定义:
public interface TcpNetConnectionSupport {
    TcpNetConnection createNewConnection(Socket socket,
            boolean server, boolean lookupHost,
            ApplicationEventPublisher applicationEventPublisher,
            String connectionFactoryName) throws Exception;
}
此接口用于创建类型为 TcpNetConnection(或其子类)的对象。框架提供了一个实现 (DefaultTcpNetConnectionSupport),默认情况下,它会创建简单的 TcpNetConnection 对象。它有两个属性:pushbackCapable 和 pushbackBufferSize。当启用了回退功能时,该实现会返回一个子类,该子类将连接的 InputStream 包装在 PushbackInputStream 中。与 PushbackInputStream 的默认行为一致,默认缓冲区大小为 1。这允许反序列化器将字节“unread”(回退)到流中。以下是一个简单的示例,展示了如何在一个委托反序列化器中使用它来“窥视”第一个字节以确定调用哪个反序列化器:
public class CompositeDeserializer implements Deserializer<byte[]> {
    private final ByteArrayStxEtxSerializer stxEtx = new ByteArrayStxEtxSerializer();
    private final ByteArrayCrLfSerializer crlf = new ByteArrayCrLfSerializer();
    @Override
    public byte[] deserialize(InputStream inputStream) throws IOException {
        PushbackInputStream pbis = (PushbackInputStream) inputStream;
        int first = pbis.read();
        if (first < 0) {
            throw new SoftEndOfStreamException();
        }
        pbis.unread(first);
        if (first == ByteArrayStxEtxSerializer.STX) {
            this.receivedStxEtx = true;
            return this.stxEtx.deserialize(pbis);
        }
        else {
            this.receivedCrLf = true;
            return this.crlf.deserialize(pbis);
        }
    }
}
TcpNioConnectionSupport 策略接口
以下列表显示了 TcpNioConnectionSupport 策略接口的定义:
public interface TcpNioConnectionSupport {
    TcpNioConnection createNewConnection(SocketChannel socketChannel,
            boolean server, boolean lookupHost,
            ApplicationEventPublisher applicationEventPublisher,
            String connectionFactoryName) throws Exception;
}
此接口用于创建 TcpNioConnection 对象(或来自子类的对象)。Spring Integration 提供了两种实现:DefaultTcpNioSSLConnectionSupport 和 DefaultTcpNioConnectionSupport。使用哪一个取决于是否使用 SSL。一个常见的用例是继承 DefaultTcpNioSSLConnectionSupport 并重写 postProcessSSLEngine。请参阅 SSL 客户端身份验证示例。与 DefaultTcpNetConnectionSupport 一样,这些实现也支持回退。
示例:启用 SSL 客户端认证
要启用使用 SSL 时的客户端证书身份验证,技术取决于你是否使用 NIO。当你不使用 NIO 时,提供一个自定义的 TcpSocketSupport 实现来后处理服务器套接字:
serverFactory.setTcpSocketSupport(new DefaultTcpSocketSupport() {
    @Override
    public void postProcessServerSocket(ServerSocket serverSocket) {
        ((SSLServerSocket) serverSocket).setNeedClientAuth(true);
    }
});
(在使用 XML 配置时,通过设置 socket-support 属性来提供对 bean 的引用)。
当你使用 NIO 时,提供一个自定义的 TcpNioSslConnectionSupport 实现来后处理 SSLEngine,如下例所示:
@Bean
public DefaultTcpNioSSLConnectionSupport tcpNioConnectionSupport() {
    return new DefaultTcpNioSSLConnectionSupport(serverSslContextSupport) {
            @Override
            protected void postProcessSSLEngine(SSLEngine sslEngine) {
                sslEngine.setNeedClientAuth(true);
            }
    }
}
@Bean
public TcpNioServerConnectionFactory server() {
    ...
    serverFactory.setTcpNioConnectionSupport(tcpNioConnectionSupport());
    ...
}
(当您使用 XML 配置时,从 4.3.7 版本开始,通过设置 nio-connection-support 属性来提供对 bean 的引用)。