Spring SFTP出站网关:如何在Java Config中关闭GET后的会话?

时间:2017-03-27 15:29:25

标签: java spring spring-integration spring-integration-sftp

我编写了一段使用Spring SFTP出站网关并执行GET操作的代码。整个配置是在JAVA(没有XML)。 我已经建立了一个缓存会话工厂,最多允许10个会话。由于多次GET请求超过10后,GET请求开始失败。

我阅读了文档,它是为了在操作后关闭会话而编写的,但我无法弄清楚如何在JAVA配置中关闭此会话?

@org.springframework.integration.annotation.MessagingGateway
public interface FileOperationGateway {
    @Gateway(requestChannel = "sftpChannelDownload")
    InputStream downloadFromSftp(Message<Boolean> message);

}



@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
    DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
    factory.setHost(SFTP_HOST);
    factory.setPort(SFTP_PORT);
    factory.setUser(SFTP_USERNAME);
    factory.setPassword(SFTP_PASSWORD);
    factory.setAllowUnknownKeys(true);
    return new CachingSessionFactory<LsEntry>(factory);
}

/**
 * Bean for Caching the session 
 * 
 */

@Bean
@Autowired
public CachingSessionFactory<LsEntry> cachingSessionFactory(SessionFactory<LsEntry> sftpSessionFactory) {
    CachingSessionFactory<LsEntry> cachingSessionFactory = new CachingSessionFactory<>(sftpSessionFactory, 10);
    cachingSessionFactory.setSessionWaitTimeout(SFTP_SESSION_TIMEOUT);
    return cachingSessionFactory;
}

/**
 * Bean for Remote File Template 
 * 
 * @return
 * @throws Exception 
 */

@Bean
@Autowired
public RemoteFileTemplate<LsEntry> remoteFileTemplateDesigner(CachingSessionFactory<LsEntry> csf) throws Exception {
    ExpressionParser expressionParser = new SpelExpressionParser();
    Expression expression = expressionParser.parseExpression("'" + SFTP_LOCATION + "'");
    SftpRemoteFileTemplate rft = new SftpRemoteFileTemplate(csf);
    rft.setRemoteDirectoryExpression(expression);
    rft.setRemoteFileSeparator("/");
    rft.setFileNameGenerator((msg) -> {
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        Instant instant = timestamp.toInstant();
        String fileNameFromHeader = msg.getHeaders().get(FileOperationConstants.FILE_HEADER_KEY).toString();
        String newFileName;
        if (fileNameFromHeader.lastIndexOf("/") != -1) {
            newFileName = fileNameFromHeader.substring(fileNameFromHeader.lastIndexOf("/"));
        } else if (fileNameFromHeader.lastIndexOf("\\") != -1) {
            newFileName = fileNameFromHeader.substring(fileNameFromHeader.lastIndexOf("\\"));
        } else
            newFileName = fileNameFromHeader;

        String fileNameOnly = newFileName.substring(0, newFileName.lastIndexOf("."));
        String fileType = newFileName.substring(newFileName.lastIndexOf(".") + 1);
        return (fileNameOnly + "__" + instant.toString() + "." + fileType);
    });
    rft.afterPropertiesSet();
    return rft;
}

@Bean
@Autowired
@ServiceActivator(inputChannel = "sftpChannelDownload")
public SftpOutboundGatewaySpec downloadHandler(RemoteFileTemplate<LsEntry> rft) {
    SftpOutboundGatewaySpec sogs =  Sftp.outboundGateway(rft, FileOperationConstants.FILE_DOWNLOAD_COMMAND,
            FileOperationConstants.FILE_DOWNLOAD_EXPRESSION);
    sogs.options(Option.STREAM);
    return sogs;
}
  

****** UPDATE:******

我使用@messageEndpoint创建了一个新类,并在其中放置了可关闭的会话代码。然后我从我的服务类(我正在使用流)中调用此处理程序。这工作:

    @MessageEndpoint
public class FileOperationCloseSessionMessageHandler {

    @ServiceActivator(inputChannel = "sftpCloseSession")
    public void closeSession(Message<Boolean> msg) throws IOException {

        Closeable closeable = new IntegrationMessageHeaderAccessor(msg).getCloseableResource();
        if (closeable != null) {
            closeable.close();
        }
    }
}

将此行放在@MessagingGateway注释类

@Gateway(requestChannel = "sftpCloseSession")
void closeSession(Message<InputStream> msg);

然后从服务类调用网关方法:

Message<InputStream> msg = msgGateway.downloadFromSftp(message);
    InputStream is = msg.getPayload();
    msgGateway.closeSession(msg);

1 个答案:

答案 0 :(得分:0)

  

sogs.options(Option.STREAM);

当您流式传输文件时,您负责在完成流式传输后关闭会话。这在the documentation中解释。

  

当将远程文件作为流使用时,用户负责在使用流之后关闭会话。为方便起见,Session在IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE标头中提供,IntegrationMessageHeaderAccessor上提供了一种便捷方法:

Closeable closeable = new IntegrationMessageHeaderAccessor(message).getCloseableResource();
if (closeable != null) {
    closeable.close();
}
  

File Splitter和Stream Transformer等框架组件将在传输数据后自动关闭会话。