自己动手实现mybatis动态sql的方法

网友投稿 375 2023-03-07


自己动手实现mybatis动态sql的方法

发现要坚持写博客真的是一件很困难的事情,各种原因都会导致顾不上博客。本来打算写自己动手实现orm,看看时间,还是先实现一个动态sql,下次有时间再补上orm完整的实现吧。

用过mybatis的人,估计对动态sql都不陌生,如果没有用过,就当看看热闹吧。我第一次接触mysql是在大四的时候,当时就觉得动态sql这东西很牛,很灵活,一直想搞明白怎么实现的,尽管当时已经能够写ioc,mvc和简单的orm框架(仿mybaits但是没有动态sql部分),但是仍然找不到mybatis核心的动态sql到底在哪实现的,怎么实现的,可能是那些代码太绕根本没法看懂,直到目前,我都没有勇气去看mybatis的动态sql部分,大概是天生对算法有莫名其妙的敬畏吧。

几年前因为想做一个配置平台,想用解析型语言替代java的实现,可以让配置人员在页面上方便的编写少量代码实现复杂的业务逻辑(包括数据库操作)。当时java已经有js解析引擎,但是大多数人都说效率太低,不知道我发什么疯就想到自己实现一个解析语言。不过实现自己的语言也是我一直的梦想,解析语言相对编译型语言入手简单,于是我就果断动手了,写完才知道,其实自己的实现估计还没有当时的js引擎效率高,那时的我真的是很年轻很简单。今天谈到的动态sql实现其实就是受到那时候解析语言的启发。

废话不多说直接开始聊动态sql,请看下面例子,先声明这里的例子并不是一个正确的sql的写法,只是想写一个尽量复杂的嵌套结构,如果把这种复杂的情况实现了,那么简单一点的就更加不在话下了。

delete from pl_pagewidget

where pagewidgetcode in

#{item}

#{b}

and a = #{a}

要实现解析出上面例子的sql,首先一个难点类似是test属性里的条件怎么判断真假,不过这个难点在struts2中学到的ognl表达式面前就比较小儿科了。不知道有么有朋友遇到过一个比较奇葩的现象,就是有时候明明在mybatis动态sql中写如下表达式,但是当n=0的时候居然是满足条件的也就是test里的值是false,0居然不能满足这个表达式的条件,这里就是ognl库的原因了。没办法它就是这么玩的,当成特殊情况记住就可以了

test="n != null and n !=''"

ognl表达式使用很方便如下

import java.util.HashMap;

import java.util.Map;

import ognl.Ognl;

public class OgnlTest {

//输出结果:false

public static void main(String[] args) throws Exception {

String con1 = "n != null and n != ''";

Map root = new HashMap<>();

root.put("n", 0);

System.out.println(Ognl.getValue(con1,root));

}

}

要实现解析上面例子的sql,第二个难点就是虽然这个sql披上一层xml的皮就是一个标准的sql,如下

delete from pl_pagewidget

where pagewidgetcode in

#{item}

#{b}

and a = #{a}

但是要解析上面的xml和我们平时不一样,这个xml是标签和文本混合的,正常我们开发中应该很少会用到解析这种xml。不过我们常用的解析xml的工具dom4j其实可以很好的解析这种sql,只不过很少可能用到。Element类的content()方法就可以返回一个Node的集合,再通过遍历这个集合,判断每个Node的类型就可以了。解决了这两个重点,只需要加上一点技巧就可以解析这种动态sql了。

我用到的技巧是根据java语法格式得到的启发。比如java中有局部变量和全局变量,不考虑引用传递这种情况,如果全局变量int i = 1;方法里面传入这个全局变量,然后在方法里面修改,在方法里面看到的是改变后的值,但是在方法外面看到的仍然是1。这个现象其实学过java应该都知道。还有就是当方法调用的时候,方法里面可以看到全局变量,也可以看到局部变量,方法调用结束后局部变量会被清空释放(看垃圾搜集器高兴)。介绍了这些直接上代码了

import java.io.StringReader;

import java.text.SimpleDateFormat;

import java.util.Arrays;

import java.util.Date;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import org.apache.commons.collections.MapUtils;

import org.apache.commons.lang.StringUtils;

import org.dom4j.Document;

import org.dom4j.Element;

import org.dom4j.Node;

import org.dom4j.Text;

import org.dom4j.io.SAXReader;

import com.rd.sql.Attrs;

import com.rd.sql.BaseNode;

import com.rd.sql.NodeFactory;

public class SqlParser {

private Map currParams = new HashMap();

/**

delete from pl_pagewidget

where pagewidgetcode in

#{item}

#{b}

and a = #{a}

*/

public static void main(String[] args) throws Exception {

Map map = new HashMap();

map.put("widgetcodes", Arrays.asList("1", "2"));

map.put("bs", Arrays.asList("3", "4"));

map.put("a", 1);

SqlParser parser = new SqlParser();

System.out

.println(parser.parser("delete from pl_pagewidget\n"

+ "\t\n"

+ "\t\twhere pagewidgetcode in\n"

+ "\t\t\n"

+ "\t\t \n"

+ "\t\t #{item}\n"

+ "\t\t \n"

+ "\t\t \n"

+ "\t\t\t#{b}\n" + "\t\t \n"

+ "\t\t\n" + "\t\n"

+ "\t\n"

+ "\t\tand a = #{a}\n" + "\t\n", map));

System.out.println(parser.getParams());

}

public String parser(String xml, Map params)

throws Exception {

// xml = ""+xml;

//给输入的动态sql套一层xml标签

xml = ""+xml+"";

SAXReader reader = new SAXReader(false);

Document document = reader.read(new StringReader(xml));

Element element = document.getRootElement();

Map currParams txLjf= new HashMap();

StringBuilder sb = new StringBuilder();

//开始解析

parserElement(element, currParams, params, sb);

return sb.toString();

}

/**

* 使用递归解析动态sql

* @param ele1 待解析的xml标签

* @param currParams

* @param globalParams

* @param sb

* @throws Exception

*/

private void parserElement(Element ele1, Map currParams,

Map globalParams, StringBuilder sb)

throws Exception {

// 解析一个节点,比如解析到了一个if节点,假如test判断为true这里就返回true

TempVal val = parserOneElement(currParams, globalParams, ele1, sb);

//得到解析的这个节点的抽象节点对象

BaseNode node = val.getNode();

/**

* 实际上这句之上的语句只是解析了xml的标签,并没有解析标签里的内容,这里

* 表示要解析内容之前,如果有前置操作做一点前置操作

*/

node.pre(currParams, globalParams, ele1, sb);

//判断是否还需要解析节点里的内容,例如if节点test结果为true

boolean flag = val.isContinue();

// 得到该节点下的所有子节点的集合,包含普通文本

List nodes = ele1.content();

if (flag && !nodes.isEmpty()) {

/**

* 这里表示要进一步解析节点里的内容了,可以把节点类比成一个方法的外壳

* 里面的内容类比成方法里的具体语句,开始解析节点的内容之前

* 先创建本节点下的局部参数的容器,最方便当然是map

*/

Map params = new HashMap();

/**

* 把外面传进来的局部参数,直接放入容器,由于本例中参数都是常用数据类型

* 不会存在引用类型所以,这里相当于是一个copy,为了不影响外面传入的对象

* 可以类比方法调用传入参数的情况

*/

params.putAll(currParams);

//循环所有子节点

for (int i = 0; i < nodes.size();) {

Node n = nodes.get(i);

//如果节点是普通文本

if (n instanceof Text) {

String text = ((Text) n).getStringValue();

if (StringUtils.isNotEmpty(text.trim())) {

//处理一下文本,如处理#{xx},直接替换${yy}为真实传入的值

sb.append(handText(text, params,globalParams));

}

i++;

} else if (n instanceof Element) {

Element e1 = (Element) n;

// 递归解析xml子元素

parserElement(e1, params, globalParams, sb);

// 如果循环标志不为true则解析下一个标签

// 这里表示需要重复解析这个循环标签,则i不变,反之继续处理下一个元素

boolean while_flag = MapUtils.getBoolean(params,

Attrs.WHILE_FLAG, false);

if (!while_flag

|| !NodeFactory.isWhile(n.getName())

|| e1.attributeValue(Attrs.INDEX) == null

|| !e1.attributeValue(Attrs.INDEX).equals(

params.get(Attrs.WHILE_INDEX))) {

i++;

}

}

}

//节点处理之后做一些啥事

node.after(currParams, globalParams, ele1, sb);

// 回收当前作用域参数

params.clear();

params = null;

}

}

/**

* 处理文本替换掉#{item}这种参数

* @param str

* @param params

* @return

* @throws Exception

*/

private String handText(String str, Map params,Map globalParams)

throws Exception {

//获取foreach这种标签中用于记录循环的变量

String indexStr = MapUtils.getString(params, Attrs.WHILE_INDEX);

Integer index = null;

if(StringUtils.isNotEmpty(indexStr)) {

index = MapUtils.getInteger(params, indexStr);

}

//匹配#{a}这种参数

String reg1 = "(#\\{)(\\w+)(\\})";

//匹配${a}这种参数

String reg2 = "(\\$\\{)(\\w+)(\\})";

Pattern p1 = Pattern.compile(reg1);

Matcher m1 = p1.matcher(str);

Pattern p2 = Pattern.compile(reg2);

Matcher m2 = p2.matcher(str);

String whileList = MapUtils.getString(params, Attrs.WHILE_LIST);

Map allParams = getAllParams(params, globalParams);

while(m1.find()) {

String tmpKey = m1.group(2);

String key = whileList == null?tmpKey:(whileList+"_"+tmpKey);

key = index == null?key:(key+index);

String reKey = "#{"+key+"}";

//如果在foreach类似的循环里,可能需要将参数#{xx}替换成#{xx_0},#{xx_1}

str = str.replace(m1.group(0), reKey);

currParams.put(key, allParams.get(tmpKey));

}

while(m2.find()) {

String tmpKey = m2.group(2);

Object value = allParams.get(tmpKey);

if(value != null) {

str = str.replace(m2.group(0), getValue(value));

}

}

return str;

}

private String getValue(Object value) {

String result = "";

if(value instanceof Date) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

result = sdf.format((Date)value);

} else {

result = String.valueOf(value);

}

return result;

}

private Map getAllParams(Map currParams,

Map globalParams) {

Map allParams = new HashMap();

allParams.putAll(globalParams);

allParams.putAll(currParams);

return allParams;

}

// 解析一个xml元素

private TempVal parserOneElement(Map currParams,

Map globalParams, Element ele, StringBuilder sb)

throws Exception {

//获取xml标签名

String eleName = ele.getName();

//解析一个节点后是否继续,如遇到if这种节点,就需要判断test里是否为空

boolean isContinue = false;

//声明一个抽象节点

BaseNode node = null;

if (StringUtils.isNotEmpty(eleName)) {

//使用节点工厂根据节点名得到一个节点对象比如是if节点还是foreach节点

node = NodeFactory.create(eleName);

//解析一下这个节点,返回是否还需要解析节点里的内容

isContinue = node.parse(currParams, globalParams, ele, sb);

}

return new TempVal(isContinue, ele, node);http://

}

public Map getParams() {

return currParams;

}

/**

* 封装一个xml元素被解析后的结果

* @author rongdi

*/

final static class TempVal {

private boolean isContinue;

private Element ele;

private BaseNode node;

public TempVal(boolean isContinue, Element ele, BaseNode node) {

this.isContinue = isContinue;

this.ele = ele;

this.node = node;

}

public boolean isContinue() {

return isContinue;

}

public void setContinue(boolean isContinue) {

this.isContinue = isContinue;

}

public Element getEle() {

return ele;

}

public void setEle(Element ele) {

this.ele = ele;

}

public BaseNode getNode() {

return node;

}

public void setNode(BaseNode node) {

this.node = node;

}

}

}

import org.dom4j.Element;

import java.util.HashMap;

import java.util.Map;

/**

* 抽象节点

* @author rongdi

*/

public abstract class BaseNode {

public abstract boolean parse(Map currParams, Map globalParams, Element ele,StringBuilder sb) throws Exception;

public void pre(Map currParams,Map globalParams,Element ele,StringBuilder sb) throws Exception {

}

public void after(Map currParams,Map globalParams,Element ele,StringBuilder sb) throws Exception {

}

protected Map getAllParams(Map currParams,

Map globalParams) {

Map allParams = new HashMap();

allParams.putAll(globalParams);

allParams.putAll(currParams);

return allParams;

}

}

import java.util.Map;

import ognl.Ognl;

import org.apache.commons.lang.StringUtils;

import org.dom4j.Element;

/**

* if节点

* @author rongdi

*/

public class IfNode extends BaseNode{

@Override

public boolean parse(Map currParams, Map globalParams, Element ele,StringBuilder sb) throws Exception {

//得到if节点的test属性

String testStr = ele.attributeValue("test");

boolean test = false;

try {

if(StringUtils.isNotEmpty(testStr)) {

//合并全局变量和局部变量

Map allParams = getAllParams(currParams,globalParams);

//使用ognl判断true或者false

test = (Boolean) Ognl.getValue(testStr,allParams);

}

} catch (Exception e) {

e.printStackTrace();

throw new Exception("判断操作参数"+testStr+"不合法");

}

if(ele.content() != null && ele.content().size()==0) {

test = true;

}

return test;

}

}

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.Set;

import ognl.Ognl;

import org.apache.commons.collections.MapUtils;

import org.apache.commons.lang.StringUtils;

import org.dom4j.Element;

/**

foreach节点属性如下

collection 需要遍历的集合

item 遍历集合后每个元素存放的变量

index 遍历集合的索引数如0,1,2...

separator 遍历后以指定分隔符拼接

open 遍历后拼接开始的符号如 (

close 遍历后拼接结束的符号如 )

*/

public class ForeachNode extends BaseNode {

@Override

public boolean parse(Map currParams, Map globalParams, Element ele, StringBuilder sb) throws Exception {

String conditionStr = null;

String collectionStr = ele.attributeValue("collection");

String itemStr = ele.attributeValue("item");

String index = ele.attributeValue("index");

String separatorStr = ele.attributeValue("separator");

String openStr = ele.attributeValue("open");

String closeStr = ele.attributeValue("close");

if(StringUtils.isEmpty(index)) {

index = "index";

}

if(StringUtils.isEmpty(separatorStr)) {

separatorStr = ",";

}

if(StringUtils.isNotEmpty(openStr)) {

currParams.put(Attrs.WHILE_OPEN,openStr);

}

if(StringUtils.isNotEmpty(closeStr)) {

currParams.put(Attrs.WHILE_CLOSE,closeStr);

}

if(StringUtils.isNotEmpty(collectionStr)) {

currParams.put(Attrs.WHILE_LIST,collectionStr);

}

currParams.put(Attrs.WHILE_SEPARATOR,separatorStr);

if(index != null) {

/**

* 如果局部变量中存在当前循环变量的值,就表示已经不是第一次进入循环标签了,移除掉开始标记

* 并将局部变量值加1

*/

if(currParams.get(index) != null) {

currParams.remove(Attrs.WHILE_START);

currParams.put(index+"_", (Integer)currParams.get(index+"_") + 1);

} else { //第一次进入循环标签内

currParams.put(Attrs.WHILE_START,true);

currParams.put(index+"_", 0);

}

currParams.put(index, (Integer)currParams.get(index+"_"));

}

boolean condition = true;

Map allParams = getAllParams(currParams,globalParams);

Object collection = null;

if(StringUtils.isNotEmpty(collectionStr)) {

//得到待循环的集合

collection = Ognl.getValue(collectionStr,allParams);

//如果集合属性不为空,但是条件为null则默认加上一个边界条件

if(StringUtils.isEmpty(conditionStr)) {

//这里只是用集合演示一下,也可以再加上数组,只不过改成.length而已

if(collection instanceof List) {

conditionStr = index+"_<"+collectionStr+".size()";

} else if(collection instanceof Map){

Map map = (Map)collection;

Set set = map.entrySet();

List list = new ArrayList(set);

allParams.put("_list_", list);

conditionStr = index+"_<_list_>

}

}

}

currParams.remove(Attrs.WHILE_END);

if(StringUtils.isNotEmpty(conditionStr)) {

//计算条件的值

condition = (Boolean)Ognl.getValue(conditionStr,allParams);

Map tempMap = new HashMap<>();

tempMap.putAll(allParams);

tempMap.put(index+"_",(Integer)currParams.get(index+"_") + 1);

currParams.put(Attrs.WHILE_END,!(Boolean)Ognl.getValue(conditionStr,tempMap));

}

boolean flag = true;

currParams.put(Attrs.WHILE_INDEX, index);

currParams.put(Attrs.WHILE_FLAG, true);

if(condition) {

try {

if(StringUtils.isNotEmpty(itemStr) && StringUtils.isNotEmpty(collectionStr)) {

Object value = null;

int idx = Integer.parseInt(currParams.get(index+"_").toString());

if(collection instanceof List) {

value = ((List)collection).get(idx);

currParams.put(itemStr, value);

} else if(collection instanceof Map){

Map map = (Map)collection;

Set> set = map.entrySet();

List> list = new ArrayList(set);

currParams.put(itemStr, list.get(idx).getValue());

currParams.put(index, list.get(idx).getKey());

}

}

} catch (Exception e) {

throw new Exception("从集合或者映射取值"+currParams.get(index)+"错误"+e.getMessage());

}

} else {

flag = false;

destroyVars(currParams, index, itemStr);

}

return flag;

}

/**

* 如果是第一次进入循环标签,则拼上open的内容

*/

@Override

public void pre(Map currParams, Map globalParams, Element ele, StringBuilder sb) throws Exception {

super.pre(currParams, globalParams, ele, sb);

boolean start = MapUtils.getBoolean(currParams,Attrs.WHILE_START,false);

if(start) {

String open = MapUtils.getString(currParams,Attrs.WHILE_OPEN);

sb.append(open);

}

}

/**

* 如果是最后进入循环标签,则最后拼上close的内容

*/

@Override

public void after(Map currParams, Map globalParams, Element ele, StringBuilder sb) throws Exception {

super.after(currParams, globalParams, ele, sb);

boolean end = MapUtils.getBoolean(currParams,Attrs.WHILE_END,false);

String separator = MapUtils.getString(currParams,Attrs.WHILE_SEPARATOR);

if(!end && StringUtils.isNotEmpty(separator)) {

sb.append(separator);

}

if(end) {

String close = MapUtils.getString(currParams,Attrs.WHILE_CLOSE);

if(sb.toString().endsWith(separator)) {

sb.deleteCharAt(sb.length() - 1);

}

sb.append(close);

}

}

//释放临时变量

private void destroyVars(Map currParams, String index,String varStr) {

currParams.remove(Attrs.WHILE_INDEX);

currParams.remove(Attrs.WHILE_FLAG);

currParams.remove(Attrs.WHILE_SEPARATOR);

currParams.remove(Attrs.WHILE_START);

currParams.remove(Attrs.WHILE_END);

currParams.remove(Attrs.WHILE_LIST);

    }

}

import org.dom4j.Element;

import java.util.Map;

public class SqlNode extends BaseNode{

@Override

public boolean parse(Map currParams, Map globalParams, Element ele,StringBuilder sb) throws Exception {

return true;

}

}

import java.util.Arrays;

import java.util.List;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

/**

* 节点工厂

*/

public class NodeFactory {

private static Map nodeMap = new ConcurrentHashMap();

private final static List whileList = Arrays.asList("foreach");

static {

nodeMap.put("if", new IfNode());

nodeMap.put("sql", new SqlNode());

nodeMap.put("foreach", new ForeachNode());

}

public static boolean isWhile(String elementName) {

return whileList.contains(elementName);

}

public static void addNode(String nodeName,BaseNode node) {

nodeMap.put(nodeName, node);

}

public static BaseNode create(String nodeName) {

return nodeMap.get(nodeName);

}

}

/**

* 各种标记

* @author rongdi

*/

public class Attrs {

public final static String TRANSACTIONAL = "transactional";

public final static String WHILE_START = "while-start";

public final static String WHILE_END = "while-end";

public final static String WHILE_OPEN = "while-open";

public final static String WHILE_CLOSE = "while-close";

public final static String WHILE_SEPARATOR = "while-separator";

public final static String WHILE_INDEX = "while-index";

public final static String WHILE_FLAG = "while-flag";

public final static String WHILE_LIST = "while-list";

public final static String WHEN_FLAG = "when-flag";

public static final String PROCESS_VAR = "process-var";

public final static String RESULT_FLAG = "result-flag";

public final static String RETURN_FLAG = "return-flag";

public final static String CONSOLE_VAR= "console-var";

public final static String DO = "do";

public final static String INDEX = "index";

public final static String CONDITION = "condition";

public final static String NAME= "name";

public final static String VALUE= "value";

public static final String TYPE = "type";

public static final String FORMAT = "format";

public static final String IF = "if";

public static final String ELSE = "else";

public final static String FILE= "file";

public static final String DATE = "date";

public static final String NOW = "now";

public static final String DECIMAL = "decimal";

public static final String ID = "id";

public static final String PARAMS = "params";

public static final String TARGET = "target";

public static final String SINGLE = "single";

public static final String PAGING = "paging";

public static final String DESC = "desc";

public static final String BREAK = "break";

public static final String CONTINUE = "continue";

public static final String COLLECTION = "collection";

public static final String VAR = "var";

public static final String EXECUTOR = "executor-1";

public static final String ROLLBACK_FLAG = "rollback-flag";

public static final String SERVICE = "service";

public static final String REF = "ref";

public static final String BIZS = "bizs";

public static final String TITLES = "titles";

public static final String COLUMNS = "columns";

public static final String CURRUSER = "currUser";

public static final String CURRPERM = "currPerm";

public static final String TASK_EXECUTOR = "taskExecutor";

public static final String DELIMITER = "delimiter";

public static final String OPERNAME = "operName";

}

currParams.remove(varStr);

currParams.remove(index);

currParams.remove(index+"_");

}

}

附上pom文件

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

4.0.0

com.rd

parser

jar

1.0-SNAPSHOT

myparser

http://maven.apache.org

dom4j

dom4j

1.6.1

opensymphony

ognl

2.6.11

commons-collections

commons-collections

3.2.1

commons-lang

commons-lang

2.6

junit

junit

3.8.1

test

src/main/java

**/*.xml

src/main/resources

**/*

${project.basedir}/src/test/java

${project.basedir}/src/test/resources

org.apache.maven.plugins

maven-compiler-plugin

3.1

1.8

1.8

UTF-8

}

}

}

currParams.remove(Attrs.WHILE_END);

if(StringUtils.isNotEmpty(conditionStr)) {

//计算条件的值

condition = (Boolean)Ognl.getValue(conditionStr,allParams);

Map tempMap = new HashMap<>();

tempMap.putAll(allParams);

tempMap.put(index+"_",(Integer)currParams.get(index+"_") + 1);

currParams.put(Attrs.WHILE_END,!(Boolean)Ognl.getValue(conditionStr,tempMap));

}

boolean flag = true;

currParams.put(Attrs.WHILE_INDEX, index);

currParams.put(Attrs.WHILE_FLAG, true);

if(condition) {

try {

if(StringUtils.isNotEmpty(itemStr) && StringUtils.isNotEmpty(collectionStr)) {

Object value = null;

int idx = Integer.parseInt(currParams.get(index+"_").toString());

if(collection instanceof List) {

value = ((List)collection).get(idx);

currParams.put(itemStr, value);

} else if(collection instanceof Map){

Map map = (Map)collection;

Set> set = map.entrySet();

List> list = new ArrayList(set);

currParams.put(itemStr, list.get(idx).getValue());

currParams.put(index, list.get(idx).getKey());

}

}

} catch (Exception e) {

throw new Exception("从集合或者映射取值"+currParams.get(index)+"错误"+e.getMessage());

}

} else {

flag = false;

destroyVars(currParams, index, itemStr);

}

return flag;

}

/**

* 如果是第一次进入循环标签,则拼上open的内容

*/

@Override

public void pre(Map currParams, Map globalParams, Element ele, StringBuilder sb) throws Exception {

super.pre(currParams, globalParams, ele, sb);

boolean start = MapUtils.getBoolean(currParams,Attrs.WHILE_START,false);

if(start) {

String open = MapUtils.getString(currParams,Attrs.WHILE_OPEN);

sb.append(open);

}

}

/**

* 如果是最后进入循环标签,则最后拼上close的内容

*/

@Override

public void after(Map currParams, Map globalParams, Element ele, StringBuilder sb) throws Exception {

super.after(currParams, globalParams, ele, sb);

boolean end = MapUtils.getBoolean(currParams,Attrs.WHILE_END,false);

String separator = MapUtils.getString(currParams,Attrs.WHILE_SEPARATOR);

if(!end && StringUtils.isNotEmpty(separator)) {

sb.append(separator);

}

if(end) {

String close = MapUtils.getString(currParams,Attrs.WHILE_CLOSE);

if(sb.toString().endsWith(separator)) {

sb.deleteCharAt(sb.length() - 1);

}

sb.append(close);

}

}

//释放临时变量

private void destroyVars(Map currParams, String index,String varStr) {

currParams.remove(Attrs.WHILE_INDEX);

currParams.remove(Attrs.WHILE_FLAG);

currParams.remove(Attrs.WHILE_SEPARATOR);

currParams.remove(Attrs.WHILE_START);

currParams.remove(Attrs.WHILE_END);

currParams.remove(Attrs.WHILE_LIST);

    }

}

import org.dom4j.Element;

import java.util.Map;

public class SqlNode extends BaseNode{

@Override

public boolean parse(Map currParams, Map globalParams, Element ele,StringBuilder sb) throws Exception {

return true;

}

}

import java.util.Arrays;

import java.util.List;

import java.util.Map;

import java.util.concurrent.ConcurrentHashMap;

/**

* 节点工厂

*/

public class NodeFactory {

private static Map nodeMap = new ConcurrentHashMap();

private final static List whileList = Arrays.asList("foreach");

static {

nodeMap.put("if", new IfNode());

nodeMap.put("sql", new SqlNode());

nodeMap.put("foreach", new ForeachNode());

}

public static boolean isWhile(String elementName) {

return whileList.contains(elementName);

}

public static void addNode(String nodeName,BaseNode node) {

nodeMap.put(nodeName, node);

}

public static BaseNode create(String nodeName) {

return nodeMap.get(nodeName);

}

}

/**

* 各种标记

* @author rongdi

*/

public class Attrs {

public final static String TRANSACTIONAL = "transactional";

public final static String WHILE_START = "while-start";

public final static String WHILE_END = "while-end";

public final static String WHILE_OPEN = "while-open";

public final static String WHILE_CLOSE = "while-close";

public final static String WHILE_SEPARATOR = "while-separator";

public final static String WHILE_INDEX = "while-index";

public final static String WHILE_FLAG = "while-flag";

public final static String WHILE_LIST = "while-list";

public final static String WHEN_FLAG = "when-flag";

public static final String PROCESS_VAR = "process-var";

public final static String RESULT_FLAG = "result-flag";

public final static String RETURN_FLAG = "return-flag";

public final static String CONSOLE_VAR= "console-var";

public final static String DO = "do";

public final static String INDEX = "index";

public final static String CONDITION = "condition";

public final static String NAME= "name";

public final static String VALUE= "value";

public static final String TYPE = "type";

public static final String FORMAT = "format";

public static final String IF = "if";

public static final String ELSE = "else";

public final static String FILE= "file";

public static final String DATE = "date";

public static final String NOW = "now";

public static final String DECIMAL = "decimal";

public static final String ID = "id";

public static final String PARAMS = "params";

public static final String TARGET = "target";

public static final String SINGLE = "single";

public static final String PAGING = "paging";

public static final String DESC = "desc";

public static final String BREAK = "break";

public static final String CONTINUE = "continue";

public static final String COLLECTION = "collection";

public static final String VAR = "var";

public static final String EXECUTOR = "executor-1";

public static final String ROLLBACK_FLAG = "rollback-flag";

public static final String SERVICE = "service";

public static final String REF = "ref";

public static final String BIZS = "bizs";

public static final String TITLES = "titles";

public static final String COLUMNS = "columns";

public static final String CURRUSER = "currUser";

public static final String CURRPERM = "currPerm";

public static final String TASK_EXECUTOR = "taskExecutor";

public static final String DELIMITER = "delimiter";

public static final String OPERNAME = "operName";

}

currParams.remove(varStr);

currParams.remove(index);

currParams.remove(index+"_");

}

}

附上pom文件

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

4.0.0

com.rd

parser

jar

1.0-SNAPSHOT

myparser

http://maven.apache.org

dom4j

dom4j

1.6.1

opensymphony

ognl

2.6.11

commons-collections

commons-collections

3.2.1

commons-lang

commons-lang

2.6

junit

junit

3.8.1

test

src/main/java

**/*.xml

src/main/resources

**/*

${project.basedir}/src/test/java

${project.basedir}/src/test/resources

org.apache.maven.plugins

maven-compiler-plugin

3.1

1.8

1.8

UTF-8

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

4.0.0

com.rd

parser

jar

1.0-SNAPSHOT

myparser

http://maven.apache.org

dom4j

dom4j

1.6.1

opensymphony

ognl

2.6.11

commons-collections

commons-collections

3.2.1

commons-lang

commons-lang

2.6

junit

junit

3.8.1

test

src/main/java

**/*.xml

src/main/resources

**/*

${project.basedir}/src/test/java

${project.basedir}/src/test/resources

org.apache.maven.plugins

maven-compiler-plugin

3.1

1.8

1.8

UTF-8


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Springboot网站第三方登录 微信登录
下一篇:api接口文档抓包(抓包获取api)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~