Spring Integration SFTP (xml) Outbound Gateway – copy folderstructure from remote directory to local directory using SPEL Expression and java

huangapple go评论80阅读模式
英文:

Spring Integration SFTP (xml) Outbound Gateway - copy folderstructure from remote directory to local directory using SPEL Expression and java

问题

我是完全新手,对于Spring Integration和Spring都不太了解。能够将文件递归复制到本地文件夹已经是个奇迹,但我已经可以做到了,我是基于Spring的这个示例应用程序构建的:

https://github.com/spring-projects/spring-integration-samples/blob/main/basic/sftp/src/test/resources/META-INF/spring/integration/SftpOutboundGatewaySample-context.xml

现在我想保持与远程文件夹相同的子目录结构。

我使用的是Spring 4.1.9 Release版本,因为有遗留代码。以下是我的依赖项:

<dependencies>
    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-core</artifactId>
        <version>4.1.9.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-sftp</artifactId>
        <version>4.1.9.RELEASE</version>
    </dependency>
</dependencies>

这是一个包含main方法的简单App类,用于加载应用程序上下文:

@Component
public class App {

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
                "classpath:SftpOutboundGateway-context-test.xml");
        ToSftpFlowGateway toFtpFlow = ctx.getBean(ToSftpFlowGateway.class);

        toFtpFlow.lsGetAndRmFiles("/remote_directory/");
        
    }
}

这是接口,bean是在xml配置文件中创建的:

public interface ToSftpFlowGateway {
    List<Boolean> lsGetAndRmFiles(String dir);
}

这是xml spring配置文件。它引用了web.xml,在那里创建了sessionfactory。在这里,我使用了outbound-gateway:

<?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:int="http://www.springframework.org/schema/integration"
       xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
       xsi:schemaLocation="http://www.springframework.org/schema/integration
                           http://www.springframework.org/schema/integration/spring-integration-4.1.xsd
		                   http://www.springframework.org/schema/beans
		                   https://www.springframework.org/schema/beans/spring-beans.xsd
		                   http://www.springframework.org/schema/integration/sftp 
		                   https://www.springframework.org/schema/integration/sftp/spring-integration-sftp-4.1.xsd">

    <import resource="web.xml"/>
    
    <int:gateway id="gw" 
                 service-interface="ToSftpFlowGateway"
                 default-request-channel="receiveChannel"
    />
    
    <int-sftp:outbound-gateway id="gateway1" 
                              auto-startup="true"
                              session-factory="sftpSessionFactory"
                              request-channel="receiveChannel"
                              command="mget"
                              local-directory-expression="'C:/temp/' + headers['file_remoteDirectory']"
                              auto-create-local-directory="true"
                              rename-expression=""
                              command-options="-R" 
                              mode="IGNORE"
                              expression="payload"
                              reply-channel="loggingChannel" 
    >
        <int:poller fixed-rate="1"/>
    </int-sftp:outbound-gateway>
    
    <int:channel id="receiveChannel">
        <int:queue/>
    </int:channel>

    <int:logging-channel-adapter id="loggingChannel" log-full-message="true" logger-name="tapInbound"
                                 level="INFO" />
    
</beans>

我想知道为什么我的子目录为空。我希望我的子目录是C:/temp/in和C:/temp/out,就像下面的图片一样:

Spring Integration SFTP (xml) Outbound Gateway – copy folderstructure from remote directory to local directory using SPEL Expression and java

现在,我得到以下作为日志的输出:

INFO: GenericMessage [payload=[C:\temp\null\file.txt, C:\temp\null\file2.txt, C:\temp\null\file3.txt], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@534a53da, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@534a53da, id=f012840c-184e-203e-1a90-754beb8796d1, file_remoteDirectory=/remote_directory/, file_remoteFile=, timestamp=1684943419215}]

这里可能是有问题的地方:

local-directory-expression="'C:/temp/' + headers['file_remoteDirectory']"

Spring文档中提到以下内容,但我不太明白:

通常,您会在local-directory-expression中使用#remoteDirectory变量,以便保留本地目录结构。

英文:

I am totally new to Spring Integration and a beginner in Spring. It is a miracle that I got so far but I already can copy my files recursively into a local folder. I based my app on this sample application from Spring:

https://github.com/spring-projects/spring-integration-samples/blob/main/basic/sftp/src/test/resources/META-INF/spring/integration/SftpOutboundGatewaySample-context.xml

Now I want to keep the same subdirectories as in the remote folder.

I am using Spring 4.1.9 Release, because of legacy code. These are my dependencies.

&lt;dependencies&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.integration&lt;/groupId&gt;
        &lt;artifactId&gt;spring-integration-core&lt;/artifactId&gt;
        &lt;version&gt;4.1.9.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.integration&lt;/groupId&gt;
        &lt;artifactId&gt;spring-integration-sftp&lt;/artifactId&gt;
        &lt;version&gt;4.1.9.RELEASE&lt;/version&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;

This is a simple App class with main method which loads the applicationcontext.

@Component
public class App {

    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
                &quot;classpath:SftpOutboundGateway-context-test.xml&quot;);
        ToSftpFlowGateway toFtpFlow = ctx.getBean(ToSftpFlowGateway.class);

        toFtpFlow.lsGetAndRmFiles(&quot;/remote_directory/&quot;);
        
    }
}

This is the interface, and the bean is made in the xml config underneath

public interface ToSftpFlowGateway
{
    List&lt;Boolean&gt; lsGetAndRmFiles(String dir);
}

This is the xml spring config. It has a reference to web.xml where the sessionfactory is made. Here I use the outbound-gateway

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
       xmlns:int=&quot;http://www.springframework.org/schema/integration&quot;
       xmlns:int-sftp=&quot;http://www.springframework.org/schema/integration/sftp&quot;
       xsi:schemaLocation=&quot;http://www.springframework.org/schema/integration
                           http://www.springframework.org/schema/integration/spring-integration-4.1.xsd
		                   http://www.springframework.org/schema/beans
		                   https://www.springframework.org/schema/beans/spring-beans.xsd
		                   http://www.springframework.org/schema/integration/sftp 
		                   https://www.springframework.org/schema/integration/sftp/spring-integration-sftp-4.1.xsd">

    &lt;import resource=&quot;web.xml&quot;/&gt;
    

    &lt;int:gateway id=&quot;gw&quot; 
                 service-interface=&quot;ToSftpFlowGateway&quot;
                 default-request-channel=&quot;receiveChannel&quot;
    /&gt;

    &lt;int-sftp:outbound-gateway id=&quot;gateway1&quot; 
                              auto-startup=&quot;true&quot;
                              session-factory=&quot;sftpSessionFactory&quot;
                              request-channel=&quot;receiveChannel&quot;
                              command=&quot;mget&quot;
                              local-directory-expression=&quot;&#39;C:/temp/&#39; + headers[&#39;file_remoteDirectory&#39;]&quot;
                              auto-create-local-directory=&quot;true&quot;
                              rename-expression=&quot;&quot; 
                              command-options=&quot;-R&quot; 
                              mode=&quot;IGNORE&quot;
                              expression=&quot;payload&quot;
                              reply-channel=&quot;loggingChannel&quot; 
    &gt;
        &lt;int:poller fixed-rate=&quot;1&quot;/&gt;
    &lt;/int-sftp:outbound-gateway&gt;
    
    &lt;int:channel id=&quot;receiveChannel&quot;&gt;
        &lt;int:queue/&gt;
    &lt;/int:channel&gt;

    &lt;int:logging-channel-adapter id=&quot;loggingChannel&quot; log-full-message=&quot;true&quot; logger-name=&quot;tapInbound&quot;
                                 level=&quot;INFO&quot; /&gt;
    
&lt;/beans&gt;

I want to know why my subdirectories are null. I want my subdirectories to be C:/temp/in and C:/temp/out as the following picture.

Spring Integration SFTP (xml) Outbound Gateway – copy folderstructure from remote directory to local directory using SPEL Expression and java

Now i get the following output as logging:

INFO: GenericMessage [payload=[C:\temp\null\file.txt, C:\temp\null\file2.txt, C:\temp\null\file3.txt], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@534a53da, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@534a53da, id=f012840c-184e-203e-1a90-754beb8796d1, file_remoteDirectory=/remote_directory/, file_remoteFile=, timestamp=1684943419215}]

This is probably wrong

local-directory-expression=&quot;&#39;C:/temp/&#39; + headers[&#39;file_remoteDirectory&#39;]&quot;

Spring documentation says the following, but I don't understand:

> Typically, you would use the #remoteDirectory variable in the
> local-directory-expression so that the remote directory structure is
> retained locally.

答案1

得分: 1

The headers['file_remoteDirectory'] 表达式引用了请求消息,该消息显然没有该信息,因为它只是一个简单的消息:

toFtpFlow.lsGetAndRmFiles("/remote_directory/");

尝试将你的 local-directory-expression 修改为:

local-directory-expression="'C:/temp/' + #remoteDirectory"

其中 remoteDirectory SpEL 变量被填充为每个检索到的文件的远程子目录的路径:

private File generateLocalDirectory(Message<?> message, String remoteDirectory) {
    EvaluationContext evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
    if (remoteDirectory != null) {
        evaluationContext.setVariable("remoteDirectory", remoteDirectory);
    }
    File localDir = ExpressionUtils.expressionToFile(this.localDirectoryExpression, evaluationContext, message, "Local Directory");
    if (!localDir.exists()) {
        Assert.isTrue(localDir.mkdirs(), () -> "Failed to make local directory: " + localDir);
    }
    return localDir;
}
英文:

The headers[&#39;file_remoteDirectory&#39;] expression references to the request message which is definitely doesn't have that info because it is a plain message:

toFtpFlow.lsGetAndRmFiles(&quot;/remote_directory/&quot;);

Try to modify your local-directory-expression to this:

local-directory-expression=&quot;&#39;C:/temp/&#39; + #remoteDirectory&quot;

Where that remoteDirectory SpEL variable is populated for the path of the remote sub-dir against every file retrieved:

private File generateLocalDirectory(Message&lt;?&gt; message, String remoteDirectory) {
	EvaluationContext evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
	if (remoteDirectory != null) {
		evaluationContext.setVariable(&quot;remoteDirectory&quot;, remoteDirectory);
	}
	File localDir = ExpressionUtils.expressionToFile(this.localDirectoryExpression, evaluationContext, message,
			&quot;Local Directory&quot;);
	if (!localDir.exists()) {
		Assert.isTrue(localDir.mkdirs(), () -&gt; &quot;Failed to make local directory: &quot; + localDir);
	}
	return localDir;
}

huangapple
  • 本文由 发表于 2023年5月25日 00:04:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76325467.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定