<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    如鵬網 大學生計算機學習社區

    CowNew開源團隊

    http://www.cownew.com 郵件請聯系 about521 at 163.com

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      363 隨筆 :: 2 文章 :: 808 評論 :: 0 Trackbacks

    #

    作者楊中科

    CowNew 開源團隊網站 http://www.cownew.com

    論壇 http://www.cownew.com/newpeng/?

    轉載請保留此信息

    一、HQL代碼的構建。
    (1)首先將hibernate中的src目錄下的代碼解壓。
    (2)安裝配置好antlr。
    (3)把grammar目錄下的三個.g文件(hql.g,hql-sql.g,sql-gen.g)解壓到一個目錄,然后從命令行進入此目錄,依次運行"java antlr.Tool hql.g","java antlr.Tool hql-sql.g","java antlr.Tool sql-gen.g",將生成的java代碼拷貝到源代碼的org.hibernate.hql.antlr下。
    二、讓我們從QueryTranslatorImpl開始分析,當調用session.find('...')的時候將會調用QueryTranslatorImpl的compile方法來解析hql語句為sql語句。compile則主要是調用的doCompile方法。
    // PHASE 1 : Parse the HQL into an AST.
    HqlParser parser = parse( true );

    // PHASE 2 : Analyze the HQL AST, and produce an SQL AST.
    HqlSqlWalker w = analyze( parser, collectionRole );
    sqlAst = ( Statement ) w.getAST();
    generate( ( QueryNode ) sqlAst );
    queryLoader = new QueryLoader( this, factory, w.getSelectClause() );

    parse的主要代碼:
    private HqlParser parse(boolean filter)
    ?HqlParser parser = HqlParser.getInstance( hql );
    ?parser.statement();
    ?AST hqlAst = parser.getAST();
    ??return parser;
    }
    analyze的主要代碼:
    private HqlSqlWalker analyze(HqlParser parser, String collectionRole) throws QueryException, RecognitionException {
    ?HqlSqlWalker w = new HqlSqlWalker( this, factory, parser, tokenReplacements, collectionRole );
    ?AST hqlAst = parser.getAST();
    ?w.statement( hqlAst );
    ?return w;
    }
    generate的主要代碼:
    private void generate(AST sqlAst) throws QueryException, RecognitionException {
    ?SqlGenerator gen = new SqlGenerator(factory);
    ?gen.statement( sqlAst );
    ?sql = gen.getSQL();
    }

    可以看到主要是三步:調用parse方法將hql解析成AST,調用analyze根據上一步生成的AST生成SQLAST,調用generate根據上一步生成的SQL AST生成sql語句, 調用w.getSelectClause()就得到sql語句了。
    “用parser把ast抽取出來,再用treeparser進行動作的double pass builder模式,解耦了parser和generation,再配合template,是antlr推薦的最佳模式?!保犊碒ibernate3如何解釋HQL語言》
    1、三個語法文件的作用:

    hibernate的hql grammar文件一共有三個,在/grammar目錄下:
    ?? 1.hql.g?? 定義token類和parser類,將hql解釋成hql的抽象語法樹(ast)
    ?? 2.hql-sql.g? 定義tree walker ,將hql ast轉化為sql ast,將生成模塊與hibernate解耦。
    ?? 3.sql-gen.g 定義tree walker,從sql ast生成sql
    ”-《看Hibernate3如何解釋HQL語言》
    2、
    逐步分析:
    (1)parse方法:
    HqlParser是從hql.g生成的HqlBaseParser繼承來的,主要實現了HqlBaseParser定義的幾個模版方法,傳入的是hql語句,傳出的是HQL AST。
    (2)analyze:
    HqlSqlWalker是從hql-sql.g生成的HqlSqlBaseWalker繼承來的,HqlSqlBaseWalker又是從TreeParser繼承的,主要實現了HqlSqlBaseWalker定義的幾個模版方法,傳入的是HQL AST,傳出的是SQL AST。
    hql-sql.g比hql.g簡單許多了,因為hql-sql.g已經為我們生成了HQL AST了,hql-sql.g需要做的就是把HQL AST組裝成強類型的SQL AST,此處大量引用了hql.g中定義的Vocabulary。
    比如:
    query!
    ?: #( QUERY { beforeStatement( "select", SELECT ); }
    ???// The first phase places the FROM first to make processing the SELECT simpler.
    ???#(SELECT_FROM
    ????f:fromClause
    ????(s:selectClause)?
    ???)
    ???(w:whereClause)?
    ???(g:groupClause)?
    ???(o:orderClause)?
    ??) {
    ??// Antlr note: #x_in refers to the input AST, #x refers to the output AST
    ??#query = #([SELECT,"SELECT"], #s, #f, #w, #g, #o);
    ??beforeStatementCompletion( "select" );
    ??processQuery( #s, #query );
    ??afterStatementCompletion( "select" );
    ?}
    ?;
    這里主要就是在調用模版方法拼狀強類型的SQL AST(異構AST)。所有的節點都定義在org.hibernate.hql.ast.tree中。
    與第一部的HqlParser用戶幾乎不用寫任何代碼相反,我們需要完成我們從HqlSqlBaseWalker繼承來的HqlSqlWalker的那些模版方法。
    (3)generate方法:
    遍歷SQL AST,輸出sql語句。SqlGenerator是從sql-gen.g生成的SqlGeneratorBase繼承來的。輸入的是SQL AST,輸出的是SQL語句。我個人認為這一步也可以通過全部書寫代碼完成,可能更清晰,更靈活。
    selectExpr
    ?: e:selectAtom { out(e); }
    ?| count
    ?| #(CONSTRUCTOR (DOT | IDENT) ( selectColumn )+ )
    ?| methodCall
    ?| aggregate
    ?| c:constant { out(c); }
    ?| arithmeticExpr
    ?| PARAM { out("?"); }
    ?| sn:SQL_NODE { out(sn); }
    ?| { out("("); } selectStatement { out(")"); }
    其中的out("(");就是在拼裝代碼。

    posted @ 2006-06-02 00:56 CowNew開源團隊 閱讀(4975) | 評論 (2)編輯 收藏

    ??? 初涉開源已經一個月了,和Huihoo、SpringSide、EasyJF這樣的“老大哥”比起來還稚嫩的很。但是在這一個月中也體會到了酸甜苦辣。
    ?? 開源是需要雷鋒精神的?!皶r間就像海綿里的水,只要愿意擠,總還是有的?!?(有人說這句話是魯迅說得,我沒時間去考證了)。哪怕公司的工作加班到了10點,回來還是可以為開源忙上一個小時的,不要給任何自己不要為之奮斗的理由,只要要求自己每天都為開源做一點事情,相信會有回報的。
    ??? 開源是孤獨的,特別是在中國。太多的人為了二斗米去奮斗,并以此給自己一個自己很忙,自己沒時間做開源的借口;太多的人認為開源是在為別人賣苦力,自己是傻大個;太多了人站在少數幾個開源者的旁邊,象看耍猴子一樣看熱鬧了;太多的人希望鉆進一個開源團隊,然后什么事情都不做,等著坐收漁利了;太多了人還沒開始做就想著項目商業運營之后到底能賺多少錢了。。。。。。
    ??? 開源是需要付出的。女朋友又想你了,你去不去?哥們又要你出去喝酒了,你去不去?周末朋友們又去蹦迪了,你去不去?開源有可能是付出了N多精力,卻無利可圖的,你干不干?。。。。。。
    ??? 開源是勞累的。忙完了白天的工作,晚上回來還要寫代碼;但別人都進入夢鄉的時候,你卻在為一個自己為自己分配的開源任務而奮斗。。。。。。??
    ??? 開源是需要鉆研精神的。開源一般做的都是業界先進的技術,能夠參考的資料很少。你不能夠要求做開源的時候還有那么多被前仆后繼的編碼員都寫臭了街的所謂“××信息系統”的代碼可以參考。更多的需要自己去鉆研:鉆研國外的資料,與同行的高手共同探討,甚至要自己獨創一套東西。創新是開源的一個重要特征。這也決定了做開源的最終都會成為精英。
    ??? 開源是需要腳踏實地的。那些希望今天做開源明天就能成名發財的人是必將失敗的。安下心來,低下頭來,走好腳下的每一步,相信成功就一定會在前方等著你。
    ??? 開源是為自己在努力的。開源項目中沒有老板,項目發起人也只是個組織者,你不是在為他工作,你是在為自己的明天奮斗。開源中付出多的就是老大。不要抱怨項目組織者今后一定會比普通的隊友成功,你來努力呀,你的成績你的付出超過他,你就是老大。記?。洪_源是為自己奮斗,那些認為是在為別人賣苦力的人還是回到公司,老老實實當你的小職員吧。
    ???
    ??? CowNew團隊過程中我們遇到了很多兢兢業業的朋友。項目經驗豐富的BadBoy,為了做團隊網站差點累出病來的土豆,經常為了SQL解析引擎而忙到凌晨2點的KingChou,為項目管理獻計獻策的Andrew、霉干菜,為產品書寫介紹文檔驗證bug的月光光、c2,經驗豐富的Sephil,還有積極關注團隊發展的孤獨河馬、滾來滾去、熱血年華、宋笑癡、foxKnit等等朋友。EasyJF的大峽、船長也給我們提出了很多建議。有了他們才有了CowNew的現在。
    ??? 問題是很多的?,F在JDBMonitor和SQL解析引擎組已經正常運作了。原先策劃的MDA、進銷存組由于大家缺少大型項目的遠程協同能力,所以不得不暫時進行合并轉型為技術預研組。現在由孤獨河馬全權負責這個項目組的管理運營,希望他能帶領大家走出一條新路。前期花了太多的時間在討論團隊的建設問題,在曉之以理動之以情的給一些兄弟講開源的真諦,在為了能找到一個開發組負責人而游說各個成員。。。。。。浪費的時間太多了,干活的時間太少了,發的所謂“條例”太多了,但是卻缺乏實行這些“條例”的基本條件。所以以后在qq群里、在論壇上不會出現太多關于團隊發展的討論,不會再出現那些“管理條例”,不會再要求大家推薦帶頭人。團隊的發展是只有真正跑起來才知道的,如果連事情都沒做談什么發展;“管理條例”是需要以后慢慢探索的,帶頭人也會在今后的項目中浮山水面的。不能適應、不能理解開源的朋友還是退出團隊吧,有更多更合適其他機會等著你。所以今后CowNew不會再有“討論”、“決議”,有的只是技術交流,有的只是干活,just do it!
    ???
    ?? 開源路漫漫,志同道合者更是少之又少,惟愿同路者以此句共勉“向雷鋒同志學習”。
    -----------------------------------
    CowNew開源團隊
    官方網站:http://www.cownew.com
    論壇:http://www.cownew.com/newpeng/
    posted @ 2006-05-30 01:31 CowNew開源團隊 閱讀(1211) | 評論 (7)編輯 收藏

    把JDBMonitor嵌入到poolman上面是有很大的實用意義的,這樣我們可以做成一個完整的數據庫連接和數據庫訪問的監控.

    JDBMonitor和poolman一樣都是非入侵性的,所以用起來很簡單,這里我說一下用法:

    在安裝好poolman后,建立連接如下

    // load the PoolMan JDBC Driver
    ??????????

    Class.forName("com.codestudio.sql.PoolMan").newInstance();

    Connection con = DriverManager.getConnection("jdbc:poolman");

    再配置poolman.xml

    ?? <?xml version="1.0" encoding="UTF-8"?>
    ?????? <poolman>
    ????????? <datasource>
    ???????????? <dbname>default</dbname>
    ???????????? <jndiName>default</jndiName>
    ??????????? <driver>com.cownew.JDBMonitor.jdbc.DBDriver</driver>
    ??????????? <url>listenerconfig=c:/config.xml:url=jdbc:oracle:thin:@localhost:1521:Database</url>
    ??????????? <username>user</username>
    ??????????? <password>code</password>

    ??????????? <logfile>c:/test.txt</logfle>

    ?????? </datasource>

    ???? </poolman>

    再配置好JDBMonitor,就完成了JDBMonitor和poolman的結合

    工程向poolman(連接池)申請連接,poolman再向JDBMonitor申請連接,并生成連接日志

    poolman負責連接池的維護,當工程執行數據庫訪問,JDBMonitor將記錄數據訪問日志,

    這樣我們就可以完全監控數據庫的連接和訪問了
    作者月光光是CowNew開源團隊(www.cownew.com)JDBMonitor開發組、SQL解析引擎開發組的主力開發人員。
    更多內容請見CowNew開源團隊網站 www.cownew.com
    論壇 http://www.cownew.com/newpeng/

    posted @ 2006-05-29 00:57 CowNew開源團隊 閱讀(1094) | 評論 (0)編輯 收藏

    今天做了個executeBatch的例子,可是輸的結果卻出乎我的意料,如下

    begintime:2006-05-25 09:58:11.0
    endtime:2006-05-25 09:58:11.14
    sqlType:executeBatch
    sql:insert into tmm_bill (billname, billdesc) values (?, ?);insert into tmm_bill (billname, billdesc) values (?, ?);
    paramters:[1, 2]

    為什么輸出的是兩個語句,而只有一組參數呢,于是我決定一探究竟.

    下面是我的例子

    ?? conn = DriverManager
    ???? .getConnection("listenerconfig=/com/cownew/JDBMonitor/demo/oracleconfig.xml:url=jdbc:oracle:thin:@zbw:1521:xinem8gg", "m8connect", "m8connect");
    ?? //for (int i = 0; i < 10; i++)
    ?? //{

    ??? ps = conn
    ????? .prepareStatement("insert into tmm_bill (billname, billdesc) values (?, ?)");
    ???
    ??? ps.setString(1,"songzho");
    ??? ps.setString(2, "yufn");
    ???
    ??? ps.addBatch();
    ???
    ??? ps.setString(1, "2");
    ??? ps.setString(2, "3");
    ???
    ??? ps.addBatch();
    ???
    ???
    ??? ps.executeBatch();
    ??? ps.close();

    原來我們輸出的內容封裝在SQLInfo這個類中

    這個類中有一個get和set方法用來取值和付值,這個我就不多介紹了,主要說一下其中一個方法

    private List parameters = new ArrayList();

    ?public List getParameters()
    ?{
    ? return parameters;
    ?}

    public String toString()
    ?{
    ? StringBuffer sb = new StringBuffer();
    ? sb.append("begintime:").append(beginTime).append("\n");//設置開始執行語句的時間
    ? sb.append("endtime:").append(endTime).append("\n");//設置結束執行語句的時間
    ? sb.append("sqlType:").append(sqlType).append("\n");//設置語句的類型
    ? sb.append("sql:").append(sql).append("\n");//設置語句
    ? if(parameters.size()>0)
    ? {
    ????? sb.append("paramters:").append(parameters).append("\n");//設置參數,就是這里有點問題
    ? }
    ? return sb.toString();
    ?}

    在這里大家可以看出來parameters就是用來傳入參數的arrayList,可是這里只能存一組參數;

    我們再看一下 DBPreparedStatement 這個類,這個類的意義也不用多說了吧,主要看看兩個方法

    ?public int[] executeBatch() throws SQLException
    ?{
    ? SQLInfo info = new SQLInfo();
    ? info.setSqlType(SQLTypeEnum.executeBatch);//SQLInfo類設置SqlType的方法
    ? info.setBeginTime(JdbcUtils.getTimeStamp());//SQLInfo類設置BeginTime的方法
    ? info.setSql(sbAddBatch.toString());//SQLInfo類設置Sql的方法,sbAddBatch是一個StringBuffer

    ? int[] ret = stmt.executeBatch();

    ? info.setEndTime(JdbcUtils.getTimeStamp()); ());//SQLInfo類設置EndTime的方法
    ?
    ? if (params != null && paramCount != 0)//這里是設置參數的地方,就是這里出了一點問題,params只是保存一組參數,也就是最后一組
    ????????? //對于只有一組參數是沒有問題的,可是如果有多組參數就會出現上面我說的那個現象了
    ? {
    ?? int i = 0;
    ?? for (int size = paramCount; i < size; i++)
    ??? info.getParameters().add(params[i]);
    ? }
    ? logSql(info);
    ? sbAddBatch.setLength(0);
    ? return ret;
    ?}

    我改動的方法是這樣的
    private ArrayList paramsList = new ArrayList();
    public class DBPreparedStatement extends DBStatement implements
    ??PreparedStatement
    {
    ?.
    ?.
    ?.
    ?public void addBatch() throws SQLException
    ?{
    ??//sbAddBatch.append(sql).append(";");
    ???? ArrayList pListTemp = new ArrayList();
    ???? for (int i = 0; i < paramCount; i ++)
    ???? {
    ???????? pListTemp.add(params[i]);//把每一組參數存到一個ArrayList里面
    ???? }
    ????
    ???? paramsList.add(pListTemp);//再把那個臨時的TempList存到一個ArrayList里面

    ??
    ??((PreparedStatement) stmt).addBatch();

    ?}

    ?.
    ?public int[] executeBatch() throws SQLException
    ?{
    ??
    ???? sbAddBatch.append(sql);
    ????
    ???? SQLInfo info = new SQLInfo();
    ??info.setSqlType(SQLTypeEnum.executeBatch);
    ??info.setBeginTime(JdbcUtils.getTimeStamp());
    ??info.setSql(sbAddBatch.toString());

    ??int[] ret = stmt.executeBatch();

    ??info.setEndTime(JdbcUtils.getTimeStamp());??
    ??
    ??if (paramsList != null && paramsList.size() != 0)
    ??{
    ???for (int i = 0; i < paramsList.size(); i ++)
    ???{
    ?????? info.getParameters().add(paramsList.get(i));//取到每一個TempList
    ???}

    ?????
    ??}
    ??logSql(info);
    ??sbAddBatch.setLength(0);
    ??return ret;
    ?}
    ?.
    ?.
    ?.
    }
    public class SQLInfo implements Serializable
    {
    ?.
    ?.
    ?.
    ?public String toString()
    ?{
    ??StringBuffer sb = new StringBuffer();
    ??sb.append("begintime:").append(beginTime).append("\n");
    ??sb.append("endtime:").append(endTime).append("\n");
    ??sb.append("sqlType:").append(sqlType).append("\n");
    ??sb.append("sql:").append(sql).append("\n");
    ??if(parameters.size()>0)
    ??{
    ????? for (int i = 0; i < parameters.size(); i ++)
    ????? {
    ????????? sb.append("paramters:").append((ArrayList)parameters.get(i)).append("\n");//循環取TempList里的參數
    ????? }

    ??}
    ??return sb.toString();
    ?}
    }
    得到的結果為
    begintime:2006-05-25 13:16:00.218
    endtime:2006-05-25 13:16:00.234
    sqlType:executeBatch
    sql:insert into tmm_bill (billname, billdesc) values (?, ?)
    paramters:[songzho, yufn]
    paramters:[2, 3]

    也不知道各位看官看明白了沒有,其實不懂也沒什么關系,我只是想在這里給大家說一下我們輸出方式,總結一下就是我們做了自己的DBConnect,DBStatetment,
    DBPrepareStatement....,都是繼承了JDBC的原型,在實現這些功能的之前,先把信息記錄在SqlInfo里,再跟據配置的寫日志方式進行寫日志.
    作者月光光是CowNew開源團隊(http://www.cownew.com)JDBMonitor開發組的核心開發人員,在J2EE開發方面頗有造詣。

    posted @ 2006-05-27 01:46 CowNew開源團隊 閱讀(1251) | 評論 (0)編輯 收藏

    這個題目其實有點大了,其實說的問題很小。
    大家都說java是跨平臺的,可是用java寫出來的代碼能不能真正的跨平臺還是要開發人員來把握。
    我今天在CSDN上看到一位朋友給JDBMonitor提出的一條bug:
    "如果我的系統是linux,那個listenerconfig=就難寫了,因為我要是寫成/root/什么的,他會認為是classpath,實際上這是個物理路徑,期待改進"
    因為在上一個小版本中,我為了同時適應用戶通過類路徑指定配置文件的位置,比如,com/cownew/config.xml,也能通過真實的文件路徑制定文件的位置,比如c:/config.xml
    所以我就要判斷用戶給出的路徑是類路徑還是文件路徑,我的實現方式是判斷路徑是否以a-z的字母開頭,并且后邊跟著":/",如果是,則為文件路徑,否則為類路徑。
    但是在unix(linux)下,絕對路徑則是/root/cfg/config.xml的形式,我就給誤判斷成是類路徑了。這樣在這些平臺下就報錯了,我采用如下方式解決:
    JDBMonitor會首先把<configfilepath>當成類路徑去讀取,如果讀取失敗再把它當作文件路徑去讀,例如如果您設定/root/cfg/config.xml,本意是想加載文件路徑/root/cfg/下的文件config.xml,但是如果您的類路徑中有root.cfg這個包,并且包下同樣有config.xml這個文件,那么JDBMonitor會去讀root.cfg中的文件config.xml,而非/root/cfg/config.xml。
    示意代碼如下:
    InputStream is = null;
    is = this.getClass().getResourceAsStream(configFile);
    if(is==null)
    {
    ?? try
    ?{
    ??is = new FileInputStream(configFile);
    ?} catch (FileNotFoundException e)
    ?{
    ??is = null;
    ?}
    }

    不知道有沒有更好的辦法解決,請高手指教。有時間也去看看那些tomcat之類的服務器是怎么解決這個問題的。
    JDBMonitor最強大的無侵入式數據庫監控、日志工具。
    COWNEW團隊,最專業的開源團隊!官方網站:
    www.cownew.com

    posted @ 2006-05-25 01:39 CowNew開源團隊 閱讀(917) | 評論 (3)編輯 收藏

    JDBMonitor(可以從www.cownew.com下載)是一個非常強大的數據庫監控、日志工具,它的無侵入性是它最大的特點。所謂無侵入性指的是無需編寫代碼就可以為系統增加數據日監控、日志功能。那么它到底是怎么實現的呢?咱們來探索一下它的基本原理。
    要明白JDBMonitor的工作原理,必須首先弄明白JDBC驅動的工作原理:
    所有的JDBC驅動都實現java.sql.Driver接口,此接口有兩個重要方法:Connection connect(String url, java.util.Properties info),boolean acceptsURL(String url)。
    JDBC中有個DriverManager類,它有一個重要方法,
    registerDriver(java.sql.Driver driver)
    所有的JDBC驅動都要調用此方法,這樣才能將注冊到驅動管理器中。
    當用戶調用DriverManager.getConnection("jdbc:......")的時候,DriverManager就把用戶穿過來的連接字符串“jdbc:......”發給每個注冊的驅動Driver的acceptsURL方法做為參數,驅動Driver就調用這個Driver的connect方法然后將方法的返回值直接做為自己的返回值。
    更詳細的解釋請查看JDBC的JavaDoc,或者參考如下文章:http://www.cntopedu.cn/cntopedu_html_itxuetang/200562963708.asp


    JDBMonitor寫了自己的JDBCDriver:DBDriver,這個DBDriver識別所有以listenerconfig=開頭的jdbc連接字符串,這樣如果您修改了您系統的JDBC連接字符串并添加listenerconfig=等部分以后,此url就不會被您原來的JDBC驅動認識,耳反而被DBDriver認識,這樣每次的數據庫連接調用也都通過DBDriver以及相關的類來進行(比如DBPreparedStatement等),這些類首先先把通過的數據庫調用記錄下來,然后再轉發給真正的數據庫驅動,這樣就達到了攔截任何JDBC調用的目的。更相信內容,請參考com.cownew.JDBMonitor.jdbc包下的DBDriver、DBConnection、DBStatement、DBPreparedStatement等類。這些類采用了代理模式、裝飾者模式等設計模式,使得程序的可擴展性得到很大的提升。

    COWNEW團隊,最專業的開源團隊!官方網站: www.cownew.com

    posted @ 2006-05-24 02:20 CowNew開源團隊 閱讀(944) | 評論 (1)編輯 收藏

    一、 Antlr 的主要類:

    Antlr 中有主要類有兩種(其實還有一種 TreeLexer

    Lexer: 文法分析器類。主要用于把讀入的字節流根據規則分段。既把長面條根據你要的尺寸切成一段一段:)并不對其作任何修改。

    Parser: 解析器類。主要用于處理經過 Lexer 處理后的各段。一些具體的操作都在這里。

    二、 Antlr 文法文件形式:

    Antlr 文件是 *.g 形式,即以 g 為后綴名。

    例如: t.g

    class P extends Parser;

    startRule

    ??? :?? n:NAME

    ??????? {System.out.println("Hi there, "+n.getText());}

    ??? ;

    class L extends Lexer;

    // one-or-more letters followed by a newline

    NAME:?? ( 'a'..'z'|'A'..'Z' )+ NEWLINE

    ??? ;

    NEWLINE

    ??? :?? '\r' '\n'?? // DOS

    ??? |?? '\n'??????? // UNIX

    ;

    具體成分分析:

    1 、總體結構

    Class P extends Parser

    Class L extends Lexer

    兩行同 JAVA 繼承一樣, P 繼承 Parser 類; L 繼承 Lexer 類。每個 .g 文件只能各有一個。

    2 、 Lexer 類分析

    一般按照

    類型名:
    ????
    匹配的具體規則
    ????
    ;

    的形式構成。是分隔字節流的依據。同時可以看到里面可以互相引用。如本例中的類型名 NEWLINE 出現在 NEW 的匹配規則中。

    3 、 Parser 類分析

    一般按照

    起始規則名:

    ???????? 規則實例名:類型名或規則名

    ??????????????????????????? {Java 語句。。。; }

    ???????? ;

    ???????? 。。。。。。。。。

    的形式構成。

    起始規則名:任意。

    規則實例名:就象 Java 中“ String s ;”的 s 一樣。規則實例名用于在之后的 JAVA 語句中調用。

    類型名或規則名:可以是在 Lexer 中定義的類型名,也可以是 Parser 中定義的規則名。感覺就像是 int Integer 的區別。

    Java 語句:指當滿足當前規則時所執行的語句。 Antlr 會自動嵌入生成的 java 類中。

    ?

    ?

    ?

    三、生成 Java

    1 、從 www.antlr.org 上下載 antlr-x.x.x.jar

    2 、配置環境變量: classpath=.;x:\jdk\lib\tools.jar;x:\antlr-x.x.x.jar

    3 、在 t.g 所在目錄下執行:

    java antlr.Tool t.g

    會在當前目錄下生成如下文件:

    L.java Lexer 文法分析器 java 類。

    P.java Parser 解析器 java 類。

    PTokenTypes.java Lexer 中定義的類型具體化,供 Parser 解析器調用。

    PTokenTypes.txt :當外部的(如 t2.g )要調用當前的類型或規則時要用到本文件。

    ?

    ?

    ?

    四、執行

    1 、編寫 Main
    import java.io.*;
    ????? class Main {
    ?public static void main(String[] args) {

    try {


    L lexer = new L(new DataInputStream(System.in));
    P parser = new P(lexer); parser.startRule();
    } catch(Exception e)
    {
    System.err.println("exception: "+e);
    }


    ? }
    }

    2 、執行
    c:\> javac *.java
    c:\> java Main
    Terence
    ^Z
    Hi there, Terence
    c:\>

    本文作者kingchou是CowNew開源團隊SQL解析引擎項目組負責人。
    更多內容請見CowNew開源團隊網站
    www.cownew.com
    論壇 http://www.cownew.com/newpeng/

    posted @ 2006-05-23 02:22 CowNew開源團隊 閱讀(2219) | 評論 (2)編輯 收藏

    上午我試了下JDBMonitor(http://www.cownew.com),并閱讀了部分代碼
    我覺得想法挺好的,不過我也發現了一個BUG

    我試了下DEMO里面TEST,結果發現如果使用SocketDBListener則整個程序不能正常結束
    我查了下代碼發現是SocketDBListener里面的THREAD不是后臺的,而且也沒有手工關閉的原因
    我改成后臺的之后就沒問題了


    另外還發現一個問題,
    在SocketDBListener的代碼里有這么一段:

    protected void finalize() throws Throwable
    {
    super.finalize();
    for(int i=0,n=clientList.size();i<n;i++)
    {
    Socket socket = (Socket) clientList.get(i);
    socket.close();
    }
    }
    這樣有2個問題:
    1)super.finalize() 最好在最后調用,而且最好在FIANLLY里用,如:
    finally{
    super.finalize();
    }
    2) 關閉socket之類的工作在fianlize里面做不太好,在我的測試里,當MAIN方法進行完了后
    finalize并沒有執行,而且因為SocketDBListener里面的THREAD還在,所以shoutdownHook也沒有執行;
    而且即使該為后臺線程,能正常關閉了,finalize也不一定進行的
    所以建議為IDBListener增加一個主動關閉的方法

    posted @ 2006-05-22 01:34 CowNew開源團隊 閱讀(842) | 評論 (0)編輯 收藏

    互幫互助,提高java程序員開發水平,完成大規模團隊項目;商業運營,追求開源產品利潤最大化

    一、CowNew開源團隊簡介

    CowNew開源團隊,是一個由Java開源愛好者組成的團隊,官方網站:www.CowNew.com。
    CowNew團隊知道很多很多java開發人員處在一個較低的開發水平,但是又都普遍想提高自己的開發技能; CowNew團隊知道很多很多java開發高手有很多想法,但是由于勢單力薄,無法完成由開發團隊協同合作、共同開發才能完成的功能;CowNew團隊知道很多很多好的想法、好的項目由于缺乏有效的商業運營而導致這些很有價值的東西停留在技術層面,無法取得應有的商業價值。

    基于此我們成立了 CowNew開源團隊,此團隊的理念是“互幫互助,提高java程序員開發水平,完成大規模團隊項目;商業運營,追求開源產品利潤最大化”。

    我們--用實際項目開發幫助開發人員進階

    我們--為有想法的高手提供實現其想法的開發伙伴

    我們--積極的進行開源項目商業化運作,讓項目組成員得到更多的回報。

    二、CowNew開源團隊組織形式

    開源組織研發部門設立兩個大項目組,一個區域是項目開發區,主要是實際的項目的開發;一個區域是后備力量培養區,主要為有熱情加入開源組織、有一定的開發經驗的朋友準備,這個區域將由專門的專家指導,幫助其提高開發能力,合格的開發人員將隨時轉到項目開發區。所有后備力量培養區人員都要分配到具體的項目組,主要承擔產品測試、文檔書寫、產品宣傳工作,并且要積極閱讀學習正式項目開發人員的代碼,并定期書寫學習筆記,其筆記也將做為產品文檔。 后備力量培養區的人員可以參與項目的開發,如果其工作產品質量較優可以考慮納入正式產品中。

    另設立宣傳組和商業伙伴組,宣傳組主要負責團隊網站的日常維護更新,在各個業界主流網站中發宣傳稿,負責項目組其他成員撰寫的文章的發表推廣工作;商業伙伴組負責項目產品的商業化運營。

    三、CowNew2006年計劃開源項目列表

    1、JDBMonitor
    功能概述:一個可擴展的無侵入式的數據庫監控、日志工具。此項目已經有了第一個版本。后期將增加可用性和配置靈活性,并增強其日志分析預警能力。
    開發人員技能要求:
    熟悉java語言,或者熟悉數據挖掘
    后備人員要求:
    熟悉java語言,后備人員可以承擔部分任務,其開發成果可以納入產品中
    2、進銷存系統
    功能:提供中小企業使用的常用的進貨、銷售、倉存功能,并提供業務分析功能。
    開發人員技能要求:
    熟悉下面技能中的一種或幾種:
    Swing界面開發
    java數據庫操作
    報表開發
    熟悉進銷存業務
    熟悉分布式開發
    較強的系統建模能力
    后備人員要求:
    熟悉java語言
    3、Java Web RAD開發工具
    功能:開發Java Web開發的RAD開發工具,簡化java的web開發難度
    開發人員技能要求:
    熟悉下面技能中的一種或幾種:
    java Web 開發
    .net Web 開發
    eclipse插件開發
    較強的系統建模能力
    后備人員要求:
    熟悉java語言

    4、SQL語句解析引擎
    功能:將標準SQL語句解析成抽象語法樹,從而為后續的SQL語句格式化器,SQL語句排錯器做準備。此功能是一個獨立的抽象部件。
    開發人員技能要求:
    熟悉編譯原理,能夠書寫有一定難度的詞法、語法分析器(可以使用antlr等工具)
    后備人員要求:
    熟悉下面技能中的一種或幾種:
    熟悉java語言,對編譯原理有一定了解
    熟悉SQL語法
    5、軟多路復用技術
    功能:為應用提供多路復用支持,簡化應用部署,提高應用安全性。
    開發人員技能要求:
    熟悉網絡編程
    后備人員要求:
    有一定網絡編程經驗

    ?


    四、CowNew團隊成員激勵機制

    1、加入項目組的成員將會被記錄團隊總積分。

    1、項目開始初每人確認自己要完成的工作量和需要完成的時間。項目初期每人分配一定的項目積分,對于按時甚至提前完成的人員將會給予不同程度的項目積分獎勵,對于延遲完成的則不會給予積分獎勵,對嚴重滯后的將視情況扣除積分。項目結束后此積分將會被累積到個人團隊總積分。

    2、成員在媒體上發表的CowNew相關的技術文章、宣傳文章都將會被給予一定程度的積分,并記入個人團隊總積分。

    3、成員推薦符合要求的成員加入、為團隊商業運營提供幫助等任何對團隊有益的事情都將給予相應程度的積分。

    4、將對成員在團隊的交流平臺(qq群,論壇等)上的活躍程度進行積分,并記入積分。

    4、積分可以兌換贊助商提供的禮品等。在成員負責的項目組的產品取得商業運營利潤之后,將可以根據積分參與分紅。

    五、成員權利與義務:

    權利:
    1、啟動項目的權利。任何成員都可以提出自己的想法,并啟動相應的項目任務。
    2、自由退出的權利。任何成員都可以隨時退出團隊。
    3、投票權、選舉權、被選舉權。任何成員都可以參與相關項目組的決策,投票,并有權利被選為負責人。
    4、分紅權。任何成員都可以參與自己負責模塊商業運營成果的分紅。
    義務:
    1、任何成員必須保守團隊的秘密。
    2、所有關于CowNew團隊以及相關產品的文章,代碼可以標注作者信息,但是必須同時標注CowNew團隊的版權信息。
    3、積極參與團隊的各項任務。對于長期不參與團隊的成員將會被請出團隊。

    六、請有興趣加入CowNew團隊的朋友按下面任何一種方式進行

    1、 加入QQ群,群號:20392347。驗證消息注明:加入開源。加入后請在BBS發貼簡要介紹自己。

    2、到項目組論壇報道:http://cownew.forumup.com/

    3、到項目的sourcege主頁的論壇報道:https://sourceforge.net/projects/jdbmonitor/

    4、給我們發送email:about521@163.com

    注:加入的成員請在加入的時候注明自己想參加哪個項目組,想負責哪塊工作,特長是什么,聯系方式,最好能提供個人作品。本團隊暫時不接納入門級開發人員,請諒解。

    ?

    posted @ 2006-05-18 23:01 CowNew開源團隊 閱讀(1419) | 評論 (3)編輯 收藏

    Log4j (http://logging.apache.org/log4j/docs)是一個開源代碼的項目(Open source project),它使開發人員能最大限度的靈活控制程序調試信息的輸出,這一點它是通過額外的配置文件實現的。

    JDBMonitor(

    共同點:

    1、Log4j和JDBMonitor都有很強的可擴展性,例如Log4j可以寫自己的Appender,JDBMonitor可以寫自己的DBListener。

    2、Log4j和JDBMonitor都很容易配置。當然Log4j配置文件相對復雜。

    不同點:

    1、Log4j能為各種事件進行日志輸出,比如關鍵操作,運行中的變量值、數據庫語句日志等。而JDBMonitor只能記錄數據庫sql語句操作記錄。所以說Log4j應用范圍更廣,如果您需要記錄非數據庫語句日志就要使用Log4j,JDBMonitor則無能為力。

    2、Log4j配置比較靈活,比如可以配置什么等級的日志被記錄,記錄的格式是什么樣的,日志文件到多大的時候被轉儲;而JDBMonitor則相對較不靈活,輸出格式比較單一、而且無法指定那些日志可以被忽略。

    3、Log4j是侵入式的,所有的日志操作都是寫在業務代碼之中的,缺點是很明顯的,這導致業務代碼中摻雜大量的日志輸出代碼,降低了代碼的可讀性,而且一旦想去掉日志功能以后必須逐個刪除代碼,加大了工作量和風險。JDBMonitor是非侵入式的,它采用代理模式攔截對數據庫的調用,然后對進行日志記錄,業務系統中根本不用摻雜日志代碼。只要修改JDBC連接字符串即可,如果想去掉日志功能,只要將JDBC連接字符串修改回去即可。

    4、Log4j采用的日志記錄實現方式會對程序的運行速度有一定影響,在日志比較多的時候,甚至會導致整個程序慢到無法忍受。而JDBMonitor則另起一個線程來記錄SQL,所以它幾乎不會對程序運行速度有任何影響。

    5、Log4j的Appender不適合進行調試開發,調試開發只有那個控制臺Appender可以用,但是在大數據量的時候整個屏幕狂刷不止,根本看不清,而且很多操作系統的控制臺(比如windows的)都有緩沖區大小限制,所以很容易造成想看的sql日志被沖掉看不到了。而Log4j的不僅有與Log4j類似的控制臺Appender可以用,而且有一個客戶端SocketSwingClient可以用,這個客戶端類似SQLServer的事件監聽器,容納的日志量相當大,而且可以自由控制日志的上下滾動。

    posted @ 2006-05-17 17:03 CowNew開源團隊 閱讀(942) | 評論 (0)編輯 收藏

    僅列出標題
    共30頁: First 上一頁 21 22 23 24 25 26 27 28 29 下一頁 Last 
    主站蜘蛛池模板: 成av免费大片黄在线观看| 亚洲精品无码av片| a级精品九九九大片免费看| 亚洲男人的天堂在线va拉文| 老司机福利在线免费观看| 免费人妻无码不卡中文字幕18禁| 综合偷自拍亚洲乱中文字幕| 国产一级做a爱免费视频| 美女又黄又免费的视频| 亚洲阿v天堂在线2017免费| 一级视频在线免费观看| 亚洲啪啪综合AV一区| 国产精成人品日日拍夜夜免费| 亚洲精品在线观看视频| 久久笫一福利免费导航| 亚洲第一街区偷拍街拍| 亚洲AV伊人久久青青草原| 最近免费中文字幕中文高清| 亚洲综合一区二区精品导航| 青青视频观看免费99| 精品亚洲视频在线| 亚洲深深色噜噜狠狠爱网站| 久久久久久毛片免费播放| 亚洲乱码中文字幕小综合| 日韩免费视频播播| 久草免费福利在线| 亚洲精品偷拍无码不卡av| 免费鲁丝片一级观看| 男女一边桶一边摸一边脱视频免费| 久久91亚洲人成电影网站| 无码人妻一区二区三区免费手机| 国产精品亚洲精品日韩动图| 亚洲码国产精品高潮在线| 男女免费观看在线爽爽爽视频| 国产亚洲情侣久久精品| 亚洲成AV人片在线观看ww| 四虎成人免费影院网址| 野花香高清在线观看视频播放免费 | 国产成人精品日本亚洲11| 免费在线观看的黄色网址| 久久国产色AV免费观看|