java自定义动态解析xml文件(xml内部支持java逻辑运算符,支持js运算符以及表达式)。

w3cdomsql使用说明:
1:只能解析xml文件
2:只能解析标签cfj、model、sql、java、js 五个标签(所有标签都是自定义,可以自行更改)
标签说明:cfj标签相当于mybatis中的mapping
         model为模块 必须配置属性id
         sql为对应的与数据库交互的sql配置  必须配置id
         java表示配置的字符串将以java进行编译并返回结果(注:java 里面不能有反斜杠转义字符,循环最好只用while for循环只支持for in ,
                                                         也不支持++,+=,-+,--,等逻辑运算,其他海待测试)
         js表示配置的字符串将以javasrcipt进行编译运算并返回结果

  3.参数传递:参数传递方式:#{wyid}且只支持这种方式     

4.优缺点:缺点1.由于是动态解析因此如果数据量大解析较慢,

                        2.java代码逻辑支持率不高尽量不要在内部写逻辑,

                        3.js代码逻辑支持率较高尽量采用js代码

                 优点:1.项目不用搭建mybatis框架

                            2.更改xml文件后不需要重启服务器,连前端都不需要重新刷新

                            3.所有东西都是自行定义,好理解便于维护,并且可适用于所有框架以及模块。   

<?xml version="1.0" encoding="UTF-8" ?>
        <!--xml文件示例 java  循环只支持while循环 for循环支持率不高 慎用-->
<cfj>
    <model id="fbdw">
        <sql id="fbdw_info">
        select * from fbdw_info where 1=1
        <java>
            if(zjsl==3){
             sql.append("and zjsl=3 and wyid=#{wyid} and wyid=#{wyid} and wyid= # { wyid }");
            }else{
            sql.append("and zjsl!=3 wyid=#{wyid} and wyid=#{wyid} and wyid= # { wyid }");
            }
        </java>
            <js>
                if(zjsl==3){
                 sql+="and zjsl='3' and wyid=#{wyid} and wyid=#{wyid} and wyid= # { wyid }";
                }else{
                  sql+="and zjsl!='3' and wyid=#{wyid} and wyid=#{wyid} and wyid= # { wyid }";
                }
            </js>
        </sql>
    </model>
</cfj>
效果效果package cfjsf.util.w3cdom;

import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.MapContext;
import org.w3c.dom.*;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.Map;

/**
 * Created by 常发均 on 2019/8/7.
 * xml文件动态生成sql解析工具类(脱离于mabatis框架,更改xml文件后不需要重启服务器,并且支持内部java代码以及js代码以及逻辑运算)
 */
public class XmlDynamicParseToSql {
   public static String xmlSql(File file,String modelId,String sqlId,Map<String,Object> params) throws Exception {
       DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
       DocumentBuilder db = dbf.newDocumentBuilder();
       Document doc = db.parse(file);
       //获得根元素结点
       Element root = doc.getDocumentElement();
       return parseGcgs(root,modelId,sqlId,params);
   }
   private static String parseGcgs(Element element,String modelId,String sqlId,Map<String,Object> params) throws Exception {
       StringBuffer dtSql=new StringBuffer("");
       parseElementGcgs(element, modelId,sqlId,dtSql,params);
       return dtSql.toString();
   }
    private static void parseElementGcgs(Element element,String modelId,String sqlId,StringBuffer dtSql,Map<String,Object> params) throws Exception {
        String tagName = element.getNodeName();
        if(!(tagName.equals("cfj")||tagName.equals("java")||tagName.equals("js")||tagName.equals("model")||tagName.equals("sql"))){
            throw new Exception("this targetName count no found!");
        }
        boolean flag=true;
        if(tagName.equals("model")||tagName.equals("sql")){
            flag=false;
        }
        NodeList children = element.getChildNodes();
        //element元素的所有属性所构成的NamedNodeMap对象,需要对其进行判断
        NamedNodeMap map = element.getAttributes();
        //如果该元素存在属性
        /*
        * 后面已经有判断 主要是担心认为操作失误 且第一个节点就为目标节点 判断不到
        * 因此再次采用多重判断
        * */
        if(null != map)
        {
            for(int i = 0; i < map.getLength(); i++)
            {
                //获得该元素的每一个属性
                Attr attr = (Attr)map.item(i);
                String attrName = attr.getName();
                String attrValue = attr.getValue();
                if(attrName.equals("id")){
                    if(tagName.equals("model")&&attrValue.equals(modelId)){
                        flag=true;
                    }else if(tagName.equals("sql")&&attrValue.equals(sqlId)){
                        flag=true;
                    }
                }
            }
        }
       if(flag){
           for(int i = 0; i < children.getLength(); i++)
           {
               Node node = children.item(i);
               int a=0;//默认a等于0 表示节点名称不为model与sql的节点需继续所有节点递归 a等于1表示还未找到目标节点需跳出循环继续寻找 a等于2 表示已找到目标节点
              /*
               * 判断是否找到当前所需节点 找到就结束循环
               * */
               if(node.getNodeName().equals("model")){
                   if(isMbNode((Element) node,"model",modelId)){
                       a=2;
                   }else{
                       a=1;
                       continue;
                   }
               }  else if(node.getNodeName().equals("sql")){
                   if(isMbNode((Element) node,"sql",sqlId)){
                       a=2;
                   }else{
                       a=1;
                       continue;
                   }
               }
               //获得结点的类型
               short nodeType = node.getNodeType();
               if(nodeType == Node.ELEMENT_NODE)
               {
                   //递归出口
                   /*
                   * sql节点下只能含有java与js节点  方便解析
                   *
                   * */
                   if(tagName.equals("sql")){
                       if(node.getNodeName().equals("java")||node.getNodeName().equals("js")){
                           //是元素,继续递归
                           parseElementGcgs((Element)node,modelId,sqlId,dtSql,params);
                       }else{
                           throw new Exception("sql标签中只能含有java或者js标签!");
                       }
                   }
                   else{
                       parseElementGcgs((Element)node,modelId,sqlId,dtSql,params);
                   }
               }
               else if(nodeType == Node.TEXT_NODE)
               {
                   //递归出口
                   if(tagName.equals("sql")){
                       dtSql.append(node.getNodeValue().trim());
                       dtSql.append(" ");
                   }
                   else if(tagName.equals("java")){
                       dtSql.append(dtjxJava(node.getNodeValue().trim(),params));
                       dtSql.append(" ");
                   }
                   else if(tagName.equals("js")){
                       dtSql.append(dtjxJs(node.getNodeValue().trim(), params));
                       dtSql.append(" ");
                   }
                   /*
                   * 替换掉所有的参数 参数方式采用#{}
                   * */
                   if(dtSql.toString().indexOf("#")>-1){
                       String[] arr=dtSql.toString().split("\\#");
                       String str="";
                       int length=dtSql.toString().length();
                       for(int j=arr.length-1;j>=1;j--){
                           length=length-arr[j].length()-1;
                           if(arr[j].indexOf("{")>-1&&arr[j].indexOf("}")>arr[j].indexOf("{")+1){
                               str=arr[j].substring(arr[j].indexOf("{")+1,arr[j].indexOf("}"));
                               if(params.containsKey(str.trim())){
                                   dtSql.replace(length,length+arr[j].indexOf("}")+2,"'"+params.get(str.trim()).toString()+"'");
                               }else{
                                   throw new Exception("找不到参数"+str.trim()+"!");
                               }
                           }
                       }
                   }
               }
               else if(nodeType == Node.COMMENT_NODE)
               {
                   Comment comment = (Comment)node;
                   //注释内容
                   String data = comment.getData();
               }
               if(a==2){
                   break;
               }
           }
       }
    }
    /*
    * 将字符串通过java进行动态编译并返回计算结果
    * 采用jexl进行解析
    * */
    private static String dtjxJava(String javaStr,Map<String,Object> params){
        JexlEngine jexl=new JexlEngine();
        JexlContext jc = new MapContext();
        for(String key:params.keySet()){
            jc.set(key,params.get(key));
        }
        jc.set("sql",new StringBuffer(""));
        Expression e = jexl.createExpression(javaStr);
        if(null==e.evaluate(jc)){
            return "";
        }else{
            return jc.get("sql").toString().trim();
        }
    }
    /*
    * 将字符串通过javasricpt进行动态编译并返回计算结果
    * */
   private static String dtjxJs(String jsSr,Map<String,Object> params){
       ScriptEngineManager manager = new ScriptEngineManager();
       ScriptEngine engine = manager.getEngineByName("javascript");
       for(String key:params.keySet()){
           engine.put(key, params.get(key));
       }
       engine.put("sql","");
       try {
           engine.eval(jsSr);
           return engine.get("sql").toString().trim();
       } catch (ScriptException e) {
           e.printStackTrace();
       }
       return "";
   }
     /*
    * 判断id是否相同
    * */
    private static boolean isMbNode(Element node,String nodeName,String nodeValue) throws Exception {
        if(node.getNodeName().equals(nodeName)){
            NamedNodeMap idNodeMap = node.getAttributes();
            if(null!=idNodeMap){
                try {
                    Attr attr=(Attr)idNodeMap.getNamedItem("id");
                    if(attr.getValue().equals(nodeValue)){
                      return true;
                    }
                }catch (Exception e){
                    throw new Exception("请对该节点配置id属性!");
                }
            }else{
                throw new Exception("请对该节点配置id属性!");
            }
        }
       return false;
    }
 }


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值