志当存高远,功到自然成!

少年强则中国强,少年进步则中国进步!

BlogJava 首页 新随笔 联系 聚合 管理
  53 Posts :: 2 Stories :: 2 Comments :: 0 Trackbacks

#

     摘要: 有关读数据库的无刷新的三级联动以及层次数据(树形结构)在关系数据库的存储 关键字: jsp 三级联动 层次 树形结构 数据库 我的标题真冗长:P 最近一直在考虑这个问题,如何在现在常用的关系型数据库(如mysql,mssql)中存储含有层次结构(例如xml或者树型结构)的数据,我最终要实现的结果是一个比较好的页面三级联动菜单。比较了一下现有的三级联动,无非有两种解决方案,1、将所有数...  阅读全文
posted @ 2008-06-27 15:54 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(1091) | 评论 (0)编辑 收藏

Oracle的换行符

  • 在SQL中,表示字符串得引号强烈建议使用单引号(')。虽然MySQL也可以使用双引号("),但是为了和SQL Server和Oracle统一,建议都使用单引号。如果在字符串中也有单引号出现的话,在SQL中需要将其替换为两个单引号(''),DBMS会将其解释为一个单引号的。
  • 关于SQL的换行符和字符串连接符,在MySQL、SQL Server和Oracle中均有不同,下面以列表显示。
      MySQL SQL Server Oracle
    换行符 \n或\r\n或CHAR(10) CHAR(13) CHR(10)
    字符串连接符 CONCAT() + ||或CONCAT()
  • posted @ 2008-06-25 16:01 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(592) | 评论 (0)编辑 收藏

    引自:http://www.itpub.net/23129.html

    1. ORACLE存储过程的参数不能限定位数,参数类型定位为
    CHAR(5)是非法的,只能定义为CHAR,具体位数限定有调用时的实参决定,这一点确实与SYBASE有很大不同;
    2.游标在PL/SQL中作用极大,游标的概念渗透到整个PL/SQL的核心,连INSERT,UPDATE等语句都隐含了一个隐式游标SQL,类似SYBASE的@@ROWCOUNT等系统变量,在ORACLE中定义为游标属性SQL%ROWCOUNT;
    3.ORACLE中显示一个变量的语句为SELECT V_VAR FROM DUAL;
    与SYBASE不同的是必须加FROM DUAL;
    4.SYBASE存储过程可以通过类似SELECT * FROM T_TABLE来返回数据集,在ORACLE中似乎不能,所有不带INTO的SELECT 语句在ORACLE存储过程中是非法的。这一点变化带来最大麻烦,应为POWERBUILDER调用SYBASE存储过程很喜欢这种方式。

    5、在存储过程中声明参数不用加 DECLARE

    6、在每个块中只有一个 DECLARE

    7、参数名不用加 @ 后缀

    8、每条语句后要加分号

    9、变量附值不同:
    myvalue:='abc';
    select @myvalue='abc'

    SELECT EMPNO into :emp from EMP WHERE ...;
    SELECT @emp=EMPNO from emp WHERE...

    10、在TRIGGER 中出现exception 不用加ROLLBACK命令

    11、oracle 不使用 read locks ,无论是 read-consistent 还是 serializable 事务所以要注意SELECT FOR UPDATE的使用

    移植方案

    一.后台存储过程利用conv72从SYBASE转换到ORACLE。

    USAGE: conv72 [-P -F -M] <input_file_name>
    -P指存储过程,-F指函数
    例如:conv72 -P filename.sql
    转换后,产生文件名字是filename.sql.sql



    二.转换后的调整。


    (一)后台存储过程的调整

    1、NULL
    ORACLE对NULL 的条件判断只能用: 变量 IS NULL 和变量 IS NOT NULL;
    对NULL 的附值只能用:变量 := NULL;
    因此需要对所有存储过程中有关 NULL 的操作做上述相应调整。

    2、StoO_error:=0;
    所有存储过程中,凡是对数据库做有效操作之前,包括UPDATE,DELETE,INSERT以及
    执行子存储过程或函数,都有必要将ORACLE转化过程中自动加上的变量StoO_error清
    零,即在操作之前加上 StoO_error:=0; 。

    3、WHEN NO_DATA_FOUND THEN StoO_error :=0;
    所有存储过程中,对数据库做有效操作之后,通常会用IF StoO_error != 0 THEN来
    检验操作成功与否。对于空操作,即WHERE 子句条件不满足时,ORACLE会产生例外,
    而SYBASE 不会出错。因此为了一致,在 EXCEPTION 中 应加入
    WHEN NO_DATA_FOUND THEN StoO_error :=0;

    4、示例:
    StoO_error :=0;/*操作之前加上 StoO_error:=0*/

    BEGIN
    DELETE BOAD
    WHERE (EXCH_ID = i_exch_id) AND (SWT_ID = i_swt_id)
    AND (FRAME_NBR = i_frame_nbr) AND (SHELF_NBR = i_shelf_nbr)
    AND (BOAD_NBR = i_boad_nbr);
    StoO_rowcnt := SQL%ROWCOUNT;
    EXCEPTION
    WHEN NO_DATA_FOUND THEN
    StoO_error :=0;
    WHEN OTHERS THEN
    StoO_error := SQLCODE;
    END;

    IF StoO_error != 0 THEN
    BEGIN
    ROLLBACK TO SAVEPOINT aa;
    i_status := -1 ;
    RETURN /* */;
    END;
    END IF;
    5、事务设计
    ORACLE的存储过程中,COMMIT 语句将会把此前未提交的所有事务都提交,且对于
    已提交的事务,无论在后台存储过程中,还是在前台 PB 的脚本中,都无法回滚。
    这与SYBASE 不同,因此事务应该结合后台存储过程与前台 PB 脚本设计。

    6、事务的调整
    在ORACLE中,没有SYBASE中事务嵌套数的概念,在后台的存储过程中,遇到
    COMMIT时,将把整个事务(包括前台和后台)全部提交。而在SYBASE中,只
    有当事物数为最低级时(设计都在前台)才能提交。

    由于所有事务都在前台提交,
    因此把后台存储过程中所有的COMMIT全部注释掉。



    7、时间参数调整

    如果该存储过程的输入参数为DATE型时,在POWERBUILDER中创建存储过程
    时,将引发错误。

    为了解决此问题,

    在后台,将这种存储过程的DATE型输入参数
    全部改为VARCHAR2型。
    在存储过程中,将VARCHAR2转化为DATE,为了前后台一致,
    采用统一的转化格式。

    i_start_DATE:=TO_DATE(i_start_string,'YYYY/MM/DD HH24:MI:SS');
    i_end_date :=TO_DATE(i_end_string, 'YYYY/MM/DD HH24:MI:SS');

    在前台POWERBUILDER中,将DATE或者DATETIME型变量转化为STRING型,
    也采用上述统一格式,再作为存储过程的参数。

    v_STRING=STRING(v_DATE, 'YYYY/MM/DD HH:MM:SS')
    v_STRING=STRING(v_DATETIME,'YYYY/MM/DD HH:MM:SS')


    (二)用于数据窗口的后台存储过程的修改

    1、通过特定表返回时,WHERE子句的处理


    TABLE: TEST

    COLUMN: NAME VARCHAR2(20);
    AGE NUMBER;
    BIRTH DATE;
    REMARKS VARCHAR2(30);

    最后的返回语句如下,WHERE子句的处理中,对字符型和日期型进行转义处理

    PBDBMS.PUT_LINE('SELECT NAME,AGE,BIRTH,REMARKS ')
    PBDBMS.PUT_LINE(' FROM TEST ');
    str_where:=' WHERE NAME='|| ''''||VAR_NAME||''''
    ||'AND AGE =' || TO_CHAR(VAR_AGE)
    ||'AND BIRTH=' || ''''||TO_CHAR(VAR_BIRTH)||'''';
    PBDBMS.PUT_LINE(str_where);

    注意:
    如果NUMBER型变量是该存储过程的输入参数,则要对他进行
    单独处理
    IF VAR_AGE IS NULL THEN
    CONV:=' AND AGE IS NULL ';
    ELSE
    CONV:=' AND AGE = ' || TO_CHAR(VAR_AGE);
    END IF;


    2、最后数据的返回通过表DUAL进行

    有两种方式:
    (1)、用PBDBMS.PUT_LINE。无法处理返回值为空值的情况
    使用方法见底下示例:
    注意:对不同变量类型进行了不同处理。

    (2)、用PBDBMS.PUT
    该过程已经过修改,可对各种变量类型进行处理,不在需要在程序中对
    不同类型进行不同处理,同时也可适应NULL值的情况。
    使用方法见底下示例:
    注意:直接使用该参数,多个变量返回时注意中间加PUT(',');

    另外:PBDBMS包中行最大长度为255,而PUT函数不换行,因此估计
    长度快到255时,使用PUT_LINE(',')来实现换行目的。

    PROCEDURE AAA
    (I_SO_NBR VARCHAR2)
    IS
    I_NUM INTEGER;
    i_date date;
    I_NAME VARCHAR2(50);
    I_COV VARCHAR2(100);
    I_COV2 VARCHAR2(100);
    BEGIN
    /* 第一种方式*/
    I_COV:= ' SELECT '||''''||I_NAME||''''||','||TO_CHAR(I_NUM)||','||''''||TO_CHAR(I_DATE)||'''';
    I_COV2:=' FROM DUAL';

    PBDBMS.PUT_LINE(i_cov);
    PBDBMS.PUT_LINE(I_cov2);

    /*第二种方式*/
    PBDBMS.PUT_LINE('SELECT ');
    PBDBMS.PUT(I_NAME);
    PBDBMS.PUT(',');/* 如长度将超过255,此处用PUT_LINE(',')进行换行*/

    PBDBMS.PUT(I_NUM);PBDBMS.PUT(',');
    PBDBMS.PUT(I_DATE);
    PBDBMS.PUT_LINE(' FROM DUAL');

    END;



    (三)前台脚本中嵌入式SQL语句的调整

    1、ORACLE 存储过程前台脚本调用方式:
    DECLARE sosp_cust_i PROCEDURE FOR sosp_cust_i
    (:name,:reg_nbr,:li_cust_cat_id,吐舌osition,
    null,吐舌arent_id) ;
    execute sosp_cust_i;


    SYBASE 存储过程前台脚本调用方式:
    DECLARE sosp_cust_i PROCEDURE FOR sosp_cust_i
    @name = :ls_name,
    @reg_nbr = :ls_regnbr,
    @cat_id = :ii_cust_cat,
    @position = null,
    @type_id = :ii_cust_type,
    @parent_id = :ll_parent_id ;
    execute sosp_cust_i;


    2、前台脚本中嵌入式的SQL语句中
    (1)NULL
    ORACLE对NULL 的条件判断只能用: 字段名 IS NULL 和 字段名?IS NOT NULL;
    而不能用:字段名 = NULL 和 字段名?<> NULL?
    若有上述情况,应做相应调整。
    如:select * from so_charge where receipt_nbr = null;
    应改为:select * from so_charge where receipt_nbr is null;

    (2)""->''
    ORACLE对字符串使用单引号,而SYBASE单引号、双引号均可
    因此若有如select * from so where state="A";的语句
    应改为select * from so where state='A';

    (3)insert -> insert into
    SYBASE允许使用insert tablename...,而ORACLE必须使用
    insert into tablename...,若有上述情况,应做相应调整。

    (4)+ --> ||
    字符串连接,SYBASE使用'+',而ORACLE使用'||'。?

    (5)getdate() --> sysdate
    取系统时间,SYBASE使用getdate(),而ORACLE使用sysdate。

    posted @ 2008-06-23 19:57 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(275) | 评论 (0)编辑 收藏

    这里笔者介绍一种很常用,也比较专业的权限控制思路。这里用java语言描述,其实都差不多的。要换成其他的语言主,自己转一下就可以了。为了方便起见,我们这里定义a^b为:a的b次方。这里,我们为每一个操作设定一个唯一的整数值,比如:

    删除A---0
    修改A---1
    添加A---2

    删除B---3
    修改B---4
    添加B---5

    ……

      理论上可以有N个操作,这取决于你用于储存用户权限值的数据类型了。

      这样,如果用户有权限:添加A---2;删除B---3;修改B---4。那用户的权限值 purview =2^2+2^3+2^4=28,也就是2的权的和了。化成二进制可以表示为11100。这样,如果要验证用户是否有删除B的权限,就可以通过位与运算来实现。在Java里,位与运算运算符号为&,即是:

    int value = purview &((int)Math.pow(2,3));

      你会发现,当用户有操作权限时,运算出来的结果都会等于这个操作需要的权限值!

      原理:

      位与运算,顾名思义就是对位进行与运算:

      以上面的式子为例:purview & 2^3 也就是 28&8

      将它们化成二进制有

      11100
    & 01000
    -------------------
      01000 == 8(十进制) == 2^3

      同理,如果要验证是否有删除A---0的权限

      可以用:purview &((int)Math.pow(2,0));

      即:

      11100
    & 00001
    ------------------------
      00000 == 0(十进制)  != 2^0

      这种算法的一个优点是速度快。可以同时处理N个权限。如果想验证是否同时有删除A---0和删除B---3的权限,可以用purview&(2^0+2^3)==(2^0+2^3)?true:false;设置多角色用户。根据权限值判断用户的角色。

      下面提供一个java的单操作权限判断的代码:

    //userPurview是用户具有的总权限
    //optPurview是一个操作要求的权限为一个整数(没有经过权的!)
    public static boolean checkPower(int userPurview, int optPurview)
    {
      int purviewValue = (int)Math.pow(2, optPurview);
      return (userPurview & purviewValue) == purviewValue;
    }

      当然,多权限的验证只要扩展一下就可以了。

      几点注意事项:首先,一个系统可能有很多的操作,因此,请建立数据字典,以便查阅,修改时使用。其次,如果用数据库储存用户权限,请注意数值的有效范围。操作权限值请用唯一的整数!

    posted @ 2008-05-29 17:13 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(339) | 评论 (0)编辑 收藏

    SQL> col fscn for 9999999999999999999
                SQL> col nscn for 9999999999999999999
                SQL> select name,FIRST_CHANGE# fscn,NEXT_CHANGE# nscn,FIRST_TIME from v$archived_log;
                ...................
                NAME                                           FSCN                 NSCN FIRST_TIME
                ------------------------------ -------------------- -------------------- -------------------
                /mwarch/oracle/1_52413.dbf              12929941968          12929942881 2005-06-22 14:38:28
                /mwarch/oracle/1_52414.dbf              12929942881          12929943706 2005-06-22 14:38:32
                /mwarch/oracle/1_52415.dbf              12929943706          12929944623 2005-06-22 14:38:35
                /mwarch/oracle/1_52416.dbf              12929944623          12929945392 2005-06-22 14:38:38
                /mwarch/oracle/1_52417.dbf              12929945392          12929945888 2005-06-22 14:38:41
                /mwarch/oracle/1_52418.dbf              12929945888          12929945965 2005-06-22 14:38:44
                /mwarch/oracle/1_52419.dbf              12929945965          12929948945 2005-06-22 14:38:45
                /mwarch/oracle/1_52420.dbf              12929948945          12929949904 2005-06-22 14:46:05
                /mwarch/oracle/1_52421.dbf              12929949904          12929950854 2005-06-22 14:46:08
                /mwarch/oracle/1_52422.dbf              12929950854          12929951751 2005-06-22 14:46:11
                /mwarch/oracle/1_52423.dbf              12929951751          12929952587 2005-06-22 14:46:14
                ...................
                /mwarch/oracle/1_52498.dbf              12930138975          12930139212 2005-06-22 15:55:57
                /mwarch/oracle/1_52499.dbf              12930139212          12930139446 2005-06-22 15:55:59
                /mwarch/oracle/1_52500.dbf              12930139446          12930139682 2005-06-22 15:56:00
                NAME                                           FSCN                 NSCN FIRST_TIME
                ------------------------------ -------------------- -------------------- -------------------
                /mwarch/oracle/1_52501.dbf              12930139682          12930139915 2005-06-22 15:56:02
                /mwarch/oracle/1_52502.dbf              12930139915          12930140149 2005-06-22 15:56:03
                /mwarch/oracle/1_52503.dbf              12930140149          12930140379 2005-06-22 15:56:05
                /mwarch/oracle/1_52504.dbf              12930140379          12930140610 2005-06-22 15:56:05
                /mwarch/oracle/1_52505.dbf              12930140610          12930140845 2005-06-22 15:56:07
                14811 rows selected.
                

    当前的SCN为:
    SQL> select dbms_flashback.get_system_change_number fscn from dual;
                FSCN
                --------------------
                12930142214
                

    使用应用用户尝试闪回
    SQL> connect username/password
                Connected.
                

    现有数据:
    SQL> select count(*) from hs_passport;
                COUNT(*)
                ----------
                851998
                

    创建恢复表
    SQL> create table hs_passport_recov as select * from hs_passport where 1=0;
                Table created.
                

    选择SCN向前恢复
    SQL> select count(*) from hs_passport as of scn 12929970422;
                COUNT(*)
                ----------
                861686
                

    尝试多个SCN,获取最佳值(如果能得知具体时间,那么可以获得准确的数据闪回)
    SQL> select count(*) from hs_passport as of scn &scn;
                Enter value for scn: 12929941968
                old   1: select count(*) from hs_passport as of scn &scn
                new   1: select count(*) from hs_passport as of scn 12929941968
                COUNT(*)
                ----------
                861684
                SQL> /
                Enter value for scn: 12927633776
                old   1: select count(*) from hs_passport as of scn &scn
                new   1: select count(*) from hs_passport as of scn 12927633776
                select count(*) from hs_passport as of scn 12927633776
                *
                ERROR at line 1:
                ORA-01466: unable to read data - table definition has changed
                SQL> /
                Enter value for scn: 12929928784
                old   1: select count(*) from hs_passport as of scn &scn
                new   1: select count(*) from hs_passport as of scn 12929928784
                COUNT(*)
                ----------
                825110
                SQL> /
                Enter value for scn: 12928000000
                old   1: select count(*) from hs_passport as of scn &scn
                new   1: select count(*) from hs_passport as of scn 12928000000
                select count(*) from hs_passport as of scn 12928000000
                *
                ERROR at line 1:
                ORA-01466: unable to read data - table definition has changed
                

    最后选择恢复到SCN为12929941968的时间点
    SQL> insert into hs_passport_recov select * from hs_passport as of scn 12929941968;
                861684 rows created.
                SQL> commit;
                Commit complete.
                
    posted @ 2008-05-25 20:13 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(203) | 评论 (0)编辑 收藏

    JIRA

      一个非常出色的Issue跟踪系统,这里的Issue不单单是指BUG, 很多时候也可以是TASK, IMPROVEMENT, NEW FEATURE, 甚至是一个QUESTION。

      在多年前, 我曾经尝试使用过那个经典的的Bugzilla,但是一个项目作下来,大家都反映那个东西的界面实在是太粗糙,简直无法忍受而且报表功能也是在太弱。最后大家就讨论自己作一个BUG的跟踪系统,就在大家已经完成了设计文档准备编码的时候, 我们发现JIRA原来就是我们要找的东西,而且比我们要的更多。它内置一个可以配置的工作流引擎(osworkflow),一个快捷的全文检索功能(基予Apache Lucene).和一个可以配置的Dashboard(portlet),以及一个和CVS连接的引擎,通过这个连接,在一个Issue中直接可以看到修改的文件名称,如果配置了viewcvs的话,还直接直接定位到行,根据一个问题可以跟踪到代码的行,这正式我们梦寐一求的功能。 也正是这种特性,才使我们能够把一个个Issue当作发布和版本管理的一个单元。

    CVS

      这个应该大家都知道。在系统开发过程中,一切的源代码和设计文档都应该进入版本管理系统来进行管理, 有的时候可能资源库可能会膨胀的很大, 但这个代价是值得的。

    XPlanner

      在整个管理体系中,进度管理一直是一个?比较薄弱的环节,我也曾试过dotproject这样的管理软件,但由于dotproject管理的太过详细,填报起来太复杂,大家渐渐都失去了填报的热情。这个 XPlanner软件可就简单多了。指定了迭代,story,然后就可以填写进度了。由于这个软件也是OpenSource的,所以如果觉得不满意,修改起来也很方便,现在老林就对这个系统作了些改进,可以直接和JIRA系统连接起来,JIRA中建立issue后,可以在XPlaner中反映出来,连填写 story的时间都省去了, 然后在下班之前可以生成一个详细的报告,列出每个人在这一天内在自己负责的Issue在上的处理时间和进度。

    WIKI

      在项目管理中,我们一直把它当作文档管理和Portlet系统来使用,它现在已经变成我们的小组的工作台,在WIKI中我们制定了包括系统开发设计规范在内的一切设计文档,以及数十个经常的HOWTO项目,例如如何配额一个标准的开发环境,如何使用CVS客户端,如何使用JIRA,以及自己的 JavaDoc, JSDoc等。 我们也可以通过Wiki来简单的整合系统,在Wiki中我们列出了所有开发环境和开发工具的入口,例如上面就放了进入JIRA,XPlanner以及我们各个Project的连接,甚至到 Apache中常用的Project的JavaDoc的连接,现在再也没有人去记录这些URL了,只要打开Wiki所有的资源都在面前了,并且由于wiki本身的开放性,所以每个团队的成员都是一个维护者,同时也是这个系统的受益者。在很多的团队中经常出现的情况是一个小子对某个技术特别在行,大家遇到这方面的问题都问他,在小的团队中, 面对面的交流通常是最快的交流方式,但是放到大的团队中,这个就不大可行了,那个小子迟早有一天会被问的烦到吐血为至,特别是他自己的工作也无法按时完工的时候。还是抽一个小时写出来,放到 wiki里面吧, 别问我, 自己去查Wiki。

    基于ISSUE的发布管理

      从版本管理的角度来考虑,最理想的发布方法就是把CVS中的代码拿下来, 打上一个tag, 编译并且测试一直到发布。 这样的管理方式的确是很简单的,但事实上用户可不买帐的, 用户觉得在新的版本中某个新的功能他还不想要,这可能是他还没有整理好业务初始数据或者在实际的业务流程上或人员上没有做好准备, 上帝说了不要咱就不能把这个新功能发布。在这个情况下,基于Issue的发布管理是一个好的方案。

      这里讲的Issue就是前面JIRA系统中的一个issue。 通常每个Issue的完成都会伴随这一些代码的修改。 基于Issue的发布简单的来说就是把一组Issue变更的文件用patch的形式发布到正式的系统中。

      基于Issue发布的前提就是要在Issue和Source之间建立连接, 使发布人员清楚的知道每个Issue修改的源代码是什么。我们实践下来最简单的办法就是在提交source的时候必须加上JIRA编号, 没有JIRA编号代码是不能提交的。 这样有以下好处:

    1)防止一些没有经验的程序员无意义的提交, 比如一个小子今天提交了一个java文件,明天发现这个变量命名有点不爽, 修改后就要提交,在这种情况下, 这个提交是没有意义的,如果测试组已经测试这个Issue, 是否测试组要重新测试? 为一个变量名称化这样的时间和冒险是可嫩的。小伙子还是在第一次提交的时候就把变量名想好了再提交。

    2)程序员偷偷的修改代码,一个小伙子发现自己的已经Closed的Issue中有一个Bug, 便偷偷的修改代码。 这个当然也是不可能的,凡是提交到CVS中的代码就不是自己的了,那是大家的, 没有足够的理由想改当然没有那么容易。 先自己建立建立个Issue, 向Team leader报告, 然后再去修改代码.。

    posted @ 2008-05-14 20:29 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(380) | 评论 (0)编辑 收藏

    今天提到文档方案的问题,正好我们的一个工程师也提出了协作问题。指出目前团队协作方面的欠缺,同时应该发现,目前对于文档管理这块,部门还是欠缺 的,虽然像某些服务单位已经有了较为完善的文档,但是由于独立和修改次数的增多,如何确立一个“正确、标准”的版本成为一个比较复杂的问题。而更大的问题 就是文档传播的问题。当然,你说工程师写好了文档,放在这里,你来拿,或者我给你邮寄。首先,我们的工程师处于市内各个地点,通讯交流有一定的阻碍,也不 能快速迅捷的复制文件,使用email更会造成邮件系统的资源占用,并且如果需要修改一处错误,难道要群发邮件?

    观目前使用的知识库,首先 仅仅按照服务地点来组合,就不是很科学的方法。文档的建立,并不是为了记录,而是为了查阅的方便。keso说过,GoogleNotebook目前失败在 于既不方便于存储也不方便提取。目前查询系统和分类界面都不是很令人满意。所以服务文档看似很多,但却很少有人去查询。
        较为科学的分类方式,借鉴当今比较火的web2.0的概念叫做tag(标签),我们通过tag文档,作为日后搜索文档和查询文档的关键字。这个关键词可以 是服务地,也可以是问题类型等。这样,一个文档被贴上多个tag后存档。比如:A单位,网络,cisco。日后a单位网络出现问题 在查询的时候,输入a单位,网络 即可搜索到相关文档。或许就是相同的问题。比如我想了解关于cisco的问题,那么同样通过cisco tag,我们也可以了解到相关信息。当然,如何组织tag的定义分类 对于快速搜索是很有帮助的。

    另一个就是版本控制。当一篇文档以标准的 格式完成的时候,我们把它加入到存档中。随着时间的增长,必然会产生新的问题或者对原有问题有了新的看法。还有新的工程师发现了问题。那么就要去修改。共 享文档自由修改虽然方便,但是版本控制就成问题。如何确保不被错改,误改?所以引入了“权威版本”的概念。比如一篇关于某系统的详细文档,经过管理人员审 订的初稿可以定为“权威版本”。日后如果发现问题或者有了新的解决需要更新,那么工程师可以立即去修改。但是这个修改并不影响到权威版本,当修改稿被广泛 接受或者经测试无误,则并入“权威版本”并相应的版本号进步。
        版本控制其实在office中已经实现,但是很少有人关注,并且其应用也受到一定的限制。并且由word组成文档组并不利于迅速的搜索,对于常见问题来说,建立长篇的大型word文档不是一个很棒的选择。

    wiki系统自出生以来,就实现了协作、共享和查阅。所以基于这种特性,很是看好wiki在日后企业中的应用。不仅仅是实现项目和文档的管理,如果实现相应的权限控制,甚至可以实现组织和运作的管理。

    通过网络的传播,不仅仅是在局域网中,在任何地方,工程师们都可以访问到OA中的文档,有效快捷的针对性查询。在家里,可以系统地看到其他项目组的有条理文档。

    EA(Electronic Arts) 公司就在其内部实现了类wiki系统的组织管理和项目管理。

    posted @ 2008-05-14 18:06 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(268) | 评论 (0)编辑 收藏

    在IE中如何在用户直接关闭窗口前清除Session

    关键字: IE 关闭窗口 清除Session
    一般的会员形式的网站,在会员登陆后都会建立会话或者Cookie,然后需要在会员退出时点退出连接或按纽退出。在会员直接关闭窗体的时候,没有触发涉及到退出的一系列退出。而这些要等到服务器会话过期才会被清除掉。

    有幸的是在网络上终于找到可以捕获用户使用Alt+F4、标题栏按右键关闭、双击标题栏、直接按关闭按钮的事件的方法。当然对于最小化到任务栏再进行关闭是不能捕获的。

    <script language="javascript">

    <!--

    function window.onunload(){

    if((window.screenLeft>=10000 && window.screenTop>=10000)||event.altKey)

    {

    //用户非正常关闭时需要触发的动作

    }

    }

    -->

    </script>

    说明:

    window.screenLeft = 10000 + 边框宽 (2×2) = 10004

    window.screenTop = 10000 + 工具栏高 + 标题栏高 = 10097

    需要说明的,在onBeforeUnload中屏幕这些坐标属性都是正常数值。

    screenLeft:获取浏览器客户区左上角相对于屏幕左上角的 x 坐标。

    screenTop:获取浏览器客户区左上角相对于屏幕左上角的 y 坐标。

    我猜测,在窗体销毁时捕获的将产生一个特殊的数值。在正常情况下的点击测试,数值都不会超过该数值。

    现在问题是,在onBeforeUnload中使用window.location可以正常地提交请求到指定URL,但在onUnload事件中该方法不能有效执行。解决的方法是新开一个窗口,在将之关闭掉。

    我们可以写上这样的话,来代替以往使用的,一系列的window.location。因为门户网站涉及到多个跨服务器的网站服务器。在统一入口退出后,需要依次地进行顺序退出,才能达到门户网站期望的效果。

    var newWindow;

    window.opener=null;

    newWindow=window.open(URL,PageName, 'height=0,width=0’);

    newWindow.opener=null;

    newWindow.close();

    ……

    该段代码已经经过测试,在onUnload里不要使用window.close,因为对象销毁前会立即触发该事件。而onBeforeUnload是页面将要被卸载前触发的事件。

    而所谓的清除实质上就是把做好退出功能的页面,直接以打开新窗口方式的调用。可能在调用到关闭的时候能停顿一两秒,或者关闭窗口放在专门的退出页面。该页面与正常退出又切回到首页,不同的是退出后会自动进行关闭,不需要再另外进行控制直接打开即可。

    [注意]在window.onUnload中如果不加判断,则会在刷新页面等导致当前页面变化都会触发该事件。因此必须要进行判断,捕捉特定的操作,才能屏蔽掉一些正常的操作。


    续:在IE中如何在用户直接关闭窗口前清除Session
    昨天曾经讲解了实现思路,但在实际操作中发现,必须要加上延迟才能确保程序可以正常执行完毕。下面附上实现的细节,并附上简单的时间延迟函数。代码已经经过测试。

    <script language="javascript">

    function window.onUnload()

    {

    var newWindow;

    if((window.screenLeft>=10000 && window.screenTop>=10000)||event.altKey)

    {

    newWindow=window.open(‘退出程序地址’,’网页名称’,

    ’width=0,height=0,top=4000,left=4000');//新窗口将在视区之外打开

    newWindow.opener=null;

    sleep(5000);

    newWindow.close();//新窗口关闭

    }

    }

    function sleep(milisecond)

    {

    var currentDate,beginDate=new Date();

    var beginHour,beginMinute,beginSecond,beginMs;

    var hourGaps,minuteGaps,secondGaps,msGaps,gaps;

    beginHour=beginDate.getHours();

    beginMinute=beginDate.getMinutes();

    beginSecond=beginDate.getSeconds();

    beginMs=beginDate.getMilliseconds();

    do

    {

    currentDate=new Date();

    hourGaps=currentDate.getHours() - beginHour;

    minuteGaps=currentDate.getMinutes() - beginMinute;

    secondGaps=currentDate.getSeconds() - beginSecond;

    msGaps=currentDate.getMilliseconds() - beginMs;

    if(hourGaps<0) hourGaps+=24; //考虑进时进分进秒的特殊情况

    gaps=hourGaps*3600+ minuteGaps*60+ secondGaps;

    gaps=gaps*1000+msGaps;

    }while(gaps<milisecond);

    }

    </script>
    posted @ 2008-05-09 12:23 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(2482) | 评论 (0)编辑 收藏


    转载处:http://blog.csdn.net/sxqem/archive/2007/02/27/1515885.aspx

    如果能在构建代码前发现代码中潜在的问题会怎么样呢?很有趣的是,Eclipse 插件中就有这样的工具,比如 JDepend 和 CheckStyle,它们能帮您在软件问题暴露前发现这些问题。在 让开发自动化 的本期文章中,自动化专家 Paul Duvall 将带来一些关于 Eclipse 插件的例子,您可以安装、配置和使用这些静态分析插件,以便在开发生命周期的早期预防问题。
    关于本系列
    作为一名开发人员,我们的工作就是为终端用户将过程自动化;然而,我们当中有很多人却忽视了将我们自己的开发过程自动化的机会。为此,我编写了让开发自动化 这个系列的文章,专门探索软件开发过程自动化的实际应用,并教您何时 以及如何 成功地应用自动化。

    开发软件时,我的主要目标之一是:要么防止将缺陷引入代码库,要么限制缺陷的生存期;换言之,要尽早找到缺陷。很显然,越是了解如何编写更好的代码以及如何有效测试软件,就越能及早地捕捉到缺陷。我也很想要一张能发现潜在缺陷的安全之网。

    在本系列 八月份 的那期文章中,我得出了这样的结论:将检验工具集成到构建过程(例如,使用 Ant 或 Maven)中,能够建立起一种寻找潜在缺陷的方法。尽管这种方法使一致性成为可能并超越了 IDE,但它也有一点反作用。必须在本地构建软件或等待 Continuous Integration 构建的运行。如果使用 Eclipse 插件,就可以在通过 Continuous Integration 构建或集成 发现一些这样的冲突。这就促成了我称为渐进编程 的编程方式,在这种方式下,允许在编码过程中进行一定程度的质量检验 —— 再也不能比这个更早了!

    本文涵盖了我所认为的 “五大” 代码分析领域:

    • 编码标准
    • 代码重复
    • 代码覆盖率
    • 依赖项分析
    • 复杂度监控

    可以用接下来的几个灵活的 Eclipse 插件来揭示这些分析领域:

    • CheckStyle:用于编码标准
    • PMD 的 CPD:帮助发现代码重复
    • Coverlipse:测量代码覆盖率
    • JDepend:提供依赖项分析
    • Eclipse Metric 插件:有效地查出复杂度
    Eclipse 不是您的构建系统
    使用 Eclipse 插件与您将这些检验工具用于构建过程并不矛盾。事实上,您想要确保的是:下列使用 Eclipse 插件的规则就是应用到构建过程中的规则。

    安装 Eclipse 插件

    安装 Eclipse 插件再简单不过了,只需要几个步骤。在开始之前,最好把该插件下载站点的 URL 准备好。表 1 是本文用到的插件的列表:


    表 1. 代码改进插件和相应的下载站点 URL

    工具 目的 Eclipse 插件的 URL
    CheckStyle 编码标准分析 http://eclipse-cs.sourceforge.net/update/
    Coverlipse 测试代码覆盖率 http://coverlipse.sf.net/update
    CPD 复制/粘贴检验 http://pmd.sourceforge.net/eclipse/
    JDepend 包依赖项分析 http://andrei.gmxhome.de/eclipse/
    Metrics 复杂度监控 http://metrics.sourceforge.net/update

    知道了这些有用插件的下载地址后,安装插件就是一个极简单的过程。启动 Eclipse,然后遵循下列步骤:

    1. 选择 Help | Software Updates | Find and Install,如图 1 所示:



      图 1. 寻找并安装 Eclipse 插件
      寻找并安装 Eclipse 插件



    2. 选择 Search for new features to install 单选按钮,单击 Next

    3. 单击 New Remote Site,输入要安装的插件名和 URL(参见图 2),单击 OK,然后单击 Finish 来显示 Eclipse 更新管理器。



      图 2. 配置新的远程站点
      配置新的远程站点



    4. 在 Eclipse 更新管理器中,有一个查看插件各方面特性的选项。我通常选择顶级项,如图 3 所示。选择您需要的选项并单击 Finish。Eclipse 现在安装该插件。您需要重启 Eclipse 实例。



      图 3. 安装 Eclipse 插件
      安装 Eclipse 插件

    请遵循上述这些步骤来安装其他的 Eclipse 插件;只需改变插件名和相应的下载位置即可。





    回页首


    用 CheckStyle 校正标准

    代码库的可维护性直接影响着软件的整个成本。另外,不佳的可维护性还会让开发人员十分头痛(进而导致开发人员的缺乏)—— 代码越容易修改,就越容易添加新的产品特性。像 CheckStyle 这样的工具可以协助寻找那些可影响到可维护性、与编码标准相冲突的地方,比方说,过大的类、太长的方法和未使用的变量等等。

    有关 PMD
    另一个叫做 PMD 的开源工具提供的功能和 CheckStyle 类似。我偏爱 CheckStyle,但 PMD 也有很多执着的追随者,所以我建议您了解一下这个工具,毕竟它也颇受一些人的青睐。

    使用 Eclipse 的 CheckStyle 插件的好处是能够在编码过程中了解到源代码上下文的各种编码冲突,让开发人员更可能在签入该代码前真正处理好这些冲突。您也几乎可以把 CheckStyle 插件视作一个连续的代码复查工具!

    安装 CheckStyle 插件并做如下配置(参见图 4):

    1. 选择 Project,然后选择 Eclipse 菜单中的 Properties 菜单项。

    2. 选择 CheckStyle active for this project 复选框,单击 OK



      图 4. 在 Eclipse 中配置 CheckStyle 插件
      在 Eclipse 中配置 CheckStyle 插件

    Eclipse 重新构建工作空间,并在 Eclipse 控制台中列示已发现的编码冲突,如图 5 所示:


    图 5. Eclipse 中 CheckStyle 的代码冲突列表
    Eclipse 中 CheckStyle 的代码冲突列表

    使用 CheckStyle 插件在 Eclipse 内嵌入编码标准检验是一种很棒的方法,用这种方法可以在编码时 积极地改进代码,从而在开发周期的早期发现源代码中潜在的缺陷。这么做还有更多的好处,如节省时间、减少失败,也因此会减少项目的成本。没错,这就是一种积极主动的方式!





    回页首


    用 Coverlipse 确认覆盖率

    Coverlipse 是一个用于 Cobertura 的 Eclipse 插件,Cobertura 是一个代码覆盖率工具,可以用它来评估具有相应测试的源代码的比率。Cobertura 也提供一个 Ant 任务和 Maven 插件,但用 Cobertura,您可以在编写代码时 评估代码覆盖率。您见过这样的模式吗?

    通过选择 Eclipse 菜单项 Run 安装 Coverlipse 插件并将其和 JUnit 关联起来,该操作会显示一系列运行配置选项,例如 JUnit、SWT 应用程序和 Java™ 应用程序。右键单击它并选择 JUnit w/Coverlipse 节点中的 New。在这里,需要确定 JUnit 测试的位置,如图 6 所示:


    图 6. 配置 Coverlipse 以获取代码覆盖率
    配置 Coverlipse 以获取代码覆盖率

    一旦单击了 Run,Eclipse 会运行 Coverlipse 并在源代码(如图 7 所示)中嵌入标记,该标记显示了具有相关 JUnit 测试的代码部分:


    图 7. Coverlipse 生成的具有嵌入类标记的报告
    Coverlipse 生成的具有嵌入类标记的报告

    正如您所见,使用 Coverlipse Eclipse 插件可以更快地确定代码覆盖率。例如,这种实时数据功能有助于在将代码签入 CM 系统 更好地进行测试。这对渐进编程来说意味着什么呢?





    回页首


    用 CPD 捕捉代码重复

    Eclipse 的 PMD 插件提供了一项叫做 CPD(或复制粘贴探测器)的功能,用于寻找重复的代码。为在 Eclipse 中使用这项便利的工具,需要安装具有 PMD 的 Eclipse 插件,该插件具有 CPD 功能。

    为寻找重复的代码,请用右键单击一个 Eclipse 项目并选择 PMD | Find Suspect Cut and Paste,如图 8 所示:


    图 8. 使用 CPD 插件运行复制粘贴检验
    使用 PMD/CPD 插件运行复制粘贴检验

    一旦运行了 CPD,您的 Eclipse 根目录下就会创建出一个 report 文件夹,其中包含一个叫做 cpd.txt 的文件,文件中列示了所有重复的代码。图 9 中是一个 cpd.txt 文件的例子:


    图 9. Eclipse 插件生成的 CPD 文本文件
    Eclipse 插件生成的 CPD 文本文件

    靠人工来寻找重复的代码是一项挑战,但使用像 CPD 这样的插件却能在编码时轻松地发现重复的代码。





    回页首


    使用 JDepend 进行依赖项检查

    JDepend 是个可免费获取的开源工具,它为包依赖项提供面向对象的度量值,以此指明代码库的弹性。换句话说,JDepend 可有效测量一个架构的健壮性(反之,脆弱性)。

    除了 Eclipse 插件,JDepend 还提供一个 Ant 任务、Maven 插件和一个 Java 应用程序,用以获取这些度量值。对于相同的信息,它们有着不同的传递机制;但 Eclipse 插件的特别之处和相应优点是:它能以更接近源代码(即,编码时)的方式传递这条信息。

    图 10 演示了使用 Eclipse JDepend 插件的方法:通过右键单击源文件夹并选择 Run JDepend Analysis。一定要选择一个含源代码的源文件夹;否则看不到此菜单项。


    图 10. 使用 JDepend Analysis 分析代码
    使用 JDepend Analysis 分析代码

    图 11 显示了运行 JDepend Analysis 时生成的报告。左边显示包,右边显示针对每个包的依赖项度量值。


    图 11. Eclipse 项目中的包依赖项
    Eclipse 项目中的包依赖项

    正如您所见,JDepend 插件提供了有助于不断观察架构可维护性变化的大量信息 —— 这其中最大的好处是您可以在编码时看到这些数据。





    回页首


    用 Metrics 测量复杂度

    “五大”代码分析最后的一项是测量复杂度。Eclipse 提供一种叫做 Metrics 的插件,使用该插件可以进行许多有用的代码度量,包括圈复杂度度量,它用于测量方法中惟一路径的数目。

    安装 Metrics 插件并重启 Eclipse;然后遵循下列步骤:

    1. 右键单击您的项目并选择 Properties 菜单。在结果窗口中,选择 Enable Metrics plugin 复选框并单击 OK,如图 12 所示:



      图 12. 为项目配置 Metrics
      为项目配置 Metrics



    2. 从 Eclipse 中选择 Window 菜单打开 Metrics 视图,然后选择 Show View | Other...

    3. 选择 Metrics | Metrics View 打开如图 13 中显示的窗口。您需要使用 Java 透视图并重新构建项目,从而显示这些度量值。



      图 13. 打开 Eclipse 中的 Metrics View
      打开 Eclipse 中的 Metrics View



    4. 单击 OK 来显示如图 14 中的窗口。

      在此例中,我正在查看一个单独方法的圈复杂度。真正妙的是您可以双击 Metrics 列表中的方法,该插件会在 Eclipse 编辑器中为此方法打开源代码。这就让修正变得超级简单(如果需要的话)!



      图 14. 查看方法的圈复杂度
      查看方法的圈复杂度

    正如我之前提到过的,Eclipse Metrics 插件还提供了许多功能强大的度量值,有助于您在开发软件的过程中改进代码 —— 可见,它是一个渐进编程意义上的插件!





    合适的才是最好的

    正如您从本文中看到的那样,将“五大”测量方法,即编码标准、代码重复、代码覆盖率、依赖项分析和复杂度监控,用于改进代码质量十分重要。但适合您 的才是好的。请记住还有其他许多可用的 Eclipse 插件(比如 PMD 和 FindBugs)能够帮助您在开发周期的早期改进代码质量。不管您想要的工具或偏爱的方法是什么,重要的是:行动起来去积极改进代码质量并让手工代码检 验的过程变得更加有效。我估计您使用这些插件一段时间后,就再也离不开它们了。

    posted @ 2008-04-30 13:44 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(277) | 评论 (0)编辑 收藏

    SOA: Service Oriented Architecture 即以服务为导向的软件开发思想。它的本质市场需求是实现服务与技术的完全分离。

    SOA同Web Service的根本区别:
    两者的共同点:1、都提供服务。
                  2、服务接口都是基于开发的。
                  3、服务接口和服务的具体实现都是分离的。
        Web Service是构成SOA的核心组件。Web Service 服务接口需要绑定具体实现服务的服务组件来实现服务,它对具体的服务实现完成了封装,实现了服务的透明化,客户端不需要知道服务是如何实现的,但是Web Service组件本身是知道服务是如何实现的,另外客户端调用Web Service组件时,需要知道Web Service的具体位置和传输协议,这些都城会造成一定的不灵活性,它只是实现了一定程度上的抽象。
        SOA架构平台只和服务接口进行绑定,对服务接口进行绑定,对服务接口实现了封装,实现了服务接口的透明化,服务位置的透明化,服务传输协议的透明化。SOA实现了最高程度上的抽象化。
     

    posted @ 2008-04-23 17:33 存鹰之心于高远,取鹰之志而凌云,习鹰之性以涉险,融鹰之神在山巅. 阅读(129) | 评论 (0)编辑 收藏

    仅列出标题
    共6页: 上一页 1 2 3 4 5 6 下一页