写在前面
最近一直在搞mule服务总线,用过mule的都知道实际界面拖动生成的是XML内容,往往有很多配置在界面点来点去就很烦人,特别是重复的配置。这时候动态地利用java来创建mule标准的XML内容,就会大大减轻工作量,因此便有了这篇博客。
生成XML的方法有很多,引入不同的工具jar包使用的代码也会不一样,往往别人的博客里面贴出来的代码,都有Document,Element之类的代码,但是假如你代码引入的jar包不对,则拷贝学习别人别人的内容时一片红色波浪线。博客内使用的jar包不用额外引入,因为相关jar包均在rt.jar中。
首先,我想要生成mule里面关于Database
中使用类型为Form Template
时所用到的配置XML内容,尽管mule可以通过界面配置,但是如下图所示,多张表或者一表多字段就会感觉到博客开头所说的烦人。
实际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);
}
}
}
配置文件
#表名
generate.tablename=esb_simulation
#字段名
generate.fields=name,age,create_date
#主键名
generate.primarykey=name
写在最后
好记性不如烂笔头~~~