|
对于最新稳定版本,请使用 Spring Integration 7.0.0! |
脚本支持
Spring Integration 2.1 增加了对 Java 6 版本引入的 JSR223 Scripting for Java 规范的支持。 它允许你使用任何支持的语言编写的脚本(包括 Ruby、JRuby、Groovy 和 Kotlin)来为各种集成组件提供逻辑,类似于 Spring Expression Language(SpEL)在 Spring Integration 中的使用方式。 有关JSR223的更多信息,请参阅相关文档。
你需要把这种依赖性纳入你的项目中:
-
Maven
-
Gradle
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-scripting</artifactId>
<version>6.3.11</version>
</dependency>
compile "org.springframework.integration:spring-integration-scripting:6.3.11"
此外,你需要添加脚本引擎实现,比如JRuby、Jython。
从 5.2 版本开始,Spring Integration 支持 Kotlin Jsr223。 你需要把这个依赖加入到你的项目中,才能让它正常工作:
-
Maven
-
Gradle
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-scripting-jsr223</artifactId>
<scope>runtime</scope>
</dependency>
runtime 'org.jetbrains.kotlin:kotlin-scripting-jsr223'
| 第三方开发了多种 JSR223 语言实现。 某个实现与 Spring Integration 的兼容性取决于其对规范的一致性以及实现者对规范的解释。 |
| 如果你计划使用 Groovy 作为脚本语言,我们建议你使用 Spring-Integration 的 Groovy 支持,因为它提供了 Groovy 专属的额外功能。 不过,这一部分同样相关。 |
脚本配置
根据集成需求的复杂程度,脚本可以作为 XML 配置中的 CDATA 内联提供,或作为包含该脚本的 Spring 资源的引用。
为了启用脚本支持,Spring Integration 定义了脚本执行消息处理器,将消息有效载荷绑定到名为有效载荷消息头为头变量,两者均可在脚本执行上下文中访问。
你只需要写一个用这些变量的脚本。
以下两对示例展示了创建Filter的示例配置:
-
Java DSL
-
XML
@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>
如前述示例所示,脚本可以内联包含,也可以通过引用资源位置(通过使用位置属性)。
此外,朗属性对应语言名称(或其 JSR223 别名)。
支持脚本的其他 Spring Integration 端点元素包括路由器,服务激活器,转换器和分配器.
每种情况下的脚本配置都与上述相同(除了端点元素)。
脚本支持的另一个有用功能是能够在无需重启应用上下文的情况下更新(重新加载)脚本。
为此,指定刷新-检查-延迟属性脚本元素,如下例所示:
-
Java DSL
-
XML
Scripts.processor(...).refreshCheckDelay(5000)
}
<int-script:script location="..." refresh-check-delay="5000"/>
在前述示例中,脚本位置每5秒检查一次更新。 如果脚本被更新,任何在更新后5秒内发生的调用都会被执行新的脚本。
请考虑以下例子:
-
Java DSL
-
XML
Scripts.processor(...).refreshCheckDelay(0)
}
<int-script:script location="..." refresh-check-delay="0"/>
在前述示例中,上下文会在脚本修改发生后立即更新,提供一种简单的“实时”配置机制。 任何负值表示在应用上下文初始化后脚本未被重新加载。 这是默认的行为。 以下示例展示了一个从未更新的脚本:
-
Java DSL
-
XML
Scripts.processor(...).refreshCheckDelay(-1)
}
<int-script:script location="..." refresh-check-delay="-1"/>
| 内联脚本无法重新加载。 |
脚本变量绑定
变量绑定是使脚本能够引用外部提供的变量的必要条件。
默认情况下,有效载荷和头被用作绑定变量。
你可以通过以下方式绑定额外的变量到脚本上<可变的>元素(或ScriptSpec.variables()选项),如下示例所示:
-
Java DSL
-
XML
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 引用。
注意有效载荷和头仍然包含在作为约束变量。
在 Spring Integration 3.0 版本中,除了变量元素,该变量属性已经被引入。
该属性和变量元素并不互斥,你可以将它们合并在一个内部脚本元件。
然而,无论变量定义在哪里,变量都必须是唯一的。
此外,自 Spring Integration 3.0 起,内联脚本也允许变量绑定,如下示例所示:
<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>
前面的例子展示了内联脚本的组合,以及变量元素,以及一个变量属性。
这变量属性包含逗号分隔值,每个段包含变量及其值的分隔对“=”。
变量名可以加上-裁判,如日期参考在前述例子中为变量。
这意味着绑定变量的名称为,日期,但该值是对dateBean应用上下文中的豆子。
这在使用属性占位符配置或命令行参数时可能非常有用。
如果你需要更多控制变量生成方式,可以实现你自己的 Java 类,使用脚本变量生成器该策略由以下接口定义:
public interface ScriptVariableGenerator {
Map<String, Object> generateScriptVariables(Message<?> message);
}
该接口要求你实现生成脚本变量(消息)方法。
message 参数允许你访问消息有效载荷和头部中可用的任何数据,返回值为地图是束缚变量。
每次为消息执行脚本时都会调用该方法。
以下示例展示了如何实现脚本变量生成器并用脚本变量生成器属性:
-
Java DSL
-
XML
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"/>
如果脚本变量生成器未提供,脚本组件使用DefaultScriptVariableGenerator,合并任意提供的<可变的>元素有效载荷和头来自消息在其生成脚本变量(消息)方法。
你无法同时提供脚本变量生成器属性和<可变的>元素。
它们是互斥的。 |
GraalVM 多语种
从6.0版本开始,框架提供了PolyglotScriptExecutor该API基于GraalVM多语种API。
JavaScript 的 JSR223 引擎实现,原本是从 Java 中移除的,现已被该新脚本执行器取代。
请参阅更多关于在 GraalVM 中启用 JavaScript 支持的信息,以及通过脚本变量传播哪些配置选项。
默认情况下,框架集合allowAllAccess自true在共享的多语圣节上上下文这使得与主机JVM的交互成为可能:
-
新线程的创建和使用。
-
开放的主办课程。
-
通过向类路径添加条目来加载新的宿主类。
-
将新成员导出到多语种装订中。
-
主机系统实现无限制的IO作。
-
通过实验性选项。
-
新子进程的创建与应用。
-
对流程环境变量的访问。
这可以通过超载进行自定义PolyglotScriptExecutor构造器接受org.graalvm.polyglot.Context.Builder.
为了实现这种 JavaScript 支持,GraalVM 使用JS必须使用组件,或者在使用普通JVM时,org.graalvm.sdk:graal-sdk和org.graalvm.js:js必须包含依赖关系。