【问题标题】:Dynamically provide directory and file name to ftp outbound gateway动态提供目录和文件名给 ftp 出站网关
【发布时间】:2015-07-08 14:33:54
【问题描述】:

我们要求 FTP 客户端下载一个文件,该文件的名称和目录在运行时提供。因此,可能会要求 FTP 客户端从远程服务器上的 foo1/foo2 目录路径下载 file1.txt。

我们确实有一个使用 Spring Integration FTP 出站网关的解决方案。使用此解决方案使其动态化:

  1. 网关的 ApplicationContext 已创建
  2. 使用文件名和远程目录路径设置网关属性
  3. 文件已下载
  4. ApplicationContext 已关闭。

我们不满意的是每次都会创建和关闭 ApplicationContext,这显然会影响性能。有没有办法动态地将文件名和目录路径传递给网关,而无需每次都重新加载Appplication Context?

我们将不胜感激。

主要代码和配置如下:

package com.cvc.ipcdservice.ftp;

import java.util.List;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.StandardEnvironment;

public class DynamicFtpClient {
    private static final Logger LOGGER = LoggerFactory
            .getLogger(DynamicFtpClient.class);

    public void download(final FtpMetaData ftpMetaData) {
        final ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
                new String[] { "/META-INF/spring/integration/FtpOutboundGateway-context.xml" },
                false);

        setEnvironment(ctx, ftpMetaData);
        ctx.refresh();

        final ToFtpFlowGateway toFtpFlow = ctx.getBean(ToFtpFlowGateway.class);

        // execute the flow (mget to download from FTP server)
        final List<Boolean> downloadResults = toFtpFlow.mGetFiles("/");

        LOGGER.info(
                "Completed downloading from remote FTP server. ftpMetaData:{}, downloadResults.size:{} ",
                ftpMetaData, downloadResults.size());

        ctx.close();
    }

    /**
     * Populate {@code ConfigurableApplicationContext} with Provider-specific
     * FTP properties.
     *
     * @param ctx
     * @param customer
     */
    private void setEnvironment(final ConfigurableApplicationContext ctx,
            final FtpMetaData ftpMetaData) {
        final StandardEnvironment env = new StandardEnvironment();
        final Properties props = new Properties();
        // populate properties for customer
        props.setProperty("ftp.host", ftpMetaData.getHost());
        props.setProperty("ftp.port", ftpMetaData.getPort());
        props.setProperty("ftp.userid", ftpMetaData.getUserName());
        props.setProperty("ftp.password", ftpMetaData.getPassword());
        // props.setProperty("remote.directory", "/");
        // WARNING: the file name pattern has to be surrounded by single-quotes
        props.setProperty("ftp.remote.filename.pattern",
                "'" + ftpMetaData.getFileNamePattern() + "'");
        props.setProperty("ftp.local.dir", ftpMetaData.getLocalDirectory());

        final PropertiesPropertySource pps = new PropertiesPropertySource(
                "ftpprops", props);
        env.getPropertySources().addLast(pps);
        ctx.setEnvironment(env);
    }
}



 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:int="http://www.springframework.org/schema/integration"
    xmlns:int-ftp="http://www.springframework.org/schema/integration/ftp"
    xsi:schemaLocation="http://www.springframework.org/schema/integration/ftp http://www.springframework.org/schema/integration/ftp/spring-integration-ftp.xsd
        http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:property-placeholder/>

    <int:gateway id="gw" service-interface="com.cvc.ipcdservice.ftp.ToFtpFlowGateway"
        default-request-channel="inbound"/>

    <bean id="ftpSessionFactory"
        class="org.springframework.integration.ftp.session.DefaultFtpSessionFactory">
        <property name="host" value="${ftp.host}"/>
        <property name="port" value="${ftp.port}"/>
        <property name="username" value="${ftp.userid}"/>
        <property name="password" value="${ftp.password}"/>
    </bean>

    <int-ftp:outbound-gateway id="gatewayGET"
        local-directory="${ftp.local.dir}"
        session-factory="ftpSessionFactory"
        request-channel="inbound"       
        command="mget"
        command-options="-P"
        expression="${ftp.remote.filename.pattern}"/>

</beans>

【问题讨论】:

    标签: spring spring-integration


    【解决方案1】:

    无需为每个请求创建上下文。

    而不是使用文字来表达:

    props.setProperty("ftp.remote.filename.pattern",
                "'" + ftpMetaData.getFileNamePattern() + "'");
    

    根据请求使用表达式;例如

    props.setProperty("ftp.remote.filename.pattern",
                "payload");
    

    然后只需在网关调用中发送所需的路径...

    final List<Boolean> downloadResults = toFtpFlow.mGetFiles("/some/path/*.txt");
    

    【讨论】:

    • 谢谢加里,它成功了!如果这没问题,请在这篇文章中对同一代码再多问几个问题:(1)我们如何设置 FTP 连接(或网关)的超时? (2)如何设置重试?建议使用 和 RequestHandlerRetryAdvice。只是还没有找到好的例子。
    • 可以在连接工厂上设置超时属性;见the javadocsretry-and-more sample 提供了如何在任何端点上配置重试的示例。
    • 非常感谢加里。会调查的。
    猜你喜欢
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多