使用ftp的Spring Boot应用程序

时间:2017-06-16 11:40:04

标签: spring spring-boot spring-integration

我需要帮助,我使用spring-integration-ftp测试了Spring Boot应用程序,如果我在主类SpringBootFtpApplication中使用它,它可以工作 它运行并将文件从远程服务器复制到我的本地,但它会自动运行。

@SpringBootApplication
public class SpringBootFtpApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootFtpApplication.class, args);
    }

     @Bean
        public SessionFactory<FTPFile> ftpSessionFactory() {
            DefaultFtpSessionFactory sf = new DefaultFtpSessionFactory();
            sf.setHost("123.ftpserver.com");
            sf.setPort(21);
            sf.setUsername("demo");
            sf.setPassword("xxxxx");
            return new CachingSessionFactory<FTPFile>(sf);
        }

    @Bean
    public FtpInboundFileSynchronizer ftpInboundFileSynchronizer() {
        FtpInboundFileSynchronizer fileSynchronizer = new FtpInboundFileSynchronizer(ftpSessionFactory());
        fileSynchronizer.setDeleteRemoteFiles(false);
        fileSynchronizer.setRemoteDirectory("upload");
        fileSynchronizer.setFilter(new FtpSimplePatternFileListFilter("*.txt"));
        return fileSynchronizer;
    }
    @Bean(name = PollerMetadata.DEFAULT_POLLER)
    public PollerMetadata defaultPoller() {

        PollerMetadata pollerMetadata = new PollerMetadata();
        pollerMetadata.setTrigger(new PeriodicTrigger(10));
        return pollerMetadata;
    }

    @Bean
    @InboundChannelAdapter(channel = "ftpChannel")
    public MessageSource<File> ftpMessageSource() {
        FtpInboundFileSynchronizingMessageSource source =
                new FtpInboundFileSynchronizingMessageSource(ftpInboundFileSynchronizer());
        source.setLocalDirectory(new File("ftp-inbound"));
        source.setAutoCreateLocalDirectory(true);
        source.setLocalFilter(new AcceptOnceFileListFilter<File>());
        return source;
    }


    @Bean
     @ServiceActivator(inputChannel = "ftpChannel")
     public MessageHandler handler() {
         return new MessageHandler() {


             @Override
             public void handleMessage(Message<?> message) throws MessagingException {
                 Object payload = message.getPayload();
                 if(payload instanceof File){
                     File f = (File) payload;
                     System.out.println(f.getName());
                 }else{
                     System.out.println(message.getPayload());
                 }
             }

         };
     }
}

如何将此代码复制到另一个类,然后从另一个控制器类手动启动,例如

public class ImportFromFtpServer(){
 /*
@Bean 
public SessionFactory<FTPFile> ftpSessionFactory() ...
@Bean
public FtpInboundFileSynchronizer ftpInboundFileSynchronizer() ...
@Bean
@InboundChannelAdapter(channel = "ftpChannel")
public MessageSource<File> ftpMessageSource() ...
@Bean
@ServiceActivator(inputChannel = "ftpChannel")
public MessageHandler handler()...
*/
}

    @Controller
public class MyController(){
   public class startFtpTransfer(){
       ImportFromFtpServer() imp = new ImportFromFtpServer();
      //how to call metod for ftp transfer ? 
 }
}

我尝试将所有代码放在一个类中并放入@Configuration注释,但是这个执行会自动运行,我对执行没有任何控制权,但我想控制何时需要启动此转移

任何提示或帮助都将受到赞赏。 TNX

3 个答案:

答案 0 :(得分:0)

如果您只想按需获取文件,请考虑使用出站网关(get命令)(或直接使用FtpRemoteFileTemplate)。

为单个文件创建轮询流并不合适。

答案 1 :(得分:0)

@InboundChannelAdapter有:

/*
 {@code SmartLifecycle} options.
 Can be specified as 'property placeholder', e.g. {@code ${foo.autoStartup}}.
 */
String autoStartup() default "true";

您可以将其配置为false。最近当你确实需要这项工作时,你应start(),因为SourcePollingChannelAdapterLifecycle实施。

你需要的是注入那个bean:

@Autowired
@Qualifier("springBootFtpApplication.ftpMessageSource.inboundChannelAdapter")
Lifecycle ftpChannelAdapter;

<强>更新

由于SourcePollingChannelAdapter用于@InboundChannelAdapter注释稍后创建,因此@Autowired阶段不可行。您的应用程序需要的是手动执行依赖注入。像这样:

@Autowired
private BeanFactory beanFactory;

@GetMapping("/startFtpPolling")
public void startFtpSource() {
    this.beanFactory.getBean("demoApplication.ftpMessageSource.inboundChannelAdapter", Lifecycle.class).start();
}

答案 2 :(得分:0)

@ artem-bilan tnx快速回复 我实现了部分解决方案并按照您对autoStartup和此工作的建议放置了这部分代码

@InboundChannelAdapter(channel = "ftpChannel",autoStartup = "false")
public MessageSource<File> ftpMessageSource() {...}

此代码停止自动执行FTP传输。 但是在我按照此代码实现解决方案的第二部分之后

public class FtpLifecycle implements Lifecycle{

@Autowired
@Qualifier("springBootBatchTestApplication.ftpMessageSource.inboundChannelAdapter")
 Lifecycle ftpChannelAdapter;

@Override
public boolean isRunning() {
    // TODO Auto-generated method stub
    return false;
}

@Override
public void start() {
    System.out.println("Started...");
    ftpChannelAdapter.start();

}

@Override
public void stop() {
    // TODO Auto-generated method stub

}
}

然后调用此方法

ftpChannelAdapter.start();

在我的控制器类中我收到了错误

java.lang.NullPointerException: null
at com.company.ftp.FtpLifecycle.start(FtpLifecycle.java:22) ~[classes/:na]

我觉得@Qualifier一定有问题,也许他根本找不到inboundChannelAdapter?有任何建议如何解决这个问题?

编辑23.6

public class FtpLifecycle implements Lifecycle{

private static final Logger LOGGER = LoggerFactory.getLogger(FtpLifecycle.class);

@Autowired
    @Qualifier("SpringBootBatchTestApplication.ftpMessageSource.inboundChannelAdapter")
    Lifecycle ftpChannelAdapter;


@Autowired
private ApplicationContext appContext;

@Override
public boolean isRunning() {
    // TODO Auto-generated method stub
    return false;
}

@Override
public void start() {
    System.out.println("Started...");
    SourcePollingChannelAdapter sp = findTestCaseBean(appContext);
    ftpChannelAdapter.start();


}

@Override
public void stop() {
    // TODO Auto-generated method stub

}
public static SourcePollingChannelAdapter findTestCaseBean(ApplicationContext appCtx) throws NoSuchBeanDefinitionException {


    Map<String, SourcePollingChannelAdapter> testcases = (Map<String, SourcePollingChannelAdapter>) appCtx.getBeansOfType(SourcePollingChannelAdapter.class);
    if (testcases.isEmpty()) {
        LOGGER.warn("No classes!");
        throw new NoSuchBeanDefinitionException(SourcePollingChannelAdapter.class);
    } else {
        LOGGER.warn("There is classes!");
        SourcePollingChannelAdapter retVal = testcases.values().iterator().next();
        if (null == retVal) {
            throw new NoSuchBeanDefinitionException(SourcePollingChannelAdapter.class);
        } else {
            return retVal;
        }
    }
}