写在前面
最近一直在搞mule服务总线,用过mule的都知道实际界面拖动生成的是XML内容,往往有很多配置在界面点来点去就很烦人,特别是重复的配置。这时候动态地利用java来创建mule标准的XML内容,就会大大减轻工作量,因此便有了这篇博客。

生成XML的方法有很多,引入不同的工具jar包使用的代码也会不一样,往往别人的博客里面贴出来的代码,都有Document,Element之类的代码,但是假如你代码引入的jar包不对,则拷贝学习别人别人的内容时一片红色波浪线。博客内使用的jar包不用额外引入,因为相关jar包均在rt.jar中。

首先,我想要生成mule里面关于Database中使用类型为Form Template时所用到的配置XML内容,尽管mule可以通过界面配置,但是如下图所示,多张表或者一表多字段就会感觉到博客开头所说的烦人。

java protocbuffer 动态使用 java动态model_父节点

实际XML内容

<db:template-query name="esb_simulation_insert" doc:name="Template Query"> 
    <db:parameterized-query><![CDATA[insert into esb_simulation(name,age,create_date)values(:name,:age,:create_date)]]></db:parameterized-query>  
    <db:in-param name="name" defaultValue="#[payload.NAME]"/>  
    <db:in-param name="age" defaultValue="#[payload.AGE]"/>  
    <db:in-param name="create_date" defaultValue="#[payload.CREATE_DATE]"/> 
  </db:template-query>  
  <db:template-query name="esb_simulation_update" doc:name="Template Query"> 
    <db:parameterized-query><![CDATA[update esb_simulation set age=:age,create_date=:create_date where name=:name]]></db:parameterized-query>  
    <db:in-param name="name" defaultValue="#[payload.NAME]"/>  
    <db:in-param name="age" defaultValue="#[payload.AGE]"/>  
    <db:in-param name="create_date" defaultValue="#[payload.CREATE_DATE]"/> 
  </db:template-query>  
  <db:template-query name="esb_simulation_delete" doc:name="Template Query"> 
    <db:parameterized-query><![CDATA[delete from esb_simulation where name=:name]]></db:parameterized-query>  
    <db:in-param name="name" defaultValue="#[payload.NAME]"/> 
  </db:template-query>

因为对一张表有三种操作,增删改,因此有三种template内容。

有了内需,自然也有了动力搞点小工具来替自己分忧解难。

使用java创建XML分为以下步骤:
(1)创建Document对象
(2)通过Document对象创建所需的Element对象,设置相关属性
(3)Element之间相互append,父Element添加到Document中,形成XML文档结构
(4)通过Transformer、DOMSource、StreamResult来输出到控制台或者文件当中

创建Document对象

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.newDocument();

通过Document对象创建所需的Element对象

Element rootElement = document.createElement("mule");
rootElement.setAttribute("xmlns:doc","http://www.mulesoft.org/schema/mule/documentation");

Element之间相互append,父Element添加到Document中,形成XML文档结构

rootElement.appendChild(whenElement);
        document.appendChild(rootElement);

通过Transformer、DOMSource、StreamResult来输出到控制台或者文件当中

/* 生成XML文件,并且内容输出到控制台 */
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        /* 生成的内容有缩进格式,实际缩进弱,不过好过一行写完 */
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        DOMSource source = new DOMSource(document);
        StreamResult result = new StreamResult(TARGET_FILE);
        transformer.transform(source, result);
        StreamResult consoleResult = new StreamResult(System.out);
        transformer.transform(source, consoleResult);

有了以上的基础,基本就可以生成不太复杂的XML文档内容,最后将会贴出所有代码,有几段代码是需要特别拿出来说一下的。
(1)生成的XML拥有不太好看,但是有点用的换行

transformer.setOutputProperty(OutputKeys.INDENT, "yes");

(2)生成被CDATA包含的内容

doc.createCDATASection(getInsertSQL(table_name,table_fields));

(3)输出到控制台的代码

StreamResult consoleResult = new StreamResult(System.out);
        transformer.transform(source, consoleResult);

(4)不设置doc命名空间就会报错

muleRootElement.setAttribute("xmlns:doc","http://www.mulesoft.org/schema/mule/documentation");

以上几段特别的代码在ALL CODE可以找到,如果像我刚学习java生成XML的友友可以在代码中看一下使用方法,最后也贴出生成db:template-query的所有代码,这个工具类就是帮我生成所需的XML,通过在配置文件中设置字段和表名即可。字段和表名通过Oracle的PLSQL Developer可以很方便获取以逗号分隔的字段值,不用手动去写,生成的XML内容放到mule项目适合的地方就能够愉快的玩耍了。

ALL CODE

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

/**
 * @author CGYDAWN
 * @date 2018-07-16
 */
public class EsbDbTemplateUtil {
    private static final String CONFIG_FILE=System.getProperty("user.dir")+File.separator+"config"+File.separator+"generate_config.properties";
    private static final String TARGET_FILE=System.getProperty("user.dir")+File.separator+"config"+File.separator+"generateTemplate.xml";
    private static final String ZKH = "(";
    private static final String YKH = ")";
    private static final String INSERT_FLAG = "_insert";
    private static final String UPDATE_FLAG = "_update";
    private static final String DELETE_FLAG = "_delete";
    private static final String PAYLOAD_START = "#[payload.";
    private static final String PAYLOAD_END = "]";

    public EsbDbTemplateUtil() {
        System.out.println("PLSQL Copy comma separated,notepad正则替换\\r\\n,再替换空格");
    }

    public static void main(String[] args) throws TransformerException, ParserConfigurationException {
        EsbDbTemplateUtil.generateXML();
    }

    public static void generateXML() throws TransformerException, ParserConfigurationException {
        Properties props = new Properties();
        try {
            props.load(new FileInputStream(CONFIG_FILE));
        } catch (IOException e) {
            e.printStackTrace();
        }
        /* 读取配置文件内容 */
        String table_name = props.getProperty("generate.tablename");
        String table_fields = props.getProperty("generate.fields");
        String primary_key = props.getProperty("generate.primarykey");
        /* 生成Document文档对象 */
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        Document doc = dBuilder.newDocument();

        /* 创建名为mule的根节点 */
        Element muleRootElement = doc.createElement("mule");
        muleRootElement.setAttribute("xmlns:doc","http://www.mulesoft.org/schema/mule/documentation");
        /* 创建insert子节点 */
        Element insertTemplateXML = generateInsertXML(doc,table_name,table_fields);
        /* 创建update子节点 */
        Element updateTemplateXML = generateUpdateXML(doc,table_name,table_fields,primary_key);
        /* 创建delete子节点 */
        Element deleteTemplateXML = generateDeleteXML(doc,table_name,table_fields,primary_key);
        /* UID三个子节点添加到根节点中 */
        muleRootElement.appendChild(insertTemplateXML);
        muleRootElement.appendChild(updateTemplateXML);
        muleRootElement.appendChild(deleteTemplateXML);
        /* 根节点添加到文档对象中 */
        doc.appendChild(muleRootElement);
        /* 生成XML文件,并且内容输出到控制台 */
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();
        /* 生成的内容有缩进格式,实际缩进弱,不过好过一行写完 */
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        DOMSource source = new DOMSource(doc);
        StreamResult result = new StreamResult(TARGET_FILE);
        transformer.transform(source, result);
        StreamResult consoleResult = new StreamResult(System.out);
        transformer.transform(source, consoleResult);
    }

    /**
     * 生成插入部分的template代码
     * @param doc 文档对象
     * @param table_name 表名
     * @param table_fields 表字段,逗号分隔
     * @return
     */
    public static Element generateInsertXML(Document doc,String table_name,String table_fields) {
        /* 生成父节点db:template-query */
        Element templateQueryElement = doc.createElement("db:template-query");
        /* 生成父节点属性name,父节点属性doc:name */
        templateQueryElement.setAttribute("name",table_name+INSERT_FLAG);
        templateQueryElement.setAttribute("doc:name","Template Query");
        /* 生成子节点db:parameterized-query */
        Element insertSqlXml = doc.createElement("db:parameterized-query");
        /* CDATA包含insert SQL语句 */
        insertSqlXml.appendChild(doc.createCDATASection(getInsertSQL(table_name,table_fields)));
        /* 子节点添加到父节点 */
        templateQueryElement.appendChild(insertSqlXml);
        /* 根据字段生成相应的db:in-param内容 */
        generateInParamContent(doc,templateQueryElement,table_fields);
        return templateQueryElement;
    }

    /**
     * 生成更新部分的template代码
     * @param doc 文档对象
     * @param table_name 表名
     * @param table_fields 表字段,逗号分隔
     * @param primarykey 表主键
     * @return
     */
    public static Element generateUpdateXML(Document doc,String table_name,String table_fields,String primarykey) {
        /* 生成父节点db:template-query */
        Element templateQueryElement = doc.createElement("db:template-query");
        /* 生成父节点属性name,父节点属性doc:name */
        templateQueryElement.setAttribute("name",table_name+UPDATE_FLAG);
        templateQueryElement.setAttribute("doc:name","Template Query");
        /* 生成子节点db:parameterized-query */
        Element updateSqlXml = doc.createElement("db:parameterized-query");
        /* CDATA包含update SQL语句 */
        updateSqlXml.appendChild(doc.createCDATASection(getUpdateSQL(table_name,table_fields,primarykey)));
        /* 子节点添加到父节点 */
        templateQueryElement.appendChild(updateSqlXml);
        /* 根据字段生成相应的db:in-param内容 */
        generateInParamContent(doc,templateQueryElement,table_fields);
        return templateQueryElement;
    }

    /**
     * 生成删除部分的template代码
     * @param doc 文档对象
     * @param table_name 表名
     * @param table_fields 表字段,逗号分隔
     * @param primarykey 表主键
     * @return
     */
    public static Element generateDeleteXML(Document doc, String table_name, String table_fields, String primarykey) {
        /* 生成父节点db:template-query */
        Element templateQueryElement = doc.createElement("db:template-query");
        /* 生成父节点属性name,父节点属性doc:name */
        templateQueryElement.setAttribute("name",table_name+DELETE_FLAG);
        templateQueryElement.setAttribute("doc:name","Template Query");
        /* 生成子节点db:parameterized-query */
        Element deleteSqlXML = doc.createElement("db:parameterized-query");
        /* CDATA包含insert SQL语句 */
        deleteSqlXML.appendChild(doc.createCDATASection(getDeleteSQL(table_name,primarykey)));
        Element deleteParam = doc.createElement("db:in-param");
        deleteParam.setAttribute("name",primarykey);
        deleteParam.setAttribute("defaultValue",PAYLOAD_START+primarykey.toUpperCase()+PAYLOAD_END);
        /* 子节点添加到父节点 */
        templateQueryElement.appendChild(deleteSqlXML);
        templateQueryElement.appendChild(deleteParam);
        return templateQueryElement;
    }

    /**
     * 获取insert模板CDATA包含的SQL语句
     * @param table_name 表名
     * @param table_fields 表字段,逗号分隔
     * @return
     */
    public static String getInsertSQL(String table_name,String table_fields) {
        StringBuffer sb = new StringBuffer();
        sb.append("insert into "+table_name+ZKH+table_fields+YKH+"values(:"+table_fields.replaceAll(",",",:")+")");
        return sb.toString();
    }

    /**
     * 获取update模板CDATA包含的SQL语句
     * @param table_name 表名
     * @param table_fields 表字段,逗号分隔
     * @param primarykey 表主键
     * @return
     */
    public static String getUpdateSQL(String table_name,String table_fields,String primarykey) {
        StringBuffer sb = new StringBuffer();
        sb.append("update "+table_name+" set ");
        /* 循环set字段 */
        String[] table_field_array = table_fields.split(",");
        for(int i=0;i<table_field_array.length;i++) {
            /* 如果update的字段为主键,跳过 */
            if(table_field_array[i].equals(primarykey))
                continue;
            sb.append(table_field_array[i]+"=:"+table_field_array[i]+",");
        }
        String updateSql = sb.toString();
        /* 去除最后一个字段set的逗号 */
        updateSql = updateSql.substring(0,updateSql.length()-1);
        sb = new StringBuffer(updateSql);
        /* 设置主键where条件 */
        sb.append(" where "+primarykey+"=:"+primarykey);
        return sb.toString();
    }

    /**
     * 获取delete模板CDATA包含的SQL语句
     * @param table_name 表名
     * @param primarykey 表主键
     * @return
     */
    public static String getDeleteSQL(String table_name,String primarykey) {
        StringBuffer sb = new StringBuffer();
        sb.append("delete from "+table_name+" where "+primarykey+"=:"+primarykey);
        return sb.toString();
    }

    /**
     * 根据字段生成模板参数
     * @param doc 文档对象
     * @param templateQueryElement 父节点TemplateQueryElement对象
     * @param table_fields 表字段
     */
    public static void generateInParamContent(Document doc,Element templateQueryElement,String table_fields) {
        String[] table_field_array = table_fields.split(",");
        for(int i=0;i<table_field_array.length;i++) {
            Element inParamElement = doc.createElement("db:in-param");
            inParamElement.setAttribute("name",table_field_array[i]);
            inParamElement.setAttribute("defaultValue",PAYLOAD_START+table_field_array[i].toUpperCase()+PAYLOAD_END);
            templateQueryElement.appendChild(inParamElement);
        }
    }

}

配置文件

java protocbuffer 动态使用 java动态model_java_02

#表名
generate.tablename=esb_simulation
#字段名
generate.fields=name,age,create_date
#主键名
generate.primarykey=name

写在最后
好记性不如烂笔头~~~