糊言乱语

志未半斤, 才无八两. 有苦有乐, 糊涂过活。
posts - 25, comments - 7, trackbacks - 0, articles - 42
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2007年10月9日

image

posted @ 2008-07-11 11:25 Stanley Sun 阅读(327) | 评论 (0)编辑 收藏

众所周知在计算机中所有的数据都是以二进制的方式存储的。不管是int,String,float等等不同的数据类型,最终都会保存为01的形式。那么为什么要使用这种方式储存数据呢?

因为计算机是一种电子设备,由复杂的电子元器件组合而成,一个电子元器件有带电和不带电两种状态,通常我们将带电状态表示为数值1,不带电状态表示为数值0,多个这样的元器件的组合可以表示更多状态,也就是可以表示更多的数据,如000表示0,001表示1,010表示2,011表示3,依此类推,111表示 7,一个元器件可表示一位(bit)数据,这种表示数据的方式就叫二进制。
在实际的电子设备中,我们将8个这样的元器件形成一个单元,这样的单元叫一个字节(byte),一个字节能表示多少个数呢?表示数值的范围是0-255。
一个字节由8个二进位组成,其中最右边的一位称为“最低有效位”或“最低位”,最左边的一位称为“最高有效位”或“最高位”。每一个二进位的值是0或1。

二进制计数的缺点:书写太长,容易出错,一般计算机的数据位数都是4的整数倍,所以,在计算机里通常采用16进制计数法。用数字可以表示各种信息,计算机里只有数值,当你在内存中看到一个数值时,这个数值可能代表各种意义,生活中的数值也可以代表其他意义,如1234可以代表密码,存款额,电报信息,根据上下线索,我们就能够知道这数值代表的意义

 

但是在Java中到底是如何去保存数据的呢?下面我就以int数据类型为例说明Java的方式。

大家都知道在Java中规定1 int = 4 byte, 1 byte = 8 bit。以此推理那么1个int在计算机中就是以4 * 8 = 32位(bit)的方式存储的。而又由于java中的int是属于有符号类型(Java中不存在unsigned类型),所以32位的高一位是符号位,由此可以推理出int的储存大小区间

Integer.MAX_VALUE = 2147483647(十进制) = 1111111 11111111 11111111 11111111(二进制)
Integer.MIN_VALUE = -2147483648(十进制) = 10000000 00000000 00000000 00000000(二进制)

现在我们知道了二进制的概念了,但是其实二进制我想我们想象的那么单纯的表示的,他们是不同的表现方式如:原码,反码,补码

  • 原码
    将最高位作为符号位(以0代表正,1代表负),其余各位代表数值本身的绝对值(以二进制表示)。
                为了简单起见,我们用1个字节来表示一个整数。
                +7的原码为: 00000111
                 -7的原码为: 10000111
  • 反码
          一个数如果为正,则它的反码与原码相同;一个数如果为负,则符号位为1,其余各位是对原码取反。
                为了简单起见,我们用1个字节来表示一个整数。
                +7的反码为: 00000111
                 -7的反码为: 11111000
  • 补码
        利用溢出,我们可以将减法变成加法。
        对于十进制数,如果从9得到结果5,可以用减法:
             9-4=5
          因为4+6=10,我们将6作为4的补数,将上式的减法改写为加法:
             9+6=15
          去掉高位1(也就是减去10),得到结果5。
          对于16进制数,如果从C得到结果5,可以用减法:
             C-7=5
          因为7+9=16,我们将9作为7的补数,将上式的减法改写为加法:
             C+9=15
          去掉高位1(也就是减去16),得到结果5。
          在计算机中,如果我们用1个字节表示一个数,一个字节有8位,超过8位就进1,在内存中情况为:
               1 00000000
        进位1被丢弃。
        一个数如果为正,则它的原码、反码、补码相同;一个数如果为负,则符号位为1,其余各位是对原码取反,然后整个数加1。
                为了简单起见,我们用1个字节来表示一个整数。
                +7的补码为: 00000111
                -7的补码为:第一步:11111000 (符号位为,其余各位取反)
                                      第二步:11111001 (整个数加1)
               +0的补码:00000000;
               -0的补码:11111111;(第一步)
                              100000000;(第二步)
    已知一个负数的补码,将其转换为十进制数,步骤:
          1、先对各位取反;
          2、将其转换为十进制数;
          3、加上负号,再减去1。
          例如:
          11111010,最高位为1,是负数,先对各位取反得00000101,转换为十进制数得5,加上负号得-5,再减1得-6。
  •  

    那么我们就知道了1与-1的二进制形式分别为0000000 00000000 00000000 00000001和11111111 11111111 11111111 11111111(Java中的数据是以补码的形式储存的)了。那么现在我们知道了数据是如何储存的了。那么计算机是如何利用这些数据进行计算的呢?我们知道在计算机的CPU中只有一个加法器,所有的运算都是需要它进行的。所以在计算机里所有的加减乘除都是转换成加法来进行运算的。那么它们是怎么转换的呢?下面我们介绍一下二进制的运算操作

  • 位运算符
    为了方便对二进制位进行操作,Java给我们提供了四个二进制位操作符:
    &          按位与
    |           按位或
    ^          按位异或
    ~          按位取反
  • 按位
        一个房间里有两个开关控制房间的灯的明暗。当两个开关同时处于打开状态时,灯才能亮。
         开关1                   开关2                         灯的状态
           关                         关                              暗
          开                          关                              暗
          关                          开                              暗
          开                          开                              亮
    结论:按位与,只有壹(1)壹(1)为1。
  • 按位
        一个房间里有两个开关控制房间的灯的明暗。当任何一个开关处于打开状态时,灯就能亮。
        开关1                     开关2                     灯的状态
           关                         关                              暗
          开                          关                              亮
          关                          开                              亮
          开                          开                              亮
    结论:按位或,只有零(0)零(0)为0。
  • 按位异或
        一个房间里有两个开关控制房间的灯的明暗。当两个开关处于不同状态时,灯就能亮。
       开关1                    开关2                       灯的状态
          关                          关                              暗
          开                          关                              亮
          关                          开                              亮
          开                          开                              暗
    结论:按位异或,只有零(0)壹(1)或壹(1)零(0)为1。
  • 按位取反
    结论:对二进制数按位取反,即0变成1,1变成0。
  • Java中有三个移位运算符
    左移:<<              (相当于 乘以2)
    带符号右移:>>     (相当于 除以2)
    无符号右移:>>>
      数            x                   x<<2                 x>>2              x>>>2
    17      00010001    00 01000100      00000100 01     00000100 01
    -17     11101111     11 10111100      11111011 11     00111011 11
  • posted @ 2008-06-14 15:25 Stanley Sun 阅读(1065) | 评论 (0)编辑 收藏

    概念:

    1.数字摘要:解决在安全的通信环境下,保证信息的唯一的一种方式。通常使用MD5/SHA-1等算法完成摘要。一般比如大家在网上下载软件光盘时都会看到一个MD5值就是起到这个数字摘要的作用。在网络的环境中发送者把消息和数字摘要一同发送给接收者,接收者使用发送者相同的算法对消息加密,看是否与发送者发送过来的数字摘要相同,如果相同就证明消息没有给篡改过。下面是一个最为简单的示例:

    import java.security.*;
    public class myDigest {
      public static void main(String[] args)  {
        myDigest my=new myDigest();
        my.testDigest();
      }
      public void testDigest()
      {
       try {
         String myinfo="我的测试信息";
        //java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5");
          java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");
          alga.update(myinfo.getBytes());
          byte[] digesta=alga.digest();
          System.out.println("本信息摘要是:"+byte2hex(digesta));
          //通过某中方式传给其他人你的信息(myinfo)和摘要(digesta) 对方可以判断是否更改或传输正常
          java.security.MessageDigest algb=java.security.MessageDigest.getInstance("SHA-1");
          algb.update(myinfo.getBytes());
          if (algb.isEqual(digesta,algb.digest())) {
             System.out.println("信息检查正常");
           }
           else
            {
              System.out.println("摘要不相同");
             }
       }
       catch (java.security.NoSuchAlgorithmException ex) {
         System.out.println("非法摘要算法");
       }
      }
      public String byte2hex(byte[] b) //二行制转字符串
        {
         String hs="";
         String stmp="";
         for (int n=0;n<b.length;n++)
          {
           stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
           if (stmp.length()==1) hs=hs+"0"+stmp;
           else hs=hs+stmp;
           if (n<b.length-1)  hs=hs+":";
          }
         return hs.toUpperCase();
        }
    }
    

    2.电子签名:对数据信息的发生者身份的认定,它是一种抽象的概念而不是一种具体技术。实现电子签名的技术手段目前有多种,比如基于公钥密码技术的数字签名;或用一个独一无二的以生物特征统计学为基础的识别标识,例如手印、声音印记或视网膜扫描的识别;手书签名和图章的电子图象的模式识别;表明身份的密码代号(对称算法);基于量子力学的计算机等等。


    3.数字签名:所谓数字签名就是利用通过某种密码运算生成的一系列符号及代码组成电子密码进行"签名",来代替书写签名或印章,对于这种电子式的签名在技术上还可进行算法验证,其验证的准确度是在物理世界中与手工签名和图章的验证是无法相比的。一般实现数字签名的方法是通过生成的密钥对的私钥对用户生成的数字消息进行DSA(Digital Signature Algorithm (DSA)是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard))加密实现的。实现代码如下:

       */
     import java.security.*;
     import java.security.spec.*;
    public class testdsa {
      public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception {
            testdsa my=new testdsa();
            my.run();
      }
      public void run()
      {
      //数字签名生成密钥
      //第一步生成密钥对,如果已经生成过,本过程就可以跳过,对用户来讲myprikey.dat要保存在本地
      //而mypubkey.dat给发布给其它用户
       if ((new java.io.File("myprikey.dat")).exists()==false) {
           if (generatekey()==false) {
               System.out.println("生成密钥对败");
               return;
              };
            }
    //第二步,此用户
    //从文件中读入私钥,对一个字符串进行签名后保存在一个文件(myinfo.dat)中
    //并且再把myinfo.dat发送出去
    //为了方便数字签名也放进了myifno.dat文件中,当然也可分别发送
      try {
      java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
      PrivateKey myprikey=(PrivateKey)in.readObject();
      in.close();
     // java.security.spec.X509EncodedKeySpec pubX509=new java.security.spec.X509EncodedKeySpec(bX509);
     //java.security.spec.X509EncodedKeySpec pubkeyEncode=java.security.spec.X509EncodedKeySpec
      String myinfo="这是我的信息";    //要签名的信息
      //用私钥对信息生成数字签名
      java.security.Signature signet=java.security.Signature.getInstance("DSA");
      signet.initSign(myprikey);
      signet.update(myinfo.getBytes());
      byte[] signed=signet.sign();  //对信息的数字签名
      System.out.println("signed(签名内容)="+byte2hex(signed));
     //把信息和数字签名保存在一个文件中
      java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
      out.writeObject(myinfo);
      out.writeObject(signed);
      out.close();
      System.out.println("签名并生成文件成功");
      }
      catch (java.lang.Exception e) {
        e.printStackTrace();
        System.out.println("签名并生成文件失败");
      };
      //第三步
      //其他人通过公共方式得到此户的公钥和文件
      //其他人用此户的公钥,对文件进行检查,如果成功说明是此用户发布的信息.
      //
      try {
       java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
       PublicKey pubkey=(PublicKey)in.readObject();
       in.close();
       System.out.println(pubkey.getFormat());
       in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
       String info=(String)in.readObject();
       byte[] signed=(byte[])in.readObject();
       in.close();
      java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
      signetcheck.initVerify(pubkey);
      signetcheck.update(info.getBytes());
      if (signetcheck.verify(signed)) {
      System.out.println("info="+info);
       System.out.println("签名正常");
      }
      else  System.out.println("非签名正常");
      }
      catch (java.lang.Exception e) {e.printStackTrace();};
      }
      //生成一对文件myprikey.dat和mypubkey.dat---私钥和公钥,
      //公钥要用户发送(文件,网络等方法)给其它用户,私钥保存在本地
      public boolean generatekey()
      {
        try {
      java.security.KeyPairGenerator  keygen=java.security.KeyPairGenerator.getInstance("DSA");
     // SecureRandom secrand=new SecureRandom();
     // secrand.setSeed("tttt".getBytes()); //初始化随机产生器
     // keygen.initialize(576,secrand);     //初始化密钥生成器
      keygen.initialize(512);
      KeyPair keys=keygen.genKeyPair();
    //  KeyPair keys=keygen.generateKeyPair(); //生成密钥组
      PublicKey pubkey=keys.getPublic();
      PrivateKey prikey=keys.getPrivate();
      java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
      out.writeObject(prikey);
      out.close();
      System.out.println("写入对象 prikeys ok");
      out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
       out.writeObject(pubkey);
       out.close();
       System.out.println("写入对象 pubkeys ok");
       System.out.println("生成密钥对成功");
       return true;
      }
      catch (java.lang.Exception e) {
       e.printStackTrace();
       System.out.println("生成密钥对失败");
       return false;
       };
      }
      public String byte2hex(byte[] b)
        {
         String hs="";
         String stmp="";
         for (int n=0;n<b.length;n++)
          {
           stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
           if (stmp.length()==1) hs=hs+"0"+stmp;
           else hs=hs+stmp;
           if (n<b.length-1)  hs=hs+":";
          }
         return hs.toUpperCase();
        }
    }    把他的公钥的信息及签名发给其它用户
    


    4.PKI(公钥基础设施):

    posted @ 2007-12-05 22:09 Stanley Sun 阅读(533) | 评论 (1)编辑 收藏

    安装完成之后打开window->show views-Task Repositories,界面如下图:


    在空白处右键点击add task repository添加知识库,如图:

    选中Jira,下一步:


    server中填写Jira的地址(http://ycfd.3322.org:88/jira),label随便填写,User ID和Password就是你在Jira上注册的帐号和密码了,填写完毕之后点Validate Setting,验证成功之后点完成即可。

    在添加完repository后,会弹出添加query界面。如图:

    选择create query using form后点击next,进入query设置界面,如图:


    在project中选中fms后点击finish。这样就完成了各项设置
    之后打开tasklist视图:window->show view->other->mylyn->task list

    点击OK,后打开task list视图,如图:


    在Task List中你可以看到你的项目中的问题和任务等,双击Task会显示该Task的详细情况:

    在Task List中还能新建Task并提交到Jira,这里就不多说了,大家自己尝试一下。

    posted @ 2007-12-03 16:38 Stanley Sun 阅读(1350) | 评论 (0)编辑 收藏

    mylyn是一款开源的基于eclipse开发平台的任务管理组件,可以制定自己的本地任务及在远程服务器(其中包括Bugzilla、Trac 和 JIRA等)中的远程任务。对于我们现在的项目,使用mylyn就可以方便我们直接的浏览在JIRA中的任务,而不必经常的登录JIRA平台了。提高了大家的工作效率。

    由于mylyn与在我们现在在项目中使用的eclipse开发平台中springide插件有冲突问题,所以首先大家需要把springide插件从eclipse中卸载。步骤如下:

    1.在eclipse安装目录下找到一个名为links的文件夹,在这个文件夹中删除Springide.link文件。

    2.启动eclipse,不过与平常不同的是需要在eclipse启动命令中加入-clean参数。可以直接加入到eclipse快捷方式的目标项中。

    此时eclipse会把springide插件卸载,之后我们就可以安装mylyn插件了。在开始安装mylyn之前,大家需要下载附件中的如下三个文件:mylyn-2.1-e3.3.zip,mylyn-2.1-extras.zip,springide_updatesite_2.0.1_v200708152145.zip

    步骤如下:

    1.设置本地插件归档:进入help->software updates->find and install菜单后,选择search for new features to install后点击next

    进入install界面,如下图:


    把下载的三个zip归档加入后,点击finish.

    2.在弹出的updates窗口中选中刚才加入的三个归档,并把springide->integrations->spring ide ajdt integrations去掉后,如下图:

    之后进入授权界面,选择i accept后next,如图:

    3.在弹出的verification窗口中点击install all开始安装,如图:

    之后提示是否重启eclipse,点击是。

    posted @ 2007-12-03 16:38 Stanley Sun 阅读(5508) | 评论 (0)编辑 收藏

    EJBCA是一个全功能的CA系统软件,它基于J2EE技术,并提供了一个强大的、高性能并基于组件的CA。EJBCA兼具灵活性和平台独立性,能够独立使用,也能和任何J2EE应用程序集成。 

    所需软件:

    1.jdk 1.5 下载地址:http://java.sun.com/

    2.jboss-4.2.0.GA 下载地址:http://www.jboss.com/

    3.jce_policy-1_5_0:下载地址:http://java.sun.com/

    4.apache-ant-1.7.0:http://ant.apache.org/

    5.oracle 10G:

    6.ojdbc14.jar:

    7.ejbca 3.4.5: 下载地址:http://ejbca.sourceforge.net

    安装步骤:

    1.安装jdk,jboss,ant,oracle,并把jce,jdbc解压分别解压到%JAVA_HOME%\jre\lib\security\与%JBOSS_HOME%\server\default\lib\。

    2.设置环境变量,我的配置为:

    ANT_HOME=C:\tool\ejbca\apache-ant-1.7.0-bin\apache-ant-1.7.0
    EJBCA_HOME=C:\tool\ejbca\ejbca_3_5_2\ejbca_3_5_2
    JBOSS_HOME=C:\tool\ejbca\jboss-4.2.0.GA\jboss-4.2.0.GA
    JAVA_HOME=C:\Program Files\Java\jdk1.6.0_03
    path=%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\tool\ejbca\apache-ant-1.7.0-bin\apache-ant-1.7.0\bin;C:\tool\ejbca\jboss-
    4.2.0.GA\jboss-4.2.0.GA\bin;C:\Program Files\Java\jdk1.6.0_03\bin
    classpath=C:\Program Files\Java\jdk1.6.0_03\lib\tools.jar

    3.在数据库中创建表空间并添加用户EJBCA,在ORACLE中的代码为:

      创建表空间:

      CREATE TABLESPACE EJBCA DATAFILE 'EJBCA.dbf' SIZE 100m ;

      创建用户:

    CREATE user EJBCA   identified by "EJBCA"   default tablespace USERS   temporary tablespace TEMP   profile DEFAULT;
    -- Grant/Revoke role privileges
    grant aq_administrator_role to EJBCA with admin option;
    grant dba to EJBCA with admin option;
    -- Grant/Revoke system privileges
    grant unlimited tablespace to EJBCA with admin option;

    4.删除所有的ejbca\adminweb中的jsp(%EJBCA_HOME%\src\adminweb*.jsp)中的

    <%@ page pageEncoding="ISO-8859-1"%>

      以解决中文乱码问题,下一步也是解决此类问题。 

    5.把%EJBCA_HOME%\conf\ejbca.properties.sample改名为ejbca.properties,并在ejbca.properties添加如下一行:

    web.contentencoding=GBK

    6.把%EJBCA_HOME%\conf\database.properties.sample改名为database.properties,并更改相应的数据库配置。如下是我的配置:

    datasource.jndi-name=EjbcaDS
    datasource.jndi-name-prefix=java:/
    database.name=oracle
    datasource.mapping=Oracle9i
    database.url=jdbc:oracle:thin:@127.0.0.1:1521:ORCL
    database.driver=oracle.jdbc.driver.OracleDriver
    database.username=ejbca
    database.password=ejbca

      注:datasource.mapping需要选择与oracle实际版本最接近的版本。 

    7.在%EJBCA_HOME%\bin中,通过cmd运行ant bootstrap。

    8.启动jboss,在%JBOSS_HOME%\bin,通过cmd运行run。

    9.在%EJBCA_HOME%\bin中,通过cmd运行ant install。

    10.关闭jboss,并在在%EJBCA_HOME%\bin中,通过cmd运行ant deploy。

    11.再次启动jboss,在%JBOSS_HOME%\bin,通过cmd运行run。

    13.导入在%EJBCA_HOME%\p12目录中superadmin.p12,默认密码为ejbca。

    注:在第7步时,如出现ANT失败,可能是由于ejbca的版本问题,推荐使用ejbca3.4.5。

    访问地址:http://localhost:8080/ejbca/

    posted @ 2007-12-03 16:33 Stanley Sun 阅读(1607) | 评论 (0)编辑 收藏

    一般在有着1年半以上的程序员基本上都是知道这个厉害的东西的,它对字符串处理的能力可以说是生猛无比。虽然大家都在使用(有时候在开发的Code中,有时候是在我们自己心爱的Editor里),但是我相信大部分人对这里禽兽的了解程度只是停留在会用的层次上。下面我对它进行一下详细的说明。

    正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。

    1956 年, 一位叫 Stephen Kleene 的美国数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。

    随后,发现可以将这一工作应用于使用Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson是Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的qed 编辑器。

    如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。

    使用正则表达式
    在典型的搜索和替换操作中,必须提供要查找的确切文字。这种技术对于静态文本中的简单搜索和替换任务可能足够了,但是由于它缺乏灵活性,因此在搜索动态文本时就有困难了,甚至是不可能的。

    使用正则表达式,就可以:

    测试字符串的某个模式。例如,可以对一个输入字符串进行测试,看在该字符串是否存在一个电话号码模式或一个信用卡号码模式。这称为数据有效性验证。
    替换文本。可以在文档中使用一个正则表达式来标识特定文字,然后可以全部将其删除,或者替换为别的文字。
    根据模式匹配从字符串中提取一个子字符串。可以用来在文本或输入字段中查找特定文字。
    例如,如果需要搜索整个 web 站点来删除某些过时的材料并替换某些HTML 格式化标记,则可以使用正则表达式对每个文件进行测试,看在该文件中是否存在所要查找的材料或 HTML 格式化标记。用这个方法,就可以将受影响的文件范围缩小到包含要删除或更改的材料的那些文件。然后可以使用正则表达式来删除过时的材料,最后,可以再次使用正则表达式来查找并替换那些需要替换的标记。

    许多种工具都支持正则表达式(文本编辑器、文字处理软件、系统工具、数据库引擎,等等),不过,要想充分挖掘正则表达式的能力,还是应当将它作为编程语言的一部分。例如Java、JScript、Visual Basic、VBScript、JavaScript、ECMAScript、C、C++、C#、elisp、Perl、Python、Tcl、Ruby、PHP、sed和awk。事实上,在一些用上述语言编写的程序中,正则表达式扮演了极其重要的角色。
    正则表达式能够得到众多语言和工具的支持是有原因的:它们极其有用。从较低的层面上来说,正则表达式描述的是一串文本(a chunk of text)的特征。大家可以用它来验证用户输入的数据,或者也可以用它来检索大量的文本。从较高的层面上来说,正则表达式容许用户掌控他们自己的数据——控制这些数据,让它们为自己服务。掌握正则表达式,就是掌握自己的数据。

    可见它的重要性,难怪每款编辑器和编程语言不同程度的实现了它,使得普通用户和开发人员受益不浅。

    posted @ 2007-11-07 23:02 Stanley Sun 阅读(423) | 评论 (1)编辑 收藏

     

    treeview 

    在开发B/S程序时,我们经常会使用到一些页面级的效果控件。比如:树形目录,ComboBox和一些其他的控件,由于这些控件的存在使得我们的程序异常的夺目。但是在开发这些控件的时候或多或少的都会比较麻烦。而大部分的程序员是使用发布的一些开源的JS控件来减轻工作量而且也使得自己的程序健壮。下面我介绍一个在开源社区中赫赫有名的树形控件:TreeView。

    首先介绍一下TreeView,TreeView原名是FolderTree,是一款比较早就出世的树形JS控件,当时是由个人开发的,之后由公司购买了。但是现在还可以免费使用。

    TreeView 有两个JS文件和一些资源文件组成。两个JS文件分别是:主要实现功能的ftiens4.js和实现多浏览器支持的ua.js文件。只有我们在开发的页面中加入如上两个文件的话就可以开发如上图所显示的树形目录了。代码如下:

    <html>

    <head>

    <script type="text/javascript" src="../treeview/ftiens4.js" ></script>

    <script type="text/javascript" src="../treeview/ua.js" ></script>

    <script type="text/javascript">

    //TreeView 环境变量

    BUILDALL = 0 //创建所有的节点对象 0:延时创建 1:立即创建
    GLOBALTARGET = 'R' //节点触发时的目标 'B':打开新窗口 'R':右边的Frame 'S':当前Frame 'T':当前浏览器窗口
    HIGHLIGHT = 0 //高亮显示当前选中的节点 0:不高亮显示 1:高亮显示
    HIGHLIGHT_BG = 'blue' //高亮显示的背景颜色
    HIGHLIGHT_COLOR = 'white' //高亮显示的颜色
    ICONPATH = '' //指定节点的显示图标,使用URL方式,而且必须用"/"结尾 如:http://www.x.com/y/
    PRESERVESTATE = 0 //保存TreeView的状态到Cookie中,当再次显示的时候会自动的回置状态 0:不保存 1:保存
    STARTALLOPEN = 0 //默认打开所有节点 0:只打开根节点 1:打开所以节点
    USEFRAMES = 1 //页面是否使用了Frame,注意:如果未使用Frame一定要设置此参数 0:未使用 1:使用了
    USEICONS = 1 //是否使用图标 0:不显示图标 1:显示图标
    USETEXTLINKS = 0 //节点文字是否为链接 0:否 1:是
    WRAPTEXT = 0 //节点显示超出一行时是否折行 0:不折行 1:折行

    foldersTree = gFld("test", "") //创建一个名为"test"的根节点
    foldersTree.treeID = "t1" //设置test节点的唯一编号为"t1"


    aux1 = insFld(foldersTree, gFld("Day of the week", "b.html")) //在根节点中加入一个名为"Day of the week"的子节点,当点击的时候打开b.html
    aux1.addChildren([["1","1.html"],["2","2.html"],["3","3.html"],["4","4.html"],["5","5.html"]])  //在aux1节点中连续加入1,2,3,4,5节点,并相应的打开1.html,2.html,3.html,4.html,5.html.

    aux2 = insFld(foldersTree, gLnk("R","Day of the week2", "b.html")) //在根节点中加入名为"Day of the week2"的节点,当点击的时候在右侧的frame中打开b.html
    aux3 = insDoc(foldersTree, gLnk("R","<input type=\"checkbox\">Day of the week3", "c.html")) //在根节点中加入名为"Day of the week3"并带有复选框的节点,当点击的时候在右侧的frame中打开c.html

    </script>

    </head>

    <body>

    <A style="font-size:7pt;text-decoration:none;color:silver" href="http://www.treemenu.net/" target=_blank>Javascript Tree Menu</A>

    <script type="text/javascript">

           initializeDocument();//构造TreeView

    </script>

    </body>

    </html>

    TreeView中主要的方法:

    gFld(Title, Link);//创建节点 例:gFld("Test A", "javascript:parent.op()")

    Argument

    Title
    Specifies the text that appears in the folder name. This text can include simple HTML tags, such as enclosing formatting tags (i, b, div, and so on). It can even include an img tag if you want to place a small icon in the node name, such as a "new!" icon for example.

    Link
    Specifies an optional URL. The URL can be a simple file name like demoFramesetRightFrame.html or a string with protocol, domain, path, and file name like http://www.treeview.net/treemenu/demopics/beenthere_europe.gif.

     

    gLnk(Target, Title, Link);//创建一个带有链接的节点 例:gLnk("B", "My File", http://www.mysite.com/MyFile.doc)

    Argument

    Target
    Configures the target location for the link. Specify one of the following values:
    "R": Open the document in the right frame (a frame named basefrm)
    "B": Open the document in a new window
    "T": Open the document in the current browser window, replacing the frameset if one exists
    "S": Open the document in the current frame, replacing the tree
    Note: This argument is case sensitive; make sure to use uppercase letters.

    Title
    Specifies the text that appears in the link. This text can include simple HTML tags, such as enclosing formatting tags (i, b, div, and so on). It can even include an img tag if you want to place a small icon in the node name, such as a "new!" icon for example.

    Link
    Specifies the URL of the document. This can be an absolute URL or a relative URL. Do not enter any other information in this string; adding a target parameter or an event handler will not work.

     

    insFld(Parent Folder, Child Folder); //在父节点中插入一个子节点 例:aux1 = insFld(foldersTree, gFld("Europe", "http..."))

    Argument

    Parent Folder
    Specifies the parent folder. That is, this argument specifies the folder node in which you want to place the other folder node.

    Child Folder
    Specifies the child folder. That is, this argument specifies the folder node that you want to place under the parent folder node.

     

    insDoc(Parent Folder, Document Node); //在节点中加入一个Dom对象 例:insDoc(aux2, gLnk("S", "Boston", "..."))

    Argument

    Parent Folder
    Specifies the parent folder. That is, this argument specifies the folder node in which you want to place the document node.

    Document Node
    Specifies the document node. That is, this argument specifies the document node that you want to place in the parent folder node

     

    更多的参考信息到 http://www.treeview.net/tv/instructions.asp

    posted @ 2007-11-07 17:59 Stanley Sun 阅读(7500) | 评论 (2)编辑 收藏

        在一年以前一个客户给我推荐一款文件管理软件,名叫Total Commander,以下简称totalcmd,据说在欧美国家相当的流行。当时给这个客户开发程序是需要打开很多个资源管理器,在这么多的管理器中相互的拷贝文件真是一件非常头疼的事情。借助totalcmd可以非常好的完成文件的管理,拷贝、删除,新建,乃至服务的管理等等。值得一提的就是totalcmd可以通过注入插件实现totalcmd本身不可以完成的功能,这也是它很大的一个亮点。

    在使用的一年多的totalcmd后,也有了一些自己的使用习惯和独爱的插件,我将罗列如下:
    使用习惯:
    1.把F2快捷键指定到cm_RenameOnly命令上。
    2.把Ctrl+G快捷键指定到cm_FocusCmdLine命令上。
    3.在开始菜单下建立一个功能,实现cm_SwitchHidSys功能,可以显示隐藏/系统文件。
    4.指定totalcmd只能运行一个实例。
    5.最小化到系统托盘里。
    6.编辑时默认打开的编辑器为ChoiceEditor。这个插件很难找。
    7.把快速查找定义为Letters with search dialog
    8.当改变驱动盘符的时候直接定位的驱动的根目录下

    独爱插件:
    1.Choice Editor:默认编辑选择器。
    2.File Redirector:临时目录,这个插件非常有用,强烈推荐。不过安装的时候需要下载一个msvcr70.dll的文件放到你的c:\windows\system32目录下。文件的下载地址:http://www.dll-files.com/dllindex/dll-files.shtml?msvcr70
    3.UnInstTC:集成在totalcmd中添加/删除程序,支持搜索。
    4.Office:可以通过Ctrl+Q快速查看Office系列软件格式。

    注:本人只是一个totalcmd的爱好者,而不是在此为他去大广告。

    posted @ 2007-10-31 11:07 Stanley Sun 阅读(660) | 评论 (0)编辑 收藏

     



            AutoSuggest是通过AJAX技术实现的一种类似于ComboBox之类的输入框,当输入一些提示字符后,AS会自动的把输入框中的Value通过AJAX发送到Server中,Server自定义的解析发送的数据,然后把返回数据通过XMLJSON方式返回到AS中。AS再根据Server返回的标准格式的数据构建出提示候选框,当用鼠标或键盘选中候选项后填充到输入框中。在写这篇手册的时候,AutoSuggest的最新版本是autosuggest_v2.1.3。基本的运行原理如上。

    AutoSuggest的主要的物理文件有:bsn.AutoSuggest_2.1.3.jsautosuggest_inquisitor.css。其他的还有一些图片资源文件,一个测试html与一个test.php的服务器段页面。结构如下:
        

    │ .DS_Store

    │ ._.DS_Store

    │ ._bsn.AutoSuggest_2.
    1.3.html

    │ ._test.php

    │ bsn.AutoSuggest_2.
    1.3.html

    │ test.php



    ├─css

    │ │ .DS_Store

    │ │ ._.DS_Store

    │ │ autosuggest_inquisitor.css

    │ │

    │ └─img_inquisitor

    │      │ .DS_Store

    │      │ ._.DS_Store

    │      │ ._as_pointer.gif

    │      │ ._hl_corner_bl.gif

    │      │ ._hl_corner_br.gif

    │      │ ._hl_corner_tl.gif

    │      │ ._hl_corner_tr.gif

    │      │ ._ul_corner_bl.gif

    │      │ ._ul_corner_br.gif

    │      │ ._ul_corner_tl.gif

    │      │ ._ul_corner_tr.gif

    │      │ as_pointer.gif

    │      │ hl_corner_bl.gif

    │      │ hl_corner_br.gif

    │      │ hl_corner_tl.gif

    │      │ hl_corner_tr.gif

    │      │ ul_corner_bl.gif

    │      │ ul_corner_br.gif

    │      │ ul_corner_tl.gif

    │      │ ul_corner_tr.gif

    │      │

    │      └─_source

    │              .DS_Store

    │              ._.DS_Store

    │              ._as_pointer.png

    │              ._li_corner.png

    │              ._ul_corner.png

    │              as_pointer.png

    │              li_corner.png

    │              ul_corner.png



    └─js

           .DS_Store

           ._.DS_Store

           ._bsn.AutoSuggest_2.
    1.3.js

           bsn.AutoSuggest_2.
    1.3.js

           bsn.AutoSuggest_2.
    1.3_comp.js


    AutoSuggest是一组JavaScript类库,其中主要的对象就是bsn.AutoSggest对象,基本的功能都是在这个对象中完成的。首先我们构建一个简单的示例:
        

    var options_xml = {

                                    script:
    function(input){return"suggestAction!userName.action?signer="+input; }//(1).带有传送数据的请求路径,其中input是输入框的value。

                                    varname:
    "input"//(2).储存输入框value的变量名

                                    delay:
    800//(3).发送请求的延时时间

                                    cache:
    false//(4).是否缓存

                                    noresults:
    "无符合的记录!",//(5).当没有符合的查询结果时的提示信息

                                    timeout:
    10000,//(6).候选框停留时间

                                    callback: 
    function(record){ document.getElementById("temp").value = record.value; } //(7).选择候选项后的回调函数

    }
    ;

    var as_xml = new bsn.AutoSuggest('signer', options_xml); //(8).创建autosuggest对象,并绑定一个输入框




    通过这样简单的方式我们就可以完成在页面中的autosuggest编码了。其中的参数表可以看下表:

    Property

    Type

    Default

    Description

    script

    String / Function

    -

    REQUIRED!
    Either: A string containing the path to the script that returns the results in XML format. (eg, "myscript.php?")
    Or: A function that accepts on attribute, the autosuggest field input as a string, and returns the path to the result script.

    varname

    String

    "input"

    Name of variable passed to script holding current input.

    minchars

    Integer

    1

    Length of input required before AutoSuggest is triggered.

    className

    String

    "autosuggest"

    Value of the class name attribute added to the generated ul.

    delay

    Integer

    500

    Number of milliseconds before an AutoSuggest AJAX request is fired.

    timeout

    Integer

    2500

    Number of milliseconds before an AutoSuggest list closes itself.

    cache

    Boolean

    true

    Whether or not a results list should be cached during typing.

    offsety

    Integer

    -5

    Vertical pixel offset from the text field.

    shownoresults

    Boolean

    true

    Whether to display a message when no results are returned.

    noresults

    String

    No results!

    No results message.

    callback

    Function

    A function taking one argument: an object

    {id:"1", value:"Foobar", info:"Cheshire"}

    json

    Boolean

    false

    Whether or not a results are returned in JSON format. If not, script assumes results are in XML.

    maxentries

    Integer

    25

    The maximum number of entries being returned by the script. (Should correspond to the LIMIT clause in the SQL query.)

    之后我们只要在我的服务器中解析传入的signer参数返回,如下格式的xml就可以了。当然也可以用JSON方式,不过我在这里就不在演示了。
        

    <results>

                                    
    <rs id="1" info="">Foobar</rs>

                                    
    <rs id="2" info="">Foobarfly</rs>

                                    
    <rs id="3" info="">Foobarnacle</rs>

    </results>


    AutoSuggest是比较方便的一种实现类Google Suggest的解决方式,提供的js文件也是比较精巧的,并提供的一个压缩后的js脚本文件只有8.33 KB大小。如果要查看其代码可以找到一个没有压缩的原始版本的源代码,其中的代码也是比较容易阅读,更改起来也是比较简单的。我会在以后写一篇《AutoSuggest代码解析》。

    更多信息可查阅 http://www.brandspankingnew.net/archive/2007/02/ajax_auto_suggest_v2.html

    posted @ 2007-10-19 18:17 Stanley Sun 阅读(2525) | 评论 (2)编辑 收藏

    在一般的项目中,数据库主键不会拥有业务逻辑。但是在一些数据库设计不是很严格的项目中还是会把拥护业务逻辑的字段作为主键使用,而且可能回事复合主键。 现在在一个项目我就遇到这情况。这个项目的数据访问框架使用的Hibernate框架,在对复合主键的映射是我遇到了一个Hibernate Bug。我使用的数据库是Oracle 8i。Hibernate Mapping如下:

    <composite-id name="id" class="InfoViewDetaillistId">

               <key-property

                  name="accountno"

                  column="ACCOUNTNO"

                  type="string"

               />

               <key-property

                  name="rlsdepid"

                  column="RLSDEPID"

                  type="string"

               />

               <key-property

                  name="sequenceno"

                  column="SEQUENCENO"

                  type="integer"

               />

               <key-property

                  name="ondate"

                  column="ONDATE"

                  type="date"

               />

    </composite-id>

    在这个复合主键中包括了四个拥有业务逻辑的字段,分别是帐号,中心号,序号,日期。问题就在Hibernate对日期类型的映射上,如使用上面的配置方法的话Hibernate在启动的时候就会报错。具体的解决方法是把
    <key-property

    name="ondate"

    column="ONDATE"

    type="date"

    />

    替换成

    <key-property name="ondate" type="date">

    <column name="ONDATE" not-null="true" sql-type="java.sql.Types.DATE"/>

    </key-property>

    Bug具体的原因我会在一会的文章中解释。

    posted @ 2007-10-09 12:57 Stanley Sun 阅读(309) | 评论 (0)编辑 收藏