超越自我
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 类似,消息 payload 和 headers 会自动绑定为脚本变量。
如果端点实现只需要一个表达式,如上例所示,大多数人会发现 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 资源一样,您可以指定 classpath、文件系统或 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 规范的一部分。
例如,在使用 Spring Integration 与 Python 时会出现一个小的限制。执行脚本时,预期返回的值是脚本主体中最后一个执行表达式的值。许多面向对象的脚本语言支持在“裸”脚本中使用 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 脚本管理应用程序。