工具 | 版本 |
---|---|
mule-standalone | 3.9.0 |
Anypoint-Studio | 6.4.0 |
Dataweave Function
dataweave language十分强大,能够完成各种格式的转换。其使用场景一般是在Transformer Message
组件中使用,通过在组件配置界面里面编写dwl能够将input转换为你所需要的output。但是实际上,除了Transformer Message组件外,dwl还能配合expression transformer
组件来使用。
Expression Transformer组件图
在expression transformer
中使用dwl使用的是Mule提供的dw function——dw()
,dwl语句可写在括号里面,通过expression transformer解析执行后便能达到和Transformer Message一样的效果。其语法结构如下:
#[dw("<dwl script>","mime type")]
因为dwl在Transformer Message中使用往往带有格式(比如换行,Tab)。因此不建议通过expression transformer组件的可视化来配置。而是直接打开XML中复制dwl代码到组件的expression属性值区域(注意xml中双引号使用"
),
注意使用dw函数需要指定转换后的输出类型。
使用例子
#[dw("payload map ((arrayVal,arrayIdx)-> arrayVal mapObject ((objVal,objIdx)-> '$objIdx':objVal ) )","application/json")]
如果转换的Dataweave语句是固定的,那么实际上使用Transformer Message
或者Expression Transformer
都可以,但是如果Dataweave语句的内容不能确定,动态传入的情况中,那么Transformer Message
就捉襟见肘了。因为其dwl语句在开发时是写死的。
存在当前场景:根据不同的情况,Dataweave语句是从数据库中读取的,并且保留到了flow变量中存储,变量名为dw_statement。
如果此时在Expression Transformer
设置表达式#[flowVars.dw_statement]
,那么并不能达到执行Dataweave的效果。因为该组件只会解析出flow变量中Dataweave语句,但是并不会予以执行。简而言之,如果你想通过该组件智能地给你解析MEL中嵌套的MEL,简单地放入一个MEL表达式是不行的。
通过阅读官方文档,会发现官网提供在Expression Transformer
中提供了好几个Evaluator
,那么这时候使用其中一个名为processor Evaluator
将会解决上面的问题。
姑且称Evaluator为评估器,该process评估器的表达式语法是#[process:processorName:valueToProcess]
。
(官网对其解释)Invokes a message processor within an expression. This processor can be any component, transformer, custom processor, processor chain or flow. This evaluator is most useful when used with a nested expression that determines the value that is processed by the referenced message processor.
表达式让我们指定一个processor来给我们处理这个valueToProcess,这个process可以是一些其他的组件,flow,转换器之类的组件,因此便有了下面的图:
process Evaluator使用图
图红色文字部分最后少了一个]
中括号
在上面截取的结构图中,通过从数据库中获取到了Dataweave语句并保存到flow变量中,然后接一个表达式组件并且配置了图中的表达式。该表达式调用了一个名为getDataweaveProcessor
的subflow。这个flow便是关键,它来真正解析我们保存在flow变量的dwl语句(其中消息增强和Object to JSON组件并不是关键,而是因为我所使用的dwl场景所需要使用而已)。子flow里面使用了一个Java Component
组件,其代码如下:
package com.data.center.utils;
import org.apache.log4j.Logger;
import org.mule.DefaultMuleEvent;
import org.mule.api.MuleEvent;
import org.mule.api.MuleEventContext;
import org.mule.api.lifecycle.Callable;
public class ExpressionEvaluatorInJava implements Callable {
private static final Logger logger = Logger.getLogger(ExpressionEvaluatorInJava.class);
@Override
public Object onCall(MuleEventContext eventContext) throws Exception {
//获取存有dataweave的流变量语句
String dw_statement = eventContext.getMessage().getInvocationProperty("dw_statement").toString();
MuleEvent muleEvent = new DefaultMuleEvent(eventContext.getMessage(), eventContext.getExchangePattern(),
eventContext.getFlowConstruct());
Object response = eventContext.getMuleContext().getExpressionManager().evaluate(dw_statement, muleEvent);
return response;
}
}
在java中,我们获取流变量中保存的Dataweave语句,并且通过JAVA代码来调用表达式解析,而这里处理的内容就是我们Expression Transformer
中传递的payload,表达式中传递的值到了子flow中将变为该flow的负载。response就是我们通过dwl转换的结果内容。
至此达到从flow变量中动态获取Dataweaeve语句解析执行的效果。之所以会有上述一系列的做法,无非就是为了更为灵活地适配不同情况下使用Dataweave来转换数据,如果有更好更方便的方法,欢迎留言评论。
参考资料
官网dw function参考资料
mulesoft博客-Anirban Sen Chowdhary的解析
stackoverflow关于使用processor evaluator-David Dossot的回答
Mule社区关于通过java来解析表达式-kiran.boddepalli的回答
官网对于Expression Evaluator的部分参考资料
关于消息增强的使用-我的博客