领先一步
VMware 提供培训和认证,助您加速进步。
了解更多Spring Integration 脚本支持在 2.1 版本中引入,它建立在 2.0 版本中引入的 Groovy 脚本支持之上。 如果您熟悉 Spring Integration,可以将脚本支持视为您工具箱中的又一个工具,在某些情况下会非常有用。 如果您有以 Groovy、Python、Ruby 或 Javascript 等语言编写的现有代码,并且需要将它们相互集成或集成到 Java 应用程序中, Spring Integration 提供了一种简单的方法。 无论哪种情况,本文都将介绍使用您喜欢的脚本语言与 Spring Integration 结合使用的基础知识。
<int:transformer input-channel="inChannel"
output-channel="outChannel"
expression="payload.toUpperCase() + '- [' + T(java.lang.System).currentTimeMillis() + ']'"/>
这是 Spring Integration 中的常见模式。开箱即用的许多端点都包含expression 属性,其内容被解释为作用于 Message 的 SpEL 表达式。
使用内联脚本也可以实现相同的功能,例如使用 Ruby 编写
<int:transformer input-channel="inChannel"
output-channel="outChannel">
<int-script:script lang="ruby">
"#{payload.upcase} -[#{Time.now.to_i}]"
</int-script:script>
</int:transformer>
请注意,脚本的主体包含在 Spring Integration 2.1 中引入的脚本命名空间定义的script 标签内。 lang 属性指定脚本语言(稍后会详细介绍)。 与 SpEL 类似,消息负载和头会自动绑定为脚本变量。
如果端点实现只需要一个表达式,如上面的示例所示,大多数人会发现 SpEL 比内联脚本更方便。 然而,正如我们将看到的,当需要时,脚本提供了额外的强大功能和灵活性。
<router input-channel="inlineScriptInput">
<int-script:script lang="javascript"><![CDATA[
(function(){
return payload.length > 5 ? "longStrings" : "shortStrings";
})();
]]>
</int-script:script>
</router>
这对于像 Python 这样的语言尤其如此,在这些语言中,换行符和缩进是语法的一部分。 但是,您也可以使用location 属性引用外部脚本
<script:script lang="groovy" location="file:scripts/groovy/myscript.groovy">
与任何 Spring 资源一样,您可以指定类路径、文件系统或 Web 应用程序上下文中的位置。 使用外部脚本可以提供一些额外的功能。 首先,您可以提供自定义变量绑定,为脚本提供额外的输入。 这些可以是原始类型或 Spring bean
<int:service-activator ...>
<int-script:script language="python" location="authorizeCredit.py" refresh-check-delay="60">
<int-script:variable name="creditService" ref="creditService"/>
<int-script:variable name="maximumAmount" value="1000.00"/>
</int:script:script>
</int:service-activator>
<bean id="creditService" class="com.example.CreditService">
...
</bean>
外部脚本提供的另一个选项是能够定期更新脚本内容。 例如, 如果脚本在文件系统中更新,应用程序上下文可以近乎实时地刷新脚本。 要启用此功能,只需提供可选的refresh-check-delay 属性,如上所示,值为秒。 如果值为 0,则刷新立即发生。 小于零的值会禁用刷新。
同样,Spring Integration 不强制或认可任何特定的脚本语言。我们已成功地将 spring-integration-scripting 模块与上述语言进行了测试,但您的使用情况可能因实现细节而异。 与其他 JSR 规范一样,合规性可能存在解释性。 此外,每种语言实现都必须提供一种从脚本环境中导入和访问 Java 类的方法。 这如何完成不是 JSR223 规范的一部分。
例如,使用 Python 和 Spring Integration 时会出现一个小的限制。 执行脚本时,期望返回值是脚本主体中最后一个已执行表达式的值。 许多面向对象的脚本语言支持“裸”脚本中的 return 语句。 返回可以是隐式的或显式的('return' 关键字是可选的)。 让我们再看一下第一个示例
<int:transformer input-channel="inChannel"
output-channel="outChannel">
<int-script:script lang="ruby">
"#{payload.upcase} -[#{Time.now.to_i}]"
</int-script:script>
</int:transformer>
脚本的主体是一个带有隐式返回的单个表达式。 我们也可以使用显式返回
<int:transformer input-channel="inChannel"
output-channel="outChannel">
<int-script:script lang="ruby">
return "#{payload.upcase} -[#{Time.now.to_i}]"
</int-script:script>
</int:transformer>
或者将变量赋给表达式并返回变量
<int:transformer input-channel="inChannel"
output-channel="outChannel">
<int-script:script lang="ruby">
val = "#{payload.upcase} -[#{Time.now.to_i}]";
val
</int-script:script>
</int:transformer>
Python 的工作方式略有不同。 首先,不支持隐式返回。 此外,不允许在函数或方法之外使用 return 语句。 裸表达式在 Python 中是有效的,但该语言在表达式和语句之间进行了微妙的区别,这影响了 JSR233 实现。 例如,如果您使用 engine.eval() 使用 JSR223 计算以下脚本,您将收到一个 null 返回值
def multiply(x,y):
return x*y
multiply(5,7)
相反,您必须将结果赋给一个变量,例如“answer”,并在 eval() 调用之后调用 engine.get("answer") 来获取预期的结果 35。
def multiply(x,y):
return x*y
answer = multiply(5,7)
Spring Integration 包含一个解决方法来解决此限制。 如果脚本的最后一个语句是变量赋值,它将解析变量名并返回 engine.get() 的值。
在此讨论的上下文中,我故意避免使用POJO 这个词,而是使用了更通用的Spring bean。 这是为了指出,即使没有 Spring 框架的帮助,也可以用 Groovy 和 Scala 等语言实现 Spring bean。 此外,Core Spring 已经提供了动态语言支持,允许您例如使用 JRuby 或 BeanShell 实现 Spring bean。 因此,即使没有 Spring Integration 的脚本支持,任何符合适当约定的 Spring bean 都可以实现 Spring Integration 端点。
<int-groovy:script location="myScript.groovy">
<int-groovy:variable name="foo" value="foo"/>
<int-groovy:variable name="bar" value="bar"/>
<int-groovy:variable name="date" ref="date"/>
</int-groovy:script>
<int-script:script lang="groovy" location="myScript.groovy">
<int-script:variable name="foo" value="foo"/>
<int-script:variable name="bar" value="bar"/>
<int-script:variable name="date" ref="date"/>
</int-script:script>
如果您只对 Groovy 感兴趣,原生支持是更好的选择。 此外,Spring Integration 的 Groovy 支持包括 Groovy 控制总线,它允许您使用 Groovy 脚本在运行时管理您的应用程序。