码迷,mamicode.com
首页 > 其他好文 > 详细

正式推荐我的一个开源项目2-自定义编译器

时间:2015-09-15 15:06:48      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:

在项目里面有时有这样的场景,我们需要一个权限表来控制权限,当满足权限表条件时,阻止用户操作并返回错误信息,表的结构类似:

技术分享

这时有一种传统方式是,我们用mybatis之类的工具,写一段sql,每次用这段sql校验权限:

SELECT * from permission_test where `condition1` = #{condition1} and `condition2` = #{condition2}


另外一种方式是,我们将table编译为一段可执行代码,然后每次执行这段代码,这段代码类似:

技术分享

那么这2种方式的效率相差多大呢,楼主写了一段测试代码:

技术分享

执行结果是,compiledtester的执行时间总是1ms,而sqltester的执行时间则在800ms左右。

那么,compiledtester是怎么生成的呢?本文将简单介绍这个生成机制。

本文用到了楼主的开源项目 autogrammerhttp://git.oschina.net/notebook

它的jar包可以在published项目下面下载到。

本文所用主要代码可以在这里 http://www.oschina.net/code/snippet_573815_50916 看到

首先有一个接口类 DBDataTester 这个类里面有2种实现,一种是传统的数据库实现SqlDataTester,另外一种是编译为java代码 DBDataTesterImpl 类的实现。

主要编译代码

技术分享

我们的思路是,从数据库里面把所有的record读取出来,然后利用autogrammer提供的功能编译这些record,最终生成目标代码。

编译java代码相关的知识你可以从这篇文章里面学到:

http://www.oschina.net/code/snippet_573815_50891

我们从数据库里面读取的record可以看作如下语句:

condition (name:"condition1", data:"condition1-1")

condition (name:"condition2", data:"condition1-2")

end (data: "错误数据1")

......

第一步:autogrammer要实现自定义编译器,首先需要你定义语法。代码中文法放在 yp/published/grammer/Grammer.txt 中:

技术分享

其中,第三句表示,一个condition可以规约为一个conditionlist

第二句表示,一个conditionlist 和 condition 可以规约为一个 conditionlist 

这样我们的文法就支持condition的无线罗列了

第一句表示,当遇到一个end时,表明当前句子结束(类似于编程语句中的;)此时会对整个句子进行编译,生成一段代码

类似:

        if ("condition1-1".equals(data.getCondition1()) && "condition2-1".equals(data.getCondition2())) {

            return "错误数据1";

        }

第二步:有了文法以后,我们就需要一个词法分析器,这个词法分析器可以从数据库中读取数据,然后转化为文法中所对应的token流。

词法分析器需要继承,并实现TokenReader接口

public class DBTokenReader implements TokenReader

它的关键代码在这里:

技术分享

技术分享

第三步,我们需要针对我们定义的语法注册处理函数

public class ConditionHandler extends DefaultExecuteHandler 

注册编译最开始的初始化函数:主要初始化ExecutePram

技术分享

注册编译结束的函数:这里利用ExecuteParam 编译最终实现类DBDataTesterImpl

技术分享

注册各个规约语句的处理函数

处理函数中,tokenWordList为一个List<TokenWord>, 里面的成员就是 "->" 左边的值(condition),

originalWord为 "->" 右边的值(conditionlist)。每一个tokenWord都有一个Object data成员可以放入自定义对象。

paramContext则是本次编译执行的参数。 

技术分享

最后,当我们凑齐了 语法文件,词法分析器,以及相关handler之后,就可以进行编译过程。在主要编译代码中,我们可以看到首先我们根据语法文件生成一个StateTable,然后生成自己的TokenReader,ExecuteHandler,最终利用3者生成一个ExecuteContext并且执行编译的过程。

再次贴出链接:

主要代码:http://www.oschina.net/code/snippet_573815_50916

编译java代码相关介绍: http://www.oschina.net/code/snippet_573815_50891

项目地址:http://git.oschina.net/notebook

其中本项目用到的是autogrammer,jar包在published项目下面。





正式推荐我的一个开源项目2-自定义编译器

标签:

原文地址:http://my.oschina.net/HaFoLuoKe/blog/506310

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!