如鹏网 大学生计算机学习社区

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推荐的最佳模式。”-《看Hibernate3如何解释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开源团队 阅读(4973) | 评论 (2)编辑 收藏

    初涉开源已经一个月了,和Huihoo、SpringSide、EasyJF这样的“老大哥”比起来还稚嫩的很。但是在这一个月中也体会到了酸甜苦辣。
   开源是需要雷锋精神的。“时间就像海绵里的水,只要愿意挤,总还是有的。” (有人说这句话是鲁迅说得,我没时间去考证了)。哪怕公司的工作加班到了10点,回来还是可以为开源忙上一个小时的,不要给任何自己不要为之奋斗的理由,只要要求自己每天都为开源做一点事情,相信会有回报的。
    开源是孤独的,特别是在中国。太多的人为了二斗米去奋斗,并以此给自己一个自己很忙,自己没时间做开源的借口;太多的人认为开源是在为别人卖苦力,自己是傻大个;太多了人站在少数几个开源者的旁边,象看耍猴子一样看热闹了;太多的人希望钻进一个开源团队,然后什么事情都不做,等着坐收渔利了;太多了人还没开始做就想着项目商业运营之后到底能赚多少钱了。。。。。。
    开源是需要付出的。女朋友又想你了,你去不去?哥们又要你出去喝酒了,你去不去?周末朋友们又去蹦迪了,你去不去?开源有可能是付出了N多精力,却无利可图的,你干不干?。。。。。。
    开源是劳累的。忙完了白天的工作,晚上回来还要写代码;但别人都进入梦乡的时候,你却在为一个自己为自己分配的开源任务而奋斗。。。。。。  
    开源是需要钻研精神的。开源一般做的都是业界先进的技术,能够参考的资料很少。你不能够要求做开源的时候还有那么多被前仆后继的编码员都写臭了街的所谓“××信息系统”的代码可以参考。更多的需要自己去钻研:钻研国外的资料,与同行的高手共同探讨,甚至要自己独创一套东西。创新是开源的一个重要特征。这也决定了做开源的最终都会成为精英。
    开源是需要脚踏实地的。那些希望今天做开源明天就能成名发财的人是必将失败的。安下心来,低下头来,走好脚下的每一步,相信成功就一定会在前方等着你。
    开源是为自己在努力的。开源项目中没有老板,项目发起人也只是个组织者,你不是在为他工作,你是在为自己的明天奋斗。开源中付出多的就是老大。不要抱怨项目组织者今后一定会比普通的队友成功,你来努力呀,你的成绩你的付出超过他,你就是老大。记住:开源是为自己奋斗,那些认为是在为别人卖苦力的人还是回到公司,老老实实当你的小职员吧。
   
    CowNew团队过程中我们遇到了很多兢兢业业的朋友。项目经验丰富的BadBoy,为了做团队网站差点累出病来的土豆,经常为了SQL解析引擎而忙到凌晨2点的KingChou,为项目管理献计献策的Andrew、霉干菜,为产品书写介绍文档验证bug的月光光、c2,经验丰富的Sephil,还有积极关注团队发展的孤独河马、滚来滚去、热血年华、宋笑痴、foxKnit等等朋友。EasyJF的大峡、船长也给我们提出了很多建议。有了他们才有了CowNew的现在。
    问题是很多的。现在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开源团队 阅读(1207) | 评论 (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开源团队 阅读(1092) | 评论 (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开源团队 阅读(1248) | 评论 (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开源团队 阅读(914) | 评论 (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开源团队 阅读(943) | 评论 (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开源团队 阅读(2213) | 评论 (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开源团队 阅读(840) | 评论 (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开源团队 阅读(1416) | 评论 (3)编辑 收藏

Log4j (http://logging.apache.org/log4j/docs)是一个开源代码的项目(Open source project),它使开发人员能最大限度的灵活控制程序调试信息的输出,这一点它是通过额外的配置文件实现的。

JDBMonitor(http://www.cownew.com)是一个开源项目。使用它开发者可以很轻松为系统增加数据库执行日志功能。它使用十分方便,您所需要做的唯一事情就是在您系统的JDBC连接字符串前增加类似于 "listenerconfig=/config.xml:url=" 的字符即可,不用写任何代码。使用 JDBMonitor,您可以把数据库执行情况记录通过各种方式记录下来,比如打印到控制台、输出到文件或者通过socket传送给远程客户端。

共同点:

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开源团队 阅读(939) | 评论 (0)编辑 收藏

仅列出标题
共30页: First 上一页 21 22 23 24 25 26 27 28 29 下一页 Last