此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Integration 6.5.1spring-doc.cadn.net.cn

脚本支持

Spring Integration 2.1 添加了对 Java 版本 6 中引入的 JSR223 Scripting for Java 规范的支持。 它允许您使用以任何受支持的语言(包括 Ruby、JRuby、Groovy 和 Kotlin)编写的脚本为各种集成组件提供逻辑,类似于在 Spring Integration 中使用 Spring 表达式语言 (SpEL) 的方式。 有关 JSR223 的更多信息,请参阅文档spring-doc.cadn.net.cn

您需要将此依赖项包含在您的项目中:spring-doc.cadn.net.cn

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-scripting</artifactId>
    <version>6.5.2-SNAPSHOT</version>
</dependency>
compile "org.springframework.integration:spring-integration-scripting:6.5.2-SNAPSHOT"

此外,您需要添加一个脚本引擎实现,例如 JRuby。spring-doc.cadn.net.cn

从 5.2 版开始,Spring Integration 提供了 Kotlin Jsr223 支持。 您需要将此依赖项添加到您的项目中以使其正常工作:spring-doc.cadn.net.cn

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-scripting-jsr223</artifactId>
    <scope>runtime</scope>
</dependency>
runtime 'org.jetbrains.kotlin:kotlin-scripting-jsr223'

为了使用 JVM 脚本语言,必须在类路径中包含该语言的 JSR223 实现。 GroovyJRuby 项目在其标准发行版中提供了 JSR233 支持。spring-doc.cadn.net.cn

第三方已经开发了各种 JSR223 语言实现。 特定实现与 Spring Integration 的兼容性取决于它符合规范的程度以及实现者对规范的解释。
如果您计划使用 Groovy 作为脚本语言,我们建议您使用 Spring-Integration 的 Groovy 支持,因为它提供了特定于 Groovy 的附加功能。 但是,本节也相关。

脚本配置

根据集成要求的复杂性,脚本可以在 XML 配置中作为 CDATA 内联提供,或者作为对包含该脚本的 Spring 资源的引用。 为了启用脚本支持,Spring Integration 定义了一个ScriptExecutingMessageProcessor,它将消息有效负载绑定到名为payload并将消息头设置为headers变量,两者都可以在脚本执行上下文中访问。 您需要做的就是编写一个使用这些变量的脚本。 以下一对示例显示了创建筛选器的示例配置:spring-doc.cadn.net.cn

@Bean
public IntegrationFlow scriptFilter() {
    return f -> f.filter(Scripts.processor("some/path/to/ruby/script/RubyFilterTests.rb"));
}
...
@Bean
public Resource scriptResource() {
	return new ByteArrayResource("headers.type == 'good'".getBytes());
}

@Bean
public IntegrationFlow scriptFilter() {
	return f -> f.filter(Scripts.processor(scriptResource()).lang("groovy"));
}
<int:filter input-channel="referencedScriptInput">
   <int-script:script location="some/path/to/ruby/script/RubyFilterTests.rb"/>
</int:filter>

<int:filter input-channel="inlineScriptInput">
     <int-script:script lang="groovy">
     <![CDATA[
     return payload == 'good'
   ]]>
  </int-script:script>
</int:filter>

如前面的示例所示,脚本可以内联包含在内,也可以通过引用资源位置来包含(通过使用location属性)。 此外,lang属性对应于语言名称(或其 JSR223 别名)。spring-doc.cadn.net.cn

其他支持脚本的 Spring Integration 端点元素包括router,service-activator,transformersplitter. 每种情况下的脚本配置都与上述相同(除了端点元素)。spring-doc.cadn.net.cn

脚本支持的另一个有用功能是能够更新(重新加载)脚本,而无需重新启动应用程序上下文。 为此,请指定refresh-check-delay属性script元素,如以下示例所示:spring-doc.cadn.net.cn

Scripts.processor(...).refreshCheckDelay(5000)
}
<int-script:script location="..." refresh-check-delay="5000"/>

在前面的示例中,每 5 秒检查一次脚本位置的更新。 如果更新了脚本,则在更新后 5 秒内发生的任何调用都会导致运行新脚本。spring-doc.cadn.net.cn

请考虑以下示例:spring-doc.cadn.net.cn

Scripts.processor(...).refreshCheckDelay(0)
}
<int-script:script location="..." refresh-check-delay="0"/>

在前面的示例中,一旦发生任何脚本修改,上下文就会使用任何脚本修改进行更新,从而为“实时”配置提供简单的机制。任何负值都表示在初始化应用程序上下文后不会重新加载脚本。这是默认行为。以下示例显示了从不更新的脚本:spring-doc.cadn.net.cn

Scripts.processor(...).refreshCheckDelay(-1)
}
<int-script:script location="..." refresh-check-delay="-1"/>
无法重新加载内联脚本。

脚本变量绑定

需要变量绑定才能使脚本引用外部提供给脚本执行上下文的变量。默认情况下,payloadheaders用作绑定变量。 您可以使用以下命令将其他变量绑定到脚本<variable>元素(或ScriptSpec.variables()选项),如以下示例所示:spring-doc.cadn.net.cn

Scripts.processor("foo/bar/MyScript.py")
    .variables(Map.of("var1", "thing1", "var2", "thing2", "date", date))
}
<script:script lang="py" location="foo/bar/MyScript.py">
    <script:variable name="var1" value="thing1"/>
    <script:variable name="var2" value="thing2"/>
    <script:variable name="date" ref="date"/>
</script:script>

如前面的示例所示,您可以将脚本变量绑定到标量值或 Spring bean 引用。 请注意payloadheaders仍作为绑定变量包含在内。spring-doc.cadn.net.cn

在 Spring Integration 3.0 中,除了variable元素,则variables属性。 此属性和variable元素并不相互排斥,您可以将它们组合到一个元素中script元件。 但是,变量必须是唯一的,无论它们在何处定义。 此外,从 Spring Integration 3.0 开始,内联脚本也允许变量绑定,如以下示例所示:spring-doc.cadn.net.cn

<service-activator input-channel="input">
    <script:script lang="ruby" variables="thing1=THING1, date-ref=dateBean">
        <script:variable name="thing2" ref="thing2Bean"/>
        <script:variable name="thing3" value="thing2"/>
        <![CDATA[
            payload.foo = thing1
            payload.date = date
            payload.bar = thing2
            payload.baz = thing3
            payload
        ]]>
    </script:script>
</service-activator>

前面的示例显示了内联脚本的组合,即variable元素和variables属性。 这variables属性包含一个逗号分隔的值,其中每个段包含变量及其值的“=”分隔对。 变量名称可以后缀-ref,如date-ref变量。 这意味着绑定变量的名称为date,但该值是对dateBeanbean 来自应用程序上下文。 这在使用属性占位符配置或命令行参数时可能很有用。spring-doc.cadn.net.cn

如果您需要更好地控制变量的生成方式,您可以实现自己的 Java 类,该类使用ScriptVariableGenerator策略,由以下接口定义:spring-doc.cadn.net.cn

public interface ScriptVariableGenerator {

    Map<String, Object> generateScriptVariables(Message<?> message);

}

此接口要求您实现generateScriptVariables(Message)方法。 message 参数允许您访问消息有效负载和标头中可用的任何数据,返回值为Map的绑定变量。 每次为消息执行脚本时都会调用此方法。 以下示例演示如何提供ScriptVariableGenerator并使用script-variable-generator属性:spring-doc.cadn.net.cn

Scripts.processor("foo/bar/MyScript.groovy")
    .variableGenerator(new foo.bar.MyScriptVariableGenerator())
}
<int-script:script location="foo/bar/MyScript.groovy"
        script-variable-generator="variableGenerator"/>

<bean id="variableGenerator" class="foo.bar.MyScriptVariableGenerator"/>

如果script-variable-generator,脚本组件使用DefaultScriptVariableGenerator,它合并了任何提供的<variable>元素与payloadheaders变量Message在其generateScriptVariables(Message)方法。spring-doc.cadn.net.cn

您不能同时提供script-variable-generator属性和<variable>元素。 它们是相互排斥的。

GraalVM 多语言

从 6.0 版开始,该框架提供了一个PolyglotScriptExecutor它基于 GraalVM Polyglot API。 JavaScript 的 JSR223 引擎实现本身从 Java 中删除,已被使用这个新的脚本执行器所取代。 请参阅有关在 GraalVM 中启用 JavaScript 支持以及可以通过脚本变量传播哪些配置选项的更多信息。 特别是,一个org.graalvm.polyglot:js必须将依赖项添加到目标项目中才能支持 JavaScript。spring-doc.cadn.net.cn

从版本 6.4 开始,Python 脚本支持也已迁移到 GraalVM Polyglot。 现在这些脚本可以用 Python 3.x 编写,并且可以使用第三方库。 有关更多信息,请参阅 GraalPy 文档。 特别是,一个rg.graalvm.polyglot:python必须将依赖项添加到目标项目中才能支持 Python。spring-doc.cadn.net.cn

默认情况下,框架将allowAllAccesstrue在共享的多语言上Context它启用了与主机 JVM 的交互:spring-doc.cadn.net.cn

这可以通过过载PolyglotScriptExecutor构造函数,该构造函数接受org.graalvm.polyglot.Context.Builder. 例如,基于 Jython 的脚本仍然可以使用option("python.EmulateJython", "true"). 但是,建议完全迁移到 GraalPy 以获得更好的解释性能。 因此importfor Java 类不再工作,而是import java必须使用,并且其java.type()功能。spring-doc.cadn.net.cn