一、Java Transformer

1.首先在项目目录下创建一个类,一定要在main文件夹下,此例为Data2Map

创建类时选择基类为org.mule.transformer.AbstractMessageTransformer

 

2.在Flow中加入一个Java Transformer组件,并指向所创建的类

 

3.重写父类的transformMessage方法,该方法的返回值即为下一组件的message.payload

package org.znufe.transformer;

import java.math.BigDecimal;
import java.util.*;

import org.mule.api.MuleMessage;
import org.mule.api.transformer.TransformerException;
import org.mule.transformer.AbstractMessageTransformer;

public class Data2Map extends AbstractMessageTransformer {

    @Override
    public Object transformMessage(MuleMessage message, String outputEncoding)
            throws TransformerException {
        // TODO Auto-generated method stub
        String strId = "'StartFlag'";
        LinkedList<Map<Object, Object>> list = (LinkedList<Map<Object, Object>>) message.getPayload();
        Map<Object, Map<Object, Object>> resultTrans = new HashMap<Object, Map<Object,Object>>();    //一级Key为科室,二级Key为物资
        if(list.size() != 0) {
            for(int i = 0; i < list.size(); i++) {
                strId += " , '" + (String) list.get(i).get("ID") + "'";
                String upperKey = (String) list.get(i).get("C_DEPT_CODE");
                //判断一级Key不存在则新建
                if(!resultTrans.containsKey(upperKey)) {
                    Map<Object, Object> upperValue = new HashMap<Object, Object>();
                    upperValue.put(list.get(i).get("M_CODE"), list.get(i).get("C_AMOUNT"));
                    resultTrans.put(upperKey, upperValue);
                } else {
                    String lowerKey = (String) list.get(i).get("M_CODE");
                    //判断二级Key
                    if(!resultTrans.get(upperKey).containsKey(lowerKey)) {
                        resultTrans.get(upperKey).put(lowerKey, list.get(i).get("C_AMOUNT"));
                    } else {
                        BigDecimal addAmount = (BigDecimal) list.get(i).get("C_AMOUNT");
                        BigDecimal oldAmount = (BigDecimal) resultTrans.get(upperKey).get(lowerKey);
                        resultTrans.get(upperKey).remove(lowerKey);
                        resultTrans.get(upperKey).put(lowerKey, oldAmount.add(addAmount));
                    }
                }
            }    
        }
        message.setSessionProperty("CurrentBatch", strId);
        return resultTrans;
    }

}

此例中将数据库查询结果(通过message.getPayload()方法获取)包装成了一个map传递到下一组件,同时设置了一个Session Variable保存部分数据。

 

二、 默认数据格式转换工具

常用默认数据格式转换工具有JSON to Object, JSON to XML,Object to XML等等。Mule会按预设方式将数据格式进行转换。

 

三、WebService Consumer

WebService Consumer用以调用外部资源WebService。

1.首先添加一个WebService配置

 

2.填写配置

图中WDSL文件用于让组件获取WebService所暴露的接口信息,Port则指定了SOAP协议的版本号,不同版本号的输入与输出XML格式有些差异。

 

3.选择接口

WebService配置完成后需要选择所调用的接口,此时组件已经根据WDSL获取了所以接口信息,只需要下拉选择接口即可。

注:WebService Consumer组件输出的message.payload是一个SOAP格式的XML的(org.apache.cxf.staxutils.DepthXMLStreamReader)对象,可以利用Java Transformer来解析获取数据。

 

四、Parse Template Transformer

首先致敬此文:外国大神就是会玩

 Parse Template Transformer主要用于按格式包装数据,比如将数据包装成SOAP的XML的格式作为WebService Consumer的输入。

假设某WebService其中一个接口的SOAP 1.2输入如下

POST /Ipedf.Hrp.MTR.API/OutstockFlow.asmx HTTP/1.1
Host: localhost
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <CreateDeptApply xmlns="http://tempuri.org/">
      <strJson>string</strJson>
    </CreateDeptApply>
  </soap12:Body>
</soap12:Envelope>

1.根据以上SOAP XML的格式创建一个格式文件(.txt)内容如下,便将上一组件传递过来的数据进行了包装

<?xml version="1.0" encoding="utf-8"?>
<CreateDeptApply xmlns="http://tempuri.org/">
  <strJson>#[message.payload]</strJson>
</CreateDeptApply>

 

2.将格式文件与组件进行关联

 

五、Set Payload

该组件用于设置欲传递到下一组建的数据。

只需要改写Settings中的Value即可,可以利用MEL组合数据也可以是普通的字符(串)。

 

六、Database

基本用法参见第02篇:Mule_ESB_02

官方文档传送门:Mule Database Connector

1.Database组件中QueryType有三种:Parameterized,Dynamic,From Template。其中前两者较为常用。

Parameterized方式只有在执行sql时才把sql中出现的MEL值计算出来并能够自动根据数据库表字段类型进行转换(这样便不需要添加<''>),安全性较高(防止sql注入),在执行多条sql效率相对较高。示例:

insert into employees where name = [message.payload.name]

注:Parameterized中的MEL不带<#>

 

Dynamic方式则在拼接sql时就已经计算好MEL的值,执行sql不会自动转换类型并存在安全问题,但是此方式在使用时灵活性更高且在执行单条sql时效率相对较高。示例:

select * from #[tablename] where id = 1

 

2.Option选项中除了常规CRUD还有Stored Procedure,Bulk Execute,Execute DDL可选。其中后两者较为常用。

Bulk Execute支持一次执行多条sql语句,但是每条sql语句之间必须用分号加换行符(<;\r\n>)作为分隔符,而且末条sql不可有分号,sql示例如下:

update TB_TEST1 set age = 100 where id = '100';

update TB_TEST1 set age = 2 where id = '2';

update TB_TEST1 set age = 1 where id = '1'

 

Execute DDL则主要用于对数据库表本身相关的操作(比如建表操作)。