Spring Integration中SftpOutboundGateway执行GET时抛SpelEvaluationException
问题根因
- 核心错误出在
localFilenameExpression、remoteDirectoryExpression两个方法的使用上:这两个方法的入参要求是SpEL表达式字符串,而非直接的配置值字符串。Spring会把你传入的目录、文件名字面值当成表达式执行,默认执行上下文的根对象是当前消息,因此会抛出GenericMessage无法转换为String的类型转换异常。 - 次要问题:SFTP Outbound Gateway执行GET命令后返回的payload是
java.io.File类型,你直接调用fromJson转换器会解析失败,需要先把文件内容读取为字符串再做JSON转换。
修正方案
方案1:使用固定值配置(不需要动态从消息取参数)
直接使用非Expression后缀的方法传入固定配置值即可,修正后的IntegrationFlow配置如下:
@Bean public IntegrationFlow sftpGetFlow(TransferContext context) { return IntegrationFlows.from("sftpGetInputChannel") .handle(Sftp.outboundGateway(sftpSessionFactory(context.getChannel()), AbstractRemoteFileOutboundGateway.Command.GET, "payload") // 用remoteDirectory传固定目录,不要用Expression版本 .remoteDirectory(context.getRemoteDir()) .localDirectory(new File(context.getLocalDir())) // 用localFilename传固定文件名,不要用Expression版本 .localFilename(context.getLocalFilename()) ) // 先读取文件内容为字符串 .transform(Files.toStringTransformer()) // 再转换为Event数组 .transform(Transformers.fromJson(Event[].class)) .channel("remoteFileOutputChannel") .get(); }
方案2:需要动态从消息获取参数的场景
如果你需要根据请求消息的内容动态指定目录、文件名,就编写正确的SpEL表达式传入Expression后缀的方法即可,示例如下:
// 从消息头获取远程目录 .remoteDirectoryExpression("headers.remoteDir") // 从消息payload获取本地文件名 .localFilenameExpression("payload.localFileName")
内容的提问来源于stack exchange,提问作者JBStonehenge
相关产品推荐
相关产品推荐

