随笔-204  评论-90  文章-8  trackbacks-0
 
2003-02-17· ·板桥里人 ··j-道

开始之初的架构设计决定着软件产品的生死存亡。“好的开始相当于成功一半”。

  开始的架构设计也是最难的,需要调研同类产品的情况以及技术特征,了解当前世界上对这种产品所能提供的理论支持和技术平台支持。再结合自己项目的特点(需要透彻的系统分析),才能逐步形成自己项目的架构蓝图。

  比如要开发网站引擎系统,就从Yahoo的个人主页生成工具 到虚拟主机商提供的网站自动生成系统,以及IBM Webphere Portal的特点和局限 从而从架构设计角度定立自己产品的位置。

  好的设计肯定需要经过反复修改,从简单到复杂的循环测试是保证设计正确的一个好办法

  由于在开始选择了正确的方向,后来项目的实现过程也验证了这种选择,但在一些架构设计的细部方面,还需要对方案进行修改,属于那种螺旋上升的方式,显然这是通过测试第一的思想和XP工程方法来实现的。

  如果我们开始的架构设计在技术平台定位具有一定的世界先进水平,那么,项目开发实际有一半相当于做实验,是研发,存在相当的技术风险。

  因此,一开始我们不可能将每个需求都实现,而是采取一种简单完成架构流程的办法,使用最简单的需求将整个架构都简单的完成一遍(加入人工干 预),以检验各个技术环节是否能协调配合工作(非常优秀先进的两种技术有时无法在一起工作),同时也可以探知技术的深浅,掌握项目中的技术难易点。这个过 程完成后,我们就对设计方案做出上面的重大修改,丰富完善了设计方案。

  设计模式是支撑架构的重要组件

  架构设计也类似一种工作流,它是动态的,这点不象建筑设计那样,一开始就能完全确定,架构设计伴随着整个项目的进行过程之中,有两种具体操作保证架构设计的正确完成,那就是设计模式(静态)和工程项目方法(RUP或XP 动态的)。

  设计模式是支撑架构的一种重要组件,这与建筑有很相象的地方,一个建筑物建立设计需要建筑架构设计,在具体施工中,有很多建筑方面的规则和模式。

  我们从J2EE蓝图模式分类http://java.sun.com/blueprints/patterns/catalog.html中就可以很清楚的看到J2EE这样一个框架软件的架构与设计模式的关系。

  架构设计是骨架,设计模式就是肉

  这样,一个比较丰富的设计方案可以交由程序员进一步完成了,载辅助以适当的工程方法,这样就可保证项目的架构设计能正确快速的完成。

  时刻牢记架构设计的目标

  由于架构设计是在动态中完成的,因此在把握架构设计的目标上就很重要,因此在整个项目过程中,甚至每一步我们都必须牢记我们架构设计的总体目标,可以概括下面几点:

  1. 最大化的重用:这个重用包括组件重用 和设计模式使用等多个方面。

  比如,我们项目中有用户注册和用户权限系统验证,这其实是个通用课题,每个项目只是有其内容和一些细微的差别,如果我们之前有这方面成功研发经 验,可以直接重用,如果没有,那么我们就要进行这个子项目的研发,在研发过程中,不能仅仅看到这个项目的需求,也要以架构的概念去完成这个可以称为组件的 子项目。

  2. 尽可能的简单明了:我们解决问题的总方向是将复杂问题简单化,其实这也是中间件或多层体系技术的根本目标。但是在具体实施设计过程中,我们可能会将简单问题复杂化,特别是设计模式的运用上很容易范这个错误,因此如何尽可能的做到设计的简单明了是不容易的。

  我认为落实到每个类的具体实现上要真正能体现系统事物的本质特征,因为事物的本质特征只有一个,你的代码越接近它,表示你的设计就是简单明了, 越简单明了,你的系统就越可靠。更多情况是,一个类并不能反应事物本质,需要多个类的组合协调,那么能够正确使用合适的设计模式就称为重中之重。

  我们看一个具备好的架构设计的系统代码时,基本看到的都是设计模式,宠物店(pet store)就是这样的例子。或者可以这样说,一个好的架构设计基本是由简单明了的多个设计模式完成的。

  3. 最灵活的拓展性:架构设计要具备灵活性 拓展性,这样,用户可以在你的架构上进行二次开发或更加具体的开发。

  要具备灵活的拓展性,就要站在理论的高度去进行架构设计,比如现在工作流概念逐步流行,因为我们具体很多实践项目中都有工作流的影子,工作流中有一个树形结构权限设定的概念就对很多领域比较通用。

  树形结构是组织信息的基本形式,我们现在看到的网站或者ERP前台都是以树形菜单来组织功能的,那么我们在进行架构设计时,就可以将树形结构和 功能分开设计,他们之间联系可以通过树形结构的节点link在一起,就象我们可以在圣诞树的树枝上挂各种小礼品一样,这些小礼品就是我们要实现的各种功 能。

  有了这个概念,通常比较难实现的用户级别权限控制也有了思路,将具体用户或组也是和树形结构的节点link在一起,这样就间接实现了用户对相应功能的权限控制,有了这样的基本设计方案的架构无疑具备很灵活的拓展性。


posted @ 2007-11-26 11:56 一凡 阅读(256) | 评论 (0)编辑 收藏
在使用二分法查找注意事项时,容器(ArrayList)的排序规则和查找时使用的比较规则必须一致,否则有查不到的情况发生。例:
 排序方法:(JVM自动调用)
 public int compare(Object o1, Object o2)和
 比较方法:(我们的程序调用)
 public int compare(int co, int oprId, int provId,int prodId)必须一致
posted @ 2007-11-21 11:22 一凡 阅读(309) | 评论 (0)编辑 收藏
第一,谈谈final, finally, finalize的区别。 
   final?修饰符(关键字)如果一个类被声明为final,意
 味着它不能再派生出新的子类,不能作为父类被继承。因此
 一个类不能既被声明为 abstract的,又被声明为final的。将
 变量或方法声明为final, 可以保证它们在使用中不被改变。
 被声明为final的变量必须在声明时给定初值,而在以后的引
 用中只能 读取,不可修改。被声明为final的方法也同样只能
 使用,不能重载。finally?再异常处理时提供 finally 块来执行
 任何清除操作。如果抛出一个异常,那么相匹配的 catch 子
 句就会执行,然后控制就会进入 finally 块(如果有的话)。 
 finalize?方法名。Java 技术允许使用 finalize() 方法在垃
 圾收集器将对象从内存中清除出去 之前做必要的清理工作。
 这个方法是由垃圾收集器在确定这个对象没有被引用时对这
 个对象调用的。它是 在 Object 类中定义的,因此所有的类
 都继承了它。子类覆盖 finalize() 方法以整理系统资源或
 者执 行其他清理工作。finalize() 方法是在垃圾收集器删
 除对象之前对这个对象调用的。 
   第二,Anonymous Inner Class (匿名内部类) 是否可
 以extends(继承)其它类,是否可以 
 implements(实现)interface(接口)? 
   匿名的内部类是没有名字的内部类。不能extends(继承
 ) 其它类,但一个内部类可以作为一个接口 
 ,由另一个内部类实现。 
   第三,Static Nested Class 和 Inner Class的不同,说得
 越多越好(面试题有的很笼统)。 
   Nested Class (一般是C++的说法),Inner Class (一
 般是JAVA的说法)。Java内部类与C++嵌套 
 类最大的不同就在于是否有指向外部的引用上。具体可
 见http: 
 //www.frontfree.net/articles/services/view.asp?id=704&page
 =1 
   注: 静态内部类(Inner Class)意味着1创建一个static
 内部类的对象,不需要一个外部类对象,2 
 不能从一个static内部类的一个对象访问一个外部类对象 
   第四,&和&&的区别。 
   &是位运算符。&&是布尔逻辑运算符。 
   第五,HashMap和Hashtable的区别。 
   都属于Map接口的类,实现了将惟一键映射到特定的值
 上。 
   HashMap 类没有分类或者排序。它允许一个 null 键和多
 个 null 值。 
   Hashtable 类似于 HashMap,但是不允许 null 键和 null 
 值。它也比 HashMap 慢,因为它是同步 
 的。 
   第六,Collection 和 Collections的区别。 
   Collections是个java.util下的类,它包含有各种有关集合
 操作的静态方法。 
   Collection是个java.util下的接口,它是各种集合结构的父
 接口。 
 第七,什么时候用assert。 
 断言是一个包含布尔表达式的语句,在执行这个语句时假定
 该表达式为 true。如果表达式计算为 false,那么系统会报告
 一个 AssertionError。它用于调试目的: 
 assert(a > 0); // throws an AssertionError if a <= 0 
 断言可以有两种形式: 
 assert Expression1 ; 
 assert Expression1 : Expression2 ; 
 Expression1 应该总是产生一个布尔值。 
 Expression2 可以是得出一个值的任意表达式。这个值用于
 生成显示更多调试信息的 String 消息。 
 断言在默认情况下是禁用的。要在编译时启用断言,需要使
 用 source 1.4 标记: 
 javac -source 1.4 Test.java 
 要在运行时启用断言,可使用 -enableassertions 或者 -ea 标
 记。 
 要在运行时选择禁用断言,可使用 -da 或者 
 -disableassertions 标记。 
 要系统类中启用断言,可使用 -esa 或者 -dsa 标记。还可以
 在包的基础上启用或者禁用断言。 可以在预计正常情况下不
 会到达的任何位置上放置断言。断言可以用于验证传递给私
 有方法的参数。不过,断言不应该用于验证传递给公有方法
 的参数,因为不管是否启用了断言,公有方法都必须检查其
 参数。不过,既可以在公有方法中,也可以在非公有方法中
 利用断言测试后置条件。另外,断言不应该以任何方式改变
 程序的状态。 
 第八,GC是什么? 为什么要有GC? (基础)。 
 GC是垃圾收集器。Java 程序员不用担心内存管理,因为垃
 圾收集器会自动进行管理。要请求垃圾收 
 集,可以调用下面的方法之一: 
 System.gc() 
 Runtime.getRuntime().gc() 
 第九,String s = new String("xyz");创建了几个String Object? 
 两个对象,一个是"xyx",一个是指向"xyx"的引用对象s。 
 第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多
 少? 
 Math.round(11.5)返回(long)12,Math.round(-11.5)返
 回(long)-11; 
 第十一,short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 
 += 1;有什么错? 
 short s1 = 1; s1 = s1 + 1;有错,s1是short型,s1+1是int型,不
 能显式转化为short型。可修改为 s1 =(short)(s1 + 1) 。short 
 s1 = 1; s1 += 1正确。 
 第十二,sleep() 和 wait() 有什么区别? 搞线程的最爱 
 sleep()方法是使线程停止一段时间的方法。在sleep 时间间
 隔期满后,线程不一定立即恢复执行。 这是因为在那个时刻
 ,其它线程可能正在运行而且没有被调度为放弃执行,除
 非(a)"醒来"的线程具有更高的优先级,(b)正在运行的线程因
 为其它原因而阻塞。 
 wait()是线程交互时,如果线程对一个同步对象x 发出一
 个wait()调用,该线程会暂停执行,被调对象进入等待状态,
 直到被唤醒或等待时间到。 
 第十三,Java有没有goto? 
 Goto?java中的保留字,现在没有在java中使用。 
 第十四,数组有没有length()这个方法? String有没有length()
 这个方法? 
 数组没有length()这个方法,有length的属性。 
 String有有length()这个方法。
  
 第十五,Overload和Override的区别。Overloaded的方法是
 否可以改变返回值的类型? 
 方法的重写Overriding和重载Overloading是Java多态性的不
 同表现。重写Overriding是父类与子类 之间多态性的一种表
 现,重载Overloading是一个类中多态性的一种表现。如果在
 子类中定义某方法与其父类有相同的名称和参数,我们说该
 方法被重写 (Overriding)。子类的对象使用这个方法时,将调
 用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了
 。如果在一个类中定义了多个同名的方法,它们或有不同的
 参数个数或有不同的参数类型,则称为方法的重
 载(Overloading)。Overloaded的方法是可以改变返回值的类
 型。 
 第十六,Set里的元素是不能重复的,那么用什么方法来区
 分重复与否呢? 是用==还是equals()? 它们有何区别? 
 Set里的元素是不能重复的,那么用iterator()方法来区分重复
 与否。equals()是判读两个Set是否相 等。 
 equals()和==方法决定引用值是否指向同一对象equals()在类
 中被覆盖,为的是当两个分离的对象的内容和类型相配的话
 ,返回真值。 
 第十七,给我一个你最常见到的runtime exception。 
 ArithmeticException, ArrayStoreException, 
 BufferOverflowException, 
 BufferUnderflowException, CannotRedoException, 
 CannotUndoException, ClassCastException, 
 CMMException, ConcurrentModificationException, 
 DOMException, EmptyStackException, 
 IllegalArgumentException, IllegalMonitorStateException, 
 IllegalPathStateException, 
 IllegalStateException, ImagingOpException, 
 IndexOutOfBoundsException, 
 MissingResourceException, NegativeArraySizeException, 
 NoSuchElementException, 
 NullPointerException, ProfileDataException, 
 ProviderException, RasterFormatException, 
 SecurityException, SystemException, 
 UndeclaredThrowableException, UnmodifiableSetException, 
 UnsupportedOperationException 
 第十八,error和exception有什么区别? 
 error 表示恢复不是不可能但很困难的情况下的一种严重问题
 。比如说内存溢出。不可能指望程序能处理这样的情况。 
 exception 表示一种设计或实现问题。也就是说,它表示如果
 程序运行正常,从不会发生的情况。 
 第十九,List, Set, Map是否继承自Collection接口? 
 List,Set是 
 Map不是 
 第二十,abstract class和interface有什么区别? 
 声明方法的存在而不去实现它的类被叫做抽象类(abstract 
 class),它用于要创建一个体现某些基本行为的类,并为该
 类声明方法,但不能在该类中实现该类的情况。不能创
 建abstract 类的实例。然而可以创建一个变量,其类型是一
 个抽象类,并让它指向具体子类的一个实例。不能有抽象构
 造函数或抽象静态方法。Abstract 类的子类为它们父类中的
 所有抽象方法提供实现,否则它们也是抽象类为。取而代之
 ,在子类中实现该方法。知道其行为的其它类可以在类中实
 现这些方法。 
 接口(interface)是抽象类的变体。在接口中,所有方法都
 是抽象的。多继承性可通过实现这样的接口而获得。接口中
 的所有方法都是抽象的,没有一个有程序体。接口只可以定
 义static final成员变量。接口的实现与子类相似,除了该实现
 类不能从接口定义中继承行为。当类实现特殊接口时,它定
 义(即将程序体给予)所有这种接口的方法。然后,它可以
 在实现了该接口的类的任何对象上调用接口的方法.由于有抽
 象类,它允许使用接口名作为引用变量的类型。通常的动态
 联编将生效。引用可以转换到接口类型或从接口类型转
 换,instanceof 运算符可以用来决定某对象的类是否实现了
 接口。 
 第二十一,abstract的method是否可同时是static,是否可同时
 是native,是否可同时是 
 synchronized? 
 都不能 
 第二十二,接口是否可继承接口? 抽象类是否可实
 现(implements)接口? 抽象类是否可继承实体类 
 (concrete class)? 
 接口可以继承接口。抽象类可以实现(implements)接口,抽象
 类是否可继承实体类,但前提是实体类必须有明确的构造函
 数。 
 第二十三,启动一个线程是用run()还是start()? 
 启动一个线程是调用start()方法,使线程所代表的虚拟处理
 机处于可运行状态,这意味着它可以由JVM调度并执行。这
 并不意味着线程就会立即运行。run()方法可以产生必须退出
 的标志来停止一个线程。 
  
 第二十四,构造器Constructor是否可被override? 
 构造器Constructor不能被继承,因此不能重写Overriding,但
 可以被重载Overloading。 
 第二十五,是否可以继承String类? 
 String类是final类故不可以继承。 
 第二十六,当一个线程进入一个对象的一个synchronized方
 法后,其它线程是否可进入此对象的其它方法? 
 不能,一个对象的一个synchronized方法只能由一个线程访
 问。 
 第二十七,try {}里有一个return语句,那么紧跟在这个try后
 的finally {}里的code会不会被执行,什么时候被执
 行,在return前还是后? 
 会执行,在return前执行。 
 第二十八,编程题: 用最有效率的方法算出2乘以8等於几? 
 有C背景的程序员特别喜欢问这种问题。 
 2 << 3 
 第二十九,两个对象值相同(x.equals(y) == true),但却可有
 不同的hash code,这句话对不对? 
 不对,有相同的hash code。 
 第三十,当一个对象被当作参数传递到一个方法后,此方法
 可改变这个对象的属性,并可返回变化后的结果,那么这里
 到底是值传递还是引用传递? 
 是值传递。Java 编程语言只由值传递参数。当一个对象实例
 作为一个参数被传递到方法中时,参数的值就是对该对象的
 引用。对象的内容可以在被调用的方法中改变,但对象的引
 用是永远不会改变的。 
 第三十一,swtich是否能作用在byte上,是否能作用在long上
 ,是否能作用在String上? 
 switch(expr1)中,expr1是一个整数表达式。因此传递给 
 switch 和 case 语句的参数应该是 int、 short、 char 或者 
 byte。long,string 都不能作用于swtich。 
 第三十二,编程题: 写一个Singleton出来。 
 Singleton模式主要作用是保证在Java应用程序中,一个
 类Class只有一个实例存在。 
 一般Singleton模式通常有几种种形式: 
 第一种形式:   定义一个类,它的构造函数为private的,
 它有一个static的private的该类变量, 在类初始化时实例话
 ,通过一个public的getInstance方法获取对它的引用,继而调
 用其中的方法。 
 public class Singleton { 
 private Singleton(){} 
 //在自己内部定义自己一个实例,是不是很奇怪? 
 //注意这是private 只供内部调用 
 private static Singleton instance = new Singleton(); 
 //这里提供了一个供外部访问本class的静态方法,可以直接
 访问 
 public static Singleton getInstance() { 
 return instance; 
 } 
 } 
 第二种形式: 
 public class Singleton { 
 private static Singleton instance = null; 
 public static synchronized Singleton getInstance() { 
 //这个方法比上面有所改进,不用每次都进行生成对象,只
 是第一次 
 //使用时生成实例,提高了效率! 
 if (instance==null) 
 instance=new Singleton(); 
 return instance; } 
 } 
 其他形式: 
 定义一个类,它的构造函数为private的,所有方法为static的
 。 
 一般认为第一种形式要更加安全些 
 第三十三 Hashtable和HashMap 
 Hashtable继承自Dictionary类,而HashMap是Java1.2引进的
 Map interface的一个实现 
 HashMap允许将null作为一个entry的key或
 者value,而Hashtable不允许 
 还有就是,HashMap把Hashtable的contains方法去掉了,改
 成containsvalue和containsKey。因为 contains方法容易让人
 引起误解。 
 最大的不同是,Hashtable的方法
 是Synchronize的,而HashMap不是,在多个线程访
 问Hashtable时,不需要自己为它的方法实现同
 步,而HashMap就必须为之提供外同步。 
 Hashtable和HashMap采用的hash/rehash算法都大概一样,
 所以性能不会有很大的差异 
posted @ 2007-11-14 16:27 一凡 阅读(293) | 评论 (0)编辑 收藏
一:需要包含的包

   

   import java.security.*;

   import java.io.*;

   import java.util.*;

   import java.security.*;

   import java.security.cert.*;

   import sun.security.x509.*

   import java.security.cert.Certificate;

   import java.security.cert.CertificateFactory;

   二:从文件中读取证书

   用keytool将.keystore中的证书写入文件中,然后从该文件中读取证书信息

   CertificateFactory cf=CertificateFactory.getInstance("X.509");

   FileInputStream in=new FileInputStream("out.csr");

   Certificate c=cf.generateCertificate(in);

   String s=c.toString();

   三:从密钥库中直接读取证书

   String pass="123456";

   FileInputStream in=new FileInputStream(".keystore");

   KeyStore ks=KeyStore.getInstance("JKS");

   ks.load(in,pass.toCharArray());

   java.security.cert.Certificate c=ks.getCertificate(alias);//alias为条目的别名

   四:JAVA程序中显示证书指定信息

   System.out.println("输出证书信息:\n"+c.toString());

   System.out.println("版本号:"+t.getVersion());

   System.out.println("序列号:"+t.getSerialNumber().toString(16));

   System.out.println("主体名:"+t.getSubjectDN());

   System.out.println("签发者:"+t.getIssuerDN());

   System.out.println("有效期:"+t.getNotBefore());

   System.out.println("签名算法:"+t.getSigAlgName());

   byte [] sig=t.getSignature();//签名值

   PublicKey pk=t.getPublicKey();

   byte [] pkenc=pk.getEncoded();

   System.out.println("公钥");

   for(int i=0;i<pkenc.length;i++)System.out.print(pkenc[i]+",");

   五:JAVA程序列出密钥库所有条目
 String pass="123456";

   FileInputStream in=new FileInputStream(".keystore");

   KeyStore ks=KeyStore.getInstance("JKS");

   ks.load(in,pass.toCharArray());

   Enumeration e=ks.aliases();

   while(e.hasMoreElements())

   java.security.cert.Certificate c=ks.getCertificate((String)e.nextElement());

   六:JAVA程序修改密钥库口令

   String oldpass="123456";

   String newpass="654321";

   FileInputStream in=new FileInputStream(".keystore");

   KeyStore ks=KeyStore.getInstance("JKS");

   ks.load(in,oldpass.toCharArray());

   in.close();

   FileOutputStream output=new FileOutputStream(".keystore");

   ks.store(output,newpass.toCharArray());

   output.close();

   七:JAVA程序修改密钥库条目的口令及添加条目

   FileInputStream in=new FileInputStream(".keystore");

   KeyStore ks=KeyStore.getInstance("JKS");

   ks.load(in,storepass.toCharArray());

   Certificate [] cchain=ks.getCertificate(alias);获取别名对应条目的证书链

   PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass.toCharArray());获取别名对应条目的私钥

   ks.setKeyEntry(alias,pk,newkeypass.toCharArray(),cchain);向密钥库中添加条目

   第一个参数指定所添加条目的别名,假如使用已存在别名将覆盖已存在条目,使用新别名将增加一个新条目,第二个参数为条目的私钥,第三个为设置的新口令,第四个为该私钥的公钥的证书链

   FileOutputStream output=new FileOutputStream("another");

   ks.store(output,storepass.toCharArray())将keystore对象内容写入新文件

   八:JAVA程序检验别名和删除条目

   FileInputStream in=new FileInputStream(".keystore");

   KeyStore ks=KeyStore.getInstance("JKS");

   ks.load(in,storepass.toCharArray());
 ks.containsAlias("sage");检验条目是否在密钥库中,存在返回true

   ks.deleteEntry("sage");删除别名对应的条目

   FileOutputStream output=new FileOutputStream(".keystore");

   ks.store(output,storepass.toCharArray())将keystore对象内容写入文件,条目删除成功

 九:JAVA程序签发数字证书

   

   (1)从密钥库中读取CA的证书

   FileInputStream in=new FileInputStream(".keystore");

   KeyStore ks=KeyStore.getInstance("JKS");

   ks.load(in,storepass.toCharArray());

   java.security.cert.Certificate c1=ks.getCertificate("caroot");

   (2)从密钥库中读取CA的私钥

   PrivateKey caprk=(PrivateKey)ks.getKey(alias,cakeypass.toCharArray());

   (3)从CA的证书中提取签发者的信息

   byte[] encod1=c1.getEncoded();  提取CA证书的编码

   X509CertImpl cimp1=new X509CertImpl(encod1); 用该编码创建X509CertImpl类型对象

   X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象

   X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME); 获取X509Name类型的签发者信息

   (4)获取待签发的证书

   CertificateFactory cf=CertificateFactory.getInstance("X.509");

   FileInputStream in2=new FileInputStream("user.csr");

   java.security.cert.Certificate c2=cf.generateCertificate(in);

   (5)从待签发的证书中提取证书信息

   byte [] encod2=c2.getEncoded();

   X509CertImpl cimp2=new X509CertImpl(encod2); 用该编码创建X509CertImpl类型对象

   X509CertInfo cinfo2=(X509CertInfo)cimp2.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象

   (6)设置新证书有效期

   Date begindate=new Date(); 获取当前时间

   Date enddate=new Date(begindate.getTime()+3000*24*60*60*1000L); 有效期为3000天
 CertificateValidity cv=new CertificateValidity(begindate,enddate); 创建对象

   cinfo2.set(X509CertInfo.VALIDITY,cv); 设置有效期

   (7)设置新证书序列号

   int sn=(int)(begindate.getTime()/1000);  以当前时间为序列号

   CertificateSerialNumber csn=new CertificateSerialNumber(sn);

   cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn);

   (8)设置新证书签发者

   cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);应用第三步的结果

   (9)设置新证书签名算法信息

   AlgorithmId algorithm=new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);

   cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM,algorithm);

   (10)创建证书并使用CA的私钥对其签名

   X509CertImpl newcert=new X509CertImpl(cinfo2);

   newcert.sign(caprk,"MD5WithRSA"); 使用CA私钥对其签名

   (11)将新证书写入密钥库

   ks.setCertificateEntry("lf_signed",newcert);

   FileOutputStream out=new FileOutputStream("newstore");

   ks.store(out,"newpass".toCharArray()); 这里是写入了新的密钥库,也可以使用第七条来增加条目

   十:数字证书的检验

   (1)验证证书的有效期

   (a)获取X509Certificate类型对象

   CertificateFactory cf=CertificateFactory.getInstance("X.509");

   FileInputStream in1=new FileInputStream("aa.crt");

   java.security.cert.Certificate c1=cf.generateCertificate(in1);

   X509Certificate t=(X509Certificate)c1;

   in2.close();

   (b)获取日期

   Date TimeNow=new Date();

   (c)检验有效性

   try{

   t.checkValidity(TimeNow);

   System.out.println("OK");

   }catch(CertificateExpiredException e){ //过期

   System.out.println("Expired");
 System.out.println(e.getMessage());

   }catch((CertificateNotYetValidException e){ //尚未生效

   System.out.println("Too early");

   System.out.println(e.getMessage());}

   (2)验证证书签名的有效性

   (a)获取CA证书

   CertificateFactory cf=CertificateFactory.getInstance("X.509");

   FileInputStream in2=new FileInputStream("caroot.crt");

   java.security.cert.Certificate cac=cf.generateCertificate(in2);

   in2.close();

   (c)获取CA的公钥

   PublicKey pbk=cac.getPublicKey();

   (b)获取待检验的证书(上步已经获取了,就是C1)

   (c)检验证书

   boolean pass=false;

   try{

   c1.verify(pbk);

   pass=true;

   }catch(Exception e){

   pass=false;

   System.out.println(e);

   } 
posted @ 2007-11-14 16:08 一凡 阅读(309) | 评论 (0)编辑 收藏

一、功能:使用crontab命令装载cron进程所需要的crontab文件。

格式:

格式1:crontab [-u user] [-l|-r|-e]

格式2:crontab [-u user] filename

其中:

-u user: 修改指定用户的crontab文件。如果不指定该选项,crontab将默认为是操作者本人的crontab。

-l:在标准输出上显示当前的crontab任务。

-r:删除当前的crontab任务。

-e:使用环境变量指定的编辑器编辑crontab文件。当结束编辑离开时,编辑后的文件将自动安装。

filename:是一个crontab文件的来源文件
crontab文件的来源文件
crontab文件的来源文件存在的形式

一个符合语法规则的纯文本文件,使用第2种格式的crontab命令装载

使用第2种格式的crontab命令时,它是一个文本编辑器(如vi)的临时文件,编辑结束自动装载

crontab文件的来源文件的格式
每一行格式为:

分< >时< >日< >月< >星期< >要运行的命令

minute hour day-of-month month-of-year day-of-week [username] commands

其中:

minute:一小时中的哪一分钟(0~59)

hour:一天中的哪个小时(0~23)

day-of-month:一月中的哪一天(1~31)

month-of-year:一年中的哪一月(1~12)

day-of-week:一周中的哪一天(0~6)

username:以指定的用户身份执行commands

commands:执行的命令(可以是多行命令或者是脚本调用)

五个时间字段的语法说明

不能为空,可以使用统配符*表示任何时间。

可以指定多个值,它们之间用逗号间隔。例如:1,3,7。

可以指定时间段,用减号间隔。例如:0-6。

可以用/n表示步长。例如:8-18/2表示时间序列8,10,12,14,16,18



二、示例
● 0 */2 * * * /sbin/service httpd restart  意思是每两个小时重启一次apache
● 50 7 * * * /sbin/service sshd start  意思是每天7:50开启ssh服务
● 50 22 * * * /sbin/service sshd stop  意思是每天22:50关闭ssh服务
● 0 0 1,15 * * fsck /home  每月1号和15号检查/home 磁盘
● 1 * * * * /home/bruce/backup  每小时的第一分执行 /home/bruce/backup这个文件
● 00 03 * * 1-5 find /home "*.xxx" -mtime +4 -exec rm {} \;  每周一至周五3点钟,在目录/home中,查找文件名为*.xxx的文件,并删除4天前的文件。
● 30 6 */10 * * ls  意思是每月的1、11、21、31日(每隔10天)是的6:30执行一次ls命令
posted @ 2007-11-02 17:43 一凡 阅读(1046) | 评论 (0)编辑 收藏
     makefile文件里的命令行部分一定要以一个TAB开头,否则会报错“makefile:2: *** 遗漏分隔符”如下:
OBJS = main.o add.o
CC 
= gcc
CFLAGS 
= -Wall --g

test : $(OBJS)
        $(CC) $(OBJS) 
-o test

main.o : main.c add.h
        $(CC) $(CFLAGS) 
-c main.c -o main.o

add.o : add.c add.h
        $(CC) $(CFLAGS) 
-c add.c -o add.o

clear:
        rm 
-*.o


posted @ 2007-10-22 13:34 一凡 阅读(390) | 评论 (0)编辑 收藏
此JOB每小时执行一次:
begin
  sys.dbms_job.submit(job => :job,
                      what => 'Cancel_36_37;',
                      next_date => to_date('22-10-2007 11:00:00', 'dd-mm-yyyy hh24:mi:ss'),
                      interval => 'trunc(sysdate +1/24,''hh'')');
  commit;
end;
/
posted @ 2007-10-22 10:35 一凡 阅读(2200) | 评论 (0)编辑 收藏
http://www.aka.org.cn/Lectures/002/Lecture-2.1.8/Lecture-2.1.8/index.htm
posted @ 2007-10-19 11:14 一凡 阅读(374) | 评论 (0)编辑 收藏

中国移动、中国联通推行的GPRS网络、CDMA网络已覆盖大量的区域,通过无线网络实现数据传输成为可能。无线Modem采用GPRS、CDMA 模块通过中国移动、中国联通的GPRS、CDMA网络进行数据传输,并通TCP/IP协议进行数据封包,可灵活地实现多种设备接入,工程安装简单,在工业 现场数据传输的应用中,能很好的解决偏远无网络无电话线路地区的数据传输的难题。同传统的数传电台想比较,更具有简便性、灵活性、易操作性,同时还降低了 成本,无线Modem传输方案是现代化工业现场数据传输最好的选择方案。
     目前中国移动、中国联通提供的GPRS网络、CDMA网络的数据传输带宽在40Kbps左右,且受带宽的限制,数据采集方案最好采用于主动告警、数据轮巡 采集、告警主动回叫等对传输带宽占用较少的采集方式。同时考虑对前置机实时采集方案的支持,无线Modem传输方案只能作为目前传输方案的补充。
    随着无线通讯技术的不断发展,无线传输数据带宽将不断提高,采用3G无线网络,数据传输带宽将达到2M,无线传输方案将逐渐成为监控传输组网的主要应用方案。
     目前,由于GPRS和CDMA固有的特性,在各个领域中GPRS和CDMA的应用也越来越广泛,但是关于传输中使用TCP/IP协议还是UDP协议,却争论很多。

这里先简单的说一下TCP与UDP的区别:
  1。基于连接与无连接
  2。对系统资源的要求(TCP较多,UDP少)
  3。UDP程序结构较简单
  4。流模式与数据报模式
  5。TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证

另外结合GPRS网络的情况具体的谈一下他们的区别:
 1。TCP传输存在一定的延时,大概是1600MS(移动提供),UDP响应速度稍微快一些。
 2。TCP包头结构
源端口16位
目标端口 16位
序列号 32位
回应序号 32位
TCP头长度 4位
reserved 6位
控制代码6位
窗口大小16位
偏移量16位
校验和16位
选项 32位(可选)
这样我们得出了TCP包头的最小大小.就是20字节.

  UDP包头结构
源端口16位
目的端口16位
长度 16位
校验和 16位
UDP的包小很多.确实如此.因为UDP是非可靠连接.设计初衷就是尽可能快的将数据包发送出去.所以UDP协

议显得非常精简.

 3。GPRS网络端口资源,UDP十分紧缺,变化很快;而TCP采用可靠链路传输,不存在端口变化的问题工业场合的应用一般都有以下特点,

 1。要求时时传输,但也有一些场合是定时传输,总的来说在整个传输过程中要求服务器中心端和GPRS终端设备能相互的、时时的传输数据。
TCP 本身就是可靠链路传输,提供一个时时的双向的传输通道,能很好的满足工业现场传输的要求。但是GPRS网络对TCP链路也存在一个限制:此条链路在长时间 (大概20分钟左右,视具体情况而定)没有数据流量,会自动降低此链路的优先级直至强制断开此链路。所以在实际使用中也会采用心跳包(一般是一个字节的数 据)来维持此链路。
UDP由于自身特点,以及GPRS网络UDP端口资源的有限性,在一段时间没有数据流量后,端口容易改变,产生的影响就是从服 务器中心端向GPRS终端发送数据,GPRS终端接收不到。具体的原因就是移动网关从中作了中转,需要隔一定时间给主机发UDP包来维持这个IP和端口 号,这样主机就能主动给GPRS发UDP包了并且我在测试中发现,这个间隔时间很短,我在1多分钟发一次UDP包才能够维持,但是再长可能移动网关那边就 要丢失这个端口了,此时如果主机想主动发数据给GPRS,那肯定是不行的了,只有GPRS终端设备再发一个UDP包过去,移动重新给你分配一个中转IP和 端口,才能够进行双向通讯。

 2。要求数据的丢包率较小。有些工业场合,例如电力、水务抄表,环保监测等等,不容许传输过程中的数据丢失或者最大限度的要求数据的可靠性。从这 一点来看,很显然在无线数据传输过程中,TCP比UDP更能保证数据的完整性、可靠性,存在更小的丢包率。在实际测试中也是如此。以厦门桑荣科技有限公司 提供的GPRS终端设备为例:TCP的在千分之9,UDP的在千分之17左右。

3。要求降低费用。目前有很大部分GPRS设备的应用都是取代前期无线数传电台,除了使用范围外,其考虑的主要问题就是费用。能降低费用当然都是大 家最愿意接受的。和费用直接相关的就是流量了,流量低,费用就低了。虽然TCP本身的包头要比UDP多,但是UDP在实际应用中往往需要维护双向通道,就 必须要通过大量的心跳包数据来维护端口资源。总的比较起来,UDP的实际流量要比TCP还要大。很多使用者在初期的时候并不了解UDP需要大量心跳包来维 持端口资源这个问题,往往都认为UDP要比TCP更节省流量,实际上这里存在着一个误区。

4。在某些特定的应用场合,例如一些银行的时时交互系统,对响应速度要求很高,此时数据传输频率较快,不需要大量心跳包维持UDP端口资源,采用UDP就比较有利了。

5。在目前的1:N的传输模式中,既有多个GPRS终端设备往一个服务器中心传输数据,此时采用UDP会比TCP要好的多,因为UDP耗用更少的系 统资源。但是在实际应用中却发现,很多用户还是采用TCP的传输方式,建立二级中心1:A(1:N),即每一个分中心对应N/A台设备,独立处理数据,再 统一将数据传送到主中心。这样既能保证了传输过程中采用了TCP的传输协议,又能很好处理了中心服务器的多链路的系统耗用的问题。
   
     总的来说,我认为TCP/IP协议更能满足目前各行业对远程数据传输的要求,它提供更稳定更便利的传输通道,很好的满足了远程数据传输的要求。
posted @ 2007-10-19 11:02 一凡 阅读(513) | 评论 (0)编辑 收藏

Siege(英文意思是围攻)是一个压力测试和评测工具,设计用于WEB开发这评估应用在压力下的承受能力:可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访问下重复进行。


最早使用的压力测试工具是apache的ab(apache benchmark),apache ab做重复压力测试不错,但是每次只能测试一个链接,如何测试一组链接(比如从日志中导出的1个小时的日志,做真实压力测试),后来找到了这个:
Siege是一个压力测试和评测工具,设计用于WEB开发这评估应用在压力下的承受能力:可以根据配置对一个WEB站点进行多用户的并发访问,记录每个用户所有请求过程的相应时间,并在一定数量的并发访问下重复进行。
SIEGE is an http regressive testing and benchmarking utility. It was designed to let web developers measure the performance of their code under duress, to see how it will stand up to load on the internet. It lets the user hit a webserver with a configurable number of concurrent simulated users. Those users place the webserver "under siege." The duration of the siege is measured in transactions, the sum of simulated users and the number of times each simulated user repeats the process of hitting the server. Thus 20 concurrent users 50 times is 1000 transactions, the length of the test.

下载/安装
Siege时一个开放源代码项目:http://www.joedog.org

下载:
wget ftp://sid.joedog.org/pub/siege/siege-latest.tar.gz

安装:
%./configure ; make
#make install

siege包含了一组压力测试工具:
SIEGE (1) Siege是一个HTTP压力测试和评测工具.
使用样例:
任务列表:www.chedong.com.url文件
http://www.chedong.com/tech/
http://www.chedong.com/tech/acdsee.html
http://www.chedong.com/tech/ant.html
http://www.chedong.com/tech/apache_install.html
http://www.chedong.com/tech/awstats.html
http://www.chedong.com/tech/cache.html
http://www.chedong.com/tech/click.html
http://www.chedong.com/tech/cms.html
http://www.chedong.com/tech/compress.html
http://www.chedong.com/tech/cvs_card.html
http://www.chedong.com/tech/default.html
http://www.chedong.com/tech/dev.html
http://www.chedong.com/tech/gnu.html
....

siege -c 20 -r 2 -f www.chedong.com.url
参数说明:
-c 20 并发20个用户
-r 2 重复循环2次
-f www.chedong.com.url 任务列表:URL列表

输出样例:

** Siege 2.59
** Preparing 20 concurrent users for battle. 这次“战斗”准备了20个并发用户
The server is now under siege.. done. 服务在“围攻”测试中:
Transactions: 40 hits 完成40次处理
Availability: 100.00 % 成功率
Elapsed time: 7.67 secs 总共用时
Data transferred: 877340 bytes 共数据传输:877340字节
Response time: 1.65 secs 相应用时1.65秒:显示网络连接的速度
Transaction rate: 5.22 trans/sec 平均每秒完成5.22次处理:表示服务器后台处理的速度
Throughput: 114385.92 bytes/sec 平均每秒传送数据:114385.92字节
Concurrency: 8.59 最高并发数 8.59
Successful transactions: 40 成功处理次数
Failed transactions: 0 失败处理次数

注意:由于速度很快,可能会达不到并发速度很高就已经完成。Response time显示的是测试机器和被测试服务器之间网络链接状况。Transaction rate则表示服务器端任务处理的完成速度。

辅助工具:
增量压力测试:


为了方便增量压力测试,siege还包含了一些辅助工具:
bombardment (1)
是一个辅助工具:用于按照增量用户压力测试:
使用样例:
bombardment urlfile.txt 5 3 4 1
初始化URL列表:urlfile.txt
初始化为:5个用户
每次增加:3个用户
运行:4次
每个客户端之间的延迟为:1秒

输出成CSV格式:
siege2csv.pl (1)
siege2csv.pl将bombardment的输出变成CSV格式:
Time Data Transferred Response Time Transaction Rate Throughput Concurrency Code 200 (note that this is horribly broken.)
242 60.22 603064 0.02 4.02 10014.35 0.08
605 59.98 1507660 0.01 10.09 25136.05 0.12
938 59.98 2337496 0.02 15.64 38971.26 0.26
1157 60 2883244 0.04 19.28 48054.07 0.78

参考:
开源测试工具:http://www.opensourcetesting.org/performance.php

压力测试工具:HammerHead 正在试用中

posted @ 2007-09-20 17:56 一凡 阅读(359) | 评论 (0)编辑 收藏
仅列出标题
共21页: First 上一页 11 12 13 14 15 16 17 18 19 下一页 Last