Let's Go!

发布新日志

  • JSSE访问带有未验证证书的HTTPS

    2009-07-16 21:08:20

     

     

    JSSE访问带有未验证证书的HTTPS

    http://www.ebok.cn/Computer-Development/Java/Java-19560.html

     

    摘 要JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问。但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从而不能访问HTTPS站点。本文在简要介绍JSSE的基础上提出了两种解决该问题的方法。


      引言

      过去的十几年,网络上已经积累了大量的Web应用。如今,无论是整合原有的Web应用系统,还是进行新的Web开发,都要求通过编程来访问某些Web页面。传统的方法是使用Socket接口,但现在很多开发平台或工具如.NET、Java或PHP等都提供了简单的Web访问接口,使用这些接口很容易编程实现与Web应用系统的交互访问,即使要访问那些采用了HTTPS而不是HTTP的Web应用系统。

      HTTPS,即安全的超文本传输协议,采用了SSL技术,被广泛使用以保证Web应用系统的安全性。访问Web应用的编程接口大多封装了SSL,使得访问HTTPS和访问HTTP一样简单。但是很多中、小型应用系统或基于局域网、校园网的应用系统所使用的证书并不是由权威的认证机构发行或者被其验证,直接使用这些编程接口将不能访问HTTPS。

      本文将在简要介绍JSSE的基础上,详细描述使用JSSE访问HTTPS的方法,主要说明了如何访问带有未经验证证书的HTTPS站点。

      JSSE简介

      Java安全套接扩展 (Java Secure Socket Extension, JSSE)是实现Internet安全通信的一系列包的集合。它是一个SSL和TLS的纯Java实现,可以透明地提供数据加密、服务器认证、信息完整性等功能,可以使我们像使用普通的套接字一样使用JSSE建立的安全套接字。JSSE是一个开放的标准,不只是Sun公司才能实现一个JSSE,事实上其他公司有自己实现的JSSE。

      在深入了解JSSE之前,需要了解一个有关Java安全的概念:客户端的TrustStore文件。客户端的TrustStore文件中保存着被客户端所信任的服务器的证书信息。客户端在进行SSL连接时,JSSE将根据这个文件中的证书决定是否信任服务器端的证书。

      JSSE中,有一个信任管理器类负责决定是否信任远端的证书,这个类有如下的处理规则:

      ⑴ 果系统属性javax.net.sll.trustStore指定了TrustStore文件,那么信任管理器就去jre安装路径下的lib/security/目录中寻找并使用这个文件来检查证书。

      ⑵ 果该系统属性没有指定TrustStore文件,它就会去jre安装路径下寻找默认的TrustStore文件,这个文件的相对路径为:lib/security/jssecacerts。

      ⑶ 如果 jssecacerts不存在,但是cacerts存在(它随J2SDK一起发行,含有数量有限的可信任的基本证书),那么这个默认的TrustStore文件就是cacerts。

      直接使用类HttpsURLConnection访问Web页面

      Java提供了一种非常简洁的方法来访问HTTPS网页,即使用类HttpsURLConnection、URL等。这几个类为支持HTTPS对JSSE相关类做了进一步的封装,例子如下所示:

    URL reqURL = new URL("https://www.sun.com" ); //创建URL对象
    HttpsURLConnection httpsConn = (HttpsURLConnection)reqURL.openConnection();

    /*下面这段代码实现向Web页面发送数据,实现与网页的交互访问
    httpsConn.setDoOutput(true);
    OutputStreamWriter ut = new OutputStreamWriter(huc.getOutputStream(), "8859_1");
    out.write( "……" );
    out.flush();
    out.close();
    */

    //取得该连接的输入流,以读取响应内容
    InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream();

    //读取服务器的响应内容并显示
    int respInt = insr.read();
    while( respInt != -1){
     System.out.print((char)respInt);
     respInt = insr.read();
    }

      这段代码能够正常执行,然而把访问的URL改为https://login.bjut.edu.cn时,程序将抛出异常javax.net.ssl.SSLException,这是由于https://login.bjut.edu.cn站点的安全证书不被JSSE所信任。根据JSSE简介中对信任管理器的分析,一种解决这个问题的方法是按照信任管理器的处理规则,把站点的证书放到证书库文件jssecacerts中,或者把证书存放到任一TrustStore文件中,然后设置系统属性javax.net.sll.trustStore指向该文件。另一种解决方法则是自己实现信任管理器类,让它信任我们指定的证书。下面分别介绍这两种方法。

      将证书导入到TrustStore文件中

      Java提供了命令行工具keytool用于创建证书或者把证书从其它文件中导入到Java自己的TrustStore文件中。把证书从其它文件导入到TrustStore文件中的命令行格式为:

      keytool -import -file src_cer_file –keystore dest_cer_store

      其中,src_cer_file为存有证书信息的源文件名,dest_cer_store为目标TrustStore文件。

      在使用keytool之前,首先要取得源证书文件,这个源文件可使用IE浏览器获得,IE浏览器会把访问过的HTTPS站点的证书保存到本地。从IE浏览器导出证书的方法是打开“Internet 选项”,选择“内容”选项卡,点击“证书…”按钮,在打开的证书对话框中,选中一个证书,然后点击“导出…”按钮,按提示一步步将该证书保存到一文件中。最后就可利用keytool把该证书导入到Java的TrustStore文件中。为了能使Java程序找到该文件,应该把这个文件复制到jre安装路径下的lib/security/目录中。

      这样,只需在程序中设置系统属性javax.net.sll.trustStore指向文件dest_cer_store,就能使JSSE信任该证书,从而使程序可以访问使用未经验证的证书的HTTPS站点。

      使用这种方法,编程非常简单,但需要手工导出服务器的证书。当服务器证书经常变化时,就需要经常进行手工导出证书的操作。下面介绍的实现X509证书信任管理器类的方法将避免手工导出证书的问题。


     

    X509证书信任管理器类的实现及应用

      在JSSE中,证书信任管理器类就是实现了接口X509TrustManager的类。我们可以自己实现该接口,让它信任我们指定的证书。

      接口X509TrustManager有下述三个公有的方法需要我们实现:

      ⑴ oid checkClientTrusted(X509Certificate[] chain, String authType)
    throws CertificateException

      该方法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。JSSE中,默认的信任管理器类为TrustManager。

      ⑵ oid checkServerTrusted(X509Certificate[] chain, String authType)
    throws CertificateException

      该方法检查服务器的证书,若不信任该证书同样抛出异常。通过自己实现该方法,可以使之信任我们指定的任何证书。在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。

      ⑶ X509Certificate[] getAcceptedIssuers()

      返回受信任的X509证书数组。

      自己实现了信任管理器类,如何使用呢?类HttpsURLConnection似乎并没有提供方法设置信任管理器。其实,HttpsURLConnection通过SSLSocket来建立与HTTPS的安全连接,SSLSocket对象是由SSLSocketFactory生成的。HttpsURLConnection提供了方法setSSLSocketFactory(SSLSocketFactory)设置它使用的SSLSocketFactory对象。SSLSocketFactory通过SSLContext对象来获得,在初始化SSLContext对象时,可指定信任管理器对象。下面用一个图简单表示这几个JSSE类的关系:

    JSSE访问带有未验证证书的HTTPS

     

     

    图1 部分JSSE类的关系图
      假设自己实现的X509TrustManager类的类名为:MyX509TrustManager,下面的代码片断说明了如何使用MyX509TrustManager:

    //创建SSLContext对象,并使用我们指定的信任管理器初始化
    TrustManager[] tm = {new MyX509TrustManager ()};
    SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE");
    sslContext.init(null, tm, new java.security.SecureRandom());

    //从上述SSLContext对象中得到SSLSocketFactory对象
    SSLSocketFactory ssf = sslContext.getSocketFactory();

    //创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
    HttpsURLConnection httpsConn = (HttpsURLConnection)myURL.openConnection();
    httpsConn.setSSLSocketFactory(ssf);

      这样,HttpsURLConnection对象就可以正常连接HTTPS了,无论其证书是否经权威机构的验证,只要实现了接口X509TrustManager的类MyX509TrustManager信任该证书。

      小结

      本文主要介绍了在HTTPS的证书未经权威机构认证的情况下,访问HTTPS站点的两种方法,一种方法是把该证书导入到Java的TrustStore文件中,另一种是自己实现并覆盖JSSE缺省的证书信任管理器类。两种方法各有优缺点,第一种方法不会影响JSSE的安全性,但需要手工导入证书;第二种方法虽然不用手工导入证书,但需要小心使用,否则会带来一些安全隐患。

     

     

     

     

     

  • java多线程框架runnable

    2009-06-26 02:35:28

     

    //此代码实现了一个java的多线程框架,您可以直接拿过来,把里面相应的地方改成自己的功能代码,就可以实现多线程了。当然框架还很不完善。。。

    package com.icss.oa.work;

    import java.lang.Runnable;

    public class OurRunnableClass implements Runnable
    {
       
     //public OurRunnableClass(){};  //定义一个构造函数,调用方法,不定义也可以。。
     
     public void method1()
     {
      System.out.println("执行方法1");
     }
     
     public void method2()
     {
      System.out.println("执行方法2");
     }
     
     public void run()
            {
                //写线程里具体要执行的事务,事务如果很多,可以分开写在方法里
          method1();            //new OurRunnableClass().method1();
          method2();           //new OurRunnableClass().method2();
                System.out.println("Hello, from another thread. "+Thread.currentThread().getName());

            }
       
        public static void main(String[] args) throws Exception
            {       
          for (int i = 0; i < 20; i++)      //写线程数目
          {
                    Runnable r = new OurRunnableClass();
                    new Thread(r).start();    //Thread th = new Thread(r); th.start();
          }
            }

    }

  • 关于语言和工具学习方向的改变

    2009-06-23 00:50:46

    python 看完了 《python简明教程》

    本来打算继续看《python核心编程》

    但是感觉python和工作联系太少,或者说还不能马上写出代码做一些事

    都是依靠java,也挺喜欢 java 丰富的类库 和其他资源的

    原本想研究下开源的 pylot ,python 写的开源性能测试工具

     

    这几天loadrunner多并发调用动态库时,一直有错误。。。

    老是不放心。

    计划着,学习下jmeter,反正Jmeter也是开源的,可以研究源代码,

    而且对java也算是比较熟悉了。。。

    使用Jmeter熟练了,再结合java做些扩展应该还是不错的

    很多前辈已经在这样做了吧

     

    Loadrunner用的有点心烦哦。。。

    赶紧把JMeter学好吧。。。。。

    顺便提升下 java的编程能力。。。。。

     

    实在是时间充裕,就再 python 吧

    语言简洁易懂,功能强大

    Load Runner vs The Grinder vs Apache JMeter

    http://niyunjiu.javaeye.com/blog/361732

     

  • 配置java环境_如何配置jdk1.5的环境变量及运行java程序 JAVA_HOME等

    2009-06-09 11:02:48

     

    又配置了一遍.......

    对于初学JAVA的人来说,第一个难题就是为自己配置一个JAVA开发平台。然而,也就不得不去安装如JDK这样的软件。对于JDK1.5的安装,我想每个人都会,也就是一直单击下去,安装是容易的了,不过配置就不是那么简单了,因为它要我们为它配置环境变量。
    以下,就让我来教你如何去配置吧:
    1.右击“我的电脑”,点击“属性”:选择“高级”选项卡,点击“环境变量”:   
    2.在“系统变量”中,设置3项系统变量,JAVA_HOME,PATH,CLASSPATH (注:“系统变量”对所有用户有用,而“用户变量”则只对当前登陆用户有用。对于变量的大小写,是不进行区分的。)


    3.因为是默认安装,所以JDK1.5是安装在C:\Program Files\Java\jdk1.5.0里了。现在为三个变量设值;


    新建 JAVA_HOME      设值     C:\Program Files\Java\jdk1.5.0
    新建 CLASSPATH    设值     .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
    编辑   PATH 设值 ;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin


    注意事项:
        配置JAVA_HOME变量的作用:JAVA_HOME路径下包括lib,bin,jre等文件夹,以后配tomcat,eclipse等java开发软件可能需要依赖此变量。
       在设置系统变量Path(系统已经有),要注意前面的分号“;”,配置Path的作用:Path使系统可以在任何路径下识别java命令。
        在设置系统变量CLASSPATH时,要注意前面的注意前面的“.;”,配置CLASSPATH变量的作用: 为系统指明java加载类(class or lib)的路径,只有类在classpath中,java命令才能识别,其中,%JAVA_HOME%就是引用前面指定的JAVA_HOME。
       用户变量的设置必须注销重登录后才起作用,但是当本次配置中所有环境变量都是系统变量,而设置系统变量的则不用。
    4.测试JDK1.5的环境变量是否配置成功。
       “开始”->“运行”,键入“cmd”进入命令提示符下,键入命令“java -version”,出现如下信息,说明环境变量配置成功:
    java version "1.5.0" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
    Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)
    5.用一个小程序测试JDK1.5是否能成功运行JAVA程序。
       现在我们编辑一个java小程序,然后进行测试。现在我们就直接在C盘建一个“Hello.java”的文件吧,并记事本打开它,在它里面输入如下代码:
    public class Hello
    { public static void main(String[] args)
        { System.out.println("Hello World!"); }
    }
    然后保存。
    现在进入到命令提示符下。输入cd\来回到C盘根目录下。即如下样式:
    C:\> java
    程序是不能直接运行的,因此,我们得对它先进地编译,即输入javac Hello.java如下:
    C:\>javac Hello.java
    C:\>
    这样就编译好了,如果没有编译好的话,它会提示错误。 java文件被编译好了之后,就会自动生成一个CLASS编译文件,因此我们可以运行它,只要输入“java Hello”就可以了。
    C:\>java Hello
    Hello World!    //结果。
    这样,我们就已经成功的对JDK进行配置了。

     
     
     
     
     
     
     
     
     
     
     
     
     
     
    linux配置java环境变量(详细) 收藏
      现在用linux的朋友越来越多了,前几天就有两个朋友问我linux下怎么配置java环境,我想还有很多朋友想了解学习这方面的东西,就写一个完全一点的linux java环境配置吧,希望对大家有帮助。
    一. 下载jdk5.0 for linux
      到sun的主页 http://java.sun.com/j2se/1.5.0/download.jsp 下载jdk安装文件jdk-1_5_0_05-linux-i586.bin
    二. 解压安装jdk
       在shell终端下进入jdk-1_5_0_05-linux-i586.bin文件所在目录,执行命令 ./jdk-1_5_0_05-linux-i586.bin 这时会出现一段协议,连继敲回车,当询问是否同意的时候,输入yes,回车。之后会在当前目录下生成一个jdk-1.5.0_05目录,你可以将它复制到 任何一个目录下。
    三. 需要配置的环境变量
      1. PATH环境变量。作用是指定命令搜索路径,在shell下面执行命令时,它会到PATH变量所指定的路径中查找看是否能找到相应的命令程序。我们需要把 jdk安装目录下的bin目录增加到现有的PATH变量中,bin目录中包含经常要用到的可执行文件如javac/java/javadoc等待,设置好 PATH变量后,就可以在任何目录下执行javac/java等工具了。
      2. CLASSPATH环境变量。作用是指定类搜索路径,要使用已经编写好的类,前提当然是能够找到它们了,JVM就是通过CLASSPTH来寻找类的。我们 需要把jdk安装目录下的lib子目录中的dt.jar和tools.jar设置到CLASSPATH中,当然,当前目录“.”也必须加入到该变量中。
      3. JAVA_HOME环境变量。它指向jdk的安装目录,Eclipse/NetBeans/Tomcat等软件就是通过搜索JAVA_HOME变量来找到并使用安装好的jdk。
    四. 三种配置环境变量的方法
      
    1. 修改/etc/profile文件   --- 一般修改 用户目录下的 .bash_profile
     
        如果你的计算机仅仅作为开发使用时推荐使用这种方法,因为所有用户的shell都有权使用这些环境变量,可能会给系统带来安全性问题。
        ·用文本编辑器打开/etc/profile
        ·在profile文件末尾加入:
          JAVA_HOME=/usr/share/jdk1.5.0_05
          PATH=$JAVA_HOME/bin:$PATH
          CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
          export JAVA_HOME
          export PATH
          export CLASSPATH
        ·重新登录  --- 使用 source .bash_profile
        ·注解
          a. 你要将 /usr/share/jdk1.5.0_05jdk 改为你的jdk安装目录
          b. linux下用冒号“:”来分隔路径
          c. $PATH / $CLASSPATH / $JAVA_HOME 是用来引用原来的环境变量的值
            在设置环境变量时特别要注意不能把原来的值给覆盖掉了,这是一种
            常见的错误。
          d. CLASSPATH中当前目录“.”不能丢,把当前目录丢掉也是常见的错误。
          e. export是把这三个变量导出为全局变量。
          f. 大小写必须严格区分。
     
     
    2. 修改.bashrc文件
        
        这种方法更为安全,它可以把使用这些环境变量的权限控制到用户级别,如果你需要给某个用户权限使用这些环境变量,你只需要修改其个人用户主目录下的.bashrc文件就可以了。
        ·用文本编辑器打开用户目录下的.bashrc文件
        ·在.bashrc文件末尾加入:
          
          set JAVA_HOME=/usr/share/jdk1.5.0_05
          export JAVA_HOME
          set PATH=$JAVA_HOME/bin:$PATH
                   export PATH
                   set CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
                   export CLASSPATH
        ·重新登录
     
    3. 直接在shell下设置变量
        不赞成使用这种方法,因为换个shell,你的设置就无效了,因此这种方法仅仅是临时使用,以后要使用的时候又要重新设置,比较麻烦。
        只需在shell终端执行下列命令:
        export JAVA_HOME=/usr/share/jdk1.5.0_05
        export PATH=$JAVA_HOME/bin:$PATH
        export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
     
    五. 测试jdk
      1. 用文本编辑器新建一个Test.java文件,在其中输入以下代码并保存:
        public class test {
          public static void main(String args[]) {
            System.out.println("A new jdk test !");
          }
        }
      2. 编译:在shell终端执行命令 javac Test.java
      3. 运行:在shell终端执行命令 java Test
        当shell下出现“A new jdk test !”字样则jdk运行正常。
     
    六. 卸载jdk
    ·找到jdk安装目录的_uninst子目录
      ·在shell终端执行命令./uninstall.sh即可卸载jdk。  
     
     
  • Eclipse中JDK不兼容异常

    2009-06-08 23:35:07

    楼主的Eclipse版本、tomcat版本、安装了哪几个版本的jdk都没说清楚,实在不好判断,建议楼主搭一个MYeclipse6.5+tomact6.0的集成环境,用下面方法来配置jdk。应该就没问题了。

    1.Window --> Preferences -->Java --> compiler中的compiler compliance level对应的下拉菜单中选择JDK版本.

    2.Window --> Preferences -->MyEclipse --> Servers -->Tomcat --> Tomcat n.x -->JDK中的Tomcat JDK name下的下拉菜单中选择自己电脑上安装的JDK版本(必须与步骤1中的JDK版本一致).

    如果还是没有解决,不用着急,因为有些MyEclipse版本自带有JDK版本,所以也要将它改过来.

    3.Window --> Preferences -->Java -->Installed JRES,然后在右边选择与步骤1和2版本一致的JDK版本,如果没有,可以自己添加.然后选中就可以了.
  • Delphi通过ADO方式访问数据库

    2009-05-13 22:23:42

    Delphi通过ADO方式访问数据库

    1. ADO组件--àADOConnection -----à双击----àBuild--à建立数据源(Connection String)

                      -----Connected属性为 True

    2. ADO组件---àADODataSet--à选择Connection 为刚才建立的Connection1

                ----àConnectionText ---à点击属性栏左侧的“三个点”,显示TablesFields数据。---àSQL栏中输入自己设计好的SQL语句---àActive属性设为 True

     

     

    //下面是为了立即看到数据而做的操作,数据关联

    3.DataAccess组件------àDataSource--à选择 Dataset属性的值为刚建立的ADODataSet1

     

    4.DataControls组件-----àDBGrid---à选择DataSource属性为刚建立的DataSource1

                    -------à这时可以看到查询出来的数据  

     

     


    object Form1: TForm1
      Left = 240
      Top = 208
      Width = 696
      Height = 480
      Caption = 'Form1'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style. = []
      ldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object DBGrid1: TDBGrid
        Left = 48
        Top = 216
        Width = 320
        Height = 120
        DataSource = DataSource1
        TabOrder = 0
        TitleFont.Charset = DEFAULT_CHARSET
        TitleFont.Color = clWindowText
        TitleFont.Height = -11
        TitleFont.Name = 'MS Sans Serif'
        TitleFont.Style. = []
      end
      object DBEdit1: TDBEdit
        Left = 464
        Top = 160
        Width = 121
        Height = 21
        DataField = 'stuName'
        DataSource = DataSource1
        TabOrder = 1
      end
      object Edit1: TEdit
        Left = 464
        Top = 240
        Width = 121
        Height = 89
        TabOrder = 2
        nChange = Edit1Change
      end
      object ADOConnection1: TADOConnection
        Connected = True
        ConnectionString =
          'Provider=SQLOLEDB.1;Password=sa;Persist Security Info=True;User ' +
          'ID=sa;Initial Catalog=test;Data Source=127.0.0.1'
        Provider = 'SQLOLEDB.1'
        Left = 120
        Top = 40
      end
      object ADODataSet1: TADODataSet
        Active = True
        Connection = ADOConnection1
        CursorType = ctStatic
        CommandText = 'select stuName  from StuInfo'
        Parameters = <>
        Left = 120
        Top = 96
      end
      object DataSource1: TDataSource
        DataSet = ADODataSet1
        Left = 120
        Top = 160
      end
    end

     

     

     

     

     

  • 脚本语言python

    2009-05-11 13:12:33

    虽然java还没有学好,

    但总觉得应该学一门脚本语言,

    最近学java挺有感觉的,感觉java API文档真是不错哦

    看mldn视频的时候,练习的少,这次回过头来,主要是针对具体的练习题,敲代码

    java还是当下学习的重点,先把基础夯实,过了基础关,再把struts 看懂

    把书后面的那个练习做了,基本目标就达到了

    最主要的是要做练习,敲代码,而不能只停留在脑袋里的认识层面

    其实要学的东西很多哦,还有测试工具的使用loadrunner,qtp,

    想着按照自带的帮助文档,再细细的练习一遍,把英文的帮助文档过过

     

    测试也正忙起来了

    还有好多东西要做呢

    加油


    现在开源的测试工具有很多,
    Python可跨平台,易学易用。

    LR的功能非常强大,但大部分功能基本上用不到。

    能针对自己的需求来开发一个能工作的测试工具,将是个多么动人心弦的事情啊!

     

    好哦好哦,能在这里看到用Python的朋友,真是不简单!还以为Python如往上所说的,只是在国外流行。看来不全是的嘛,上个月我在图书馆看到一本Python编写网络程序的书,叫什么来着。等我找找哈,

    是叫《Python Network Programming》,已经有中译版咯。电子版可以到
    www.itpub.net上搜索到,嘿嘿。可惜我用Python没经验,观察下我咯。

    可以考虑学习JMeter的方式,也针对发送URL模式来编写这个程序。也把问题考虑太复杂咯,一步一步来。在CSDN的开源频道开个项目如何,我也尝试参加下这个项目咯。^_^,^_^。

     

     

    给两个用Python写的开源的web性能测试工具,供参考:

    FunkLoad:
    http://funkload.nuxeo.org/

    Pylot:
    http://www.pylot.org/


    与其自己从头开始,不如加入这些项目。

     

     

     

     

     

    python 写自动化性能测试脚本


    看了ZEE大神发的一个绿色 简单的http性能测试工具AB 让我觉得它真的很有趣
    于是就通过它联想一些有趣的事情,做个自动化性能测试脚本 大家有兴趣一起来写吧。
    先首发我的一些想法和代码,看官们都手下留情。
    1. #!/usr/bin/python
    2. # -*- coding: cp936 -*-
    3. #filename : SimpleAutoTest.py

    4. #
    5. #   writer : 天渊小剑
    6. #   @copyright -*- 2009-04-19  -*-
    7. #

    8. import os
    9. import sys
    10. import re
    11. #--------------------------------------
    12. #    Class Name :SimpleAutoTest
    13. #--------------------------------------
    14. class SimpleAutoTest:

    15.     #--------------------------------------------------
    16.     #   Function :
    17.     #        method__ : 主函数      Main__()      =>    private
    18.     #                   设置运行参数SetFormat__() =>    private
    19.     #                   写日志      __WriteLog()  =>    public
    20.     #                   读取日志    __ReadLog()   =>    public
    21.     #                   分析数据    __AnaylzData()=>    public
    22.     #                   结果估值    EvalData__()  =>    private
    23.     #
    24.     #--------------------------------------------------

    25.     def __init__ (self,exeFile,logFile,url):
    26.         '''
    27.             __init__
    28.         '''
    29.         self.SysPath = os.getcwd()
    30.         self.ToolPath = self.SysPath+'\\tool\\'
    31.         self.LogPaht = self.SysPath+'\\Log\\'
    32.         self.ToolName = exeFile
    33.         self.LogName = logFile
    34.         self.Url = url

    35.     def main__ (self):
    36.         self.SysCmd()

    37.     def SysCmd (self):
    38.         tmp = os.popen(self.ToolPath+self.ToolName+' -n 3 -c 4 '+self.Url).readlines()
    39.         print(tmp)

    40. '''1
    41.     def SetFormat__(self):

    42.     def writeLog__ (self):

    43.     def __AnaylzData (self):

    44.     def EvalData__ (self):
    45. '''




    46. #--------------------------------------
    47. #   Test Name :
    48. #--------------------------------------
    49. exeFile = 'ab'
    50. logFile = 'log.log'
    51. url = 'http://51hongka.com/news/index.html';
    52. bf = SimpleAutoTest(exeFile,logFile,url)
    53. bf.main__()
    复制代码

     

     

    本帖最后由 小剑天下 于 2009-4-19 10:39 编辑

    ZEE大神说的是,我的运行环境是python3.0  是我失误了
    安装完python 3.0后 启动windows下面的cmd窗口 需要在python的目录下才能运行下面命令
    但是由于我采用的是自动获取当前路径 因此需要修改程序里面的self.SysPath = os.getcwd()
    改成self.SysPath = simlpautotest的文件路径
    输入 python [progfilepath] 即可
    如果是在 idle下 你要把
    # -*- coding: cp936 -*- 去掉
    在前面加# -*- coding: cp936 -*-就可以正确显示中文 而python 的idle不支持
    我把我的proj 也当附件传上来。

    Simpautotest.rar(29.5 KB)

     

    期待加上LOG处理的模块,这样就可以用它了,如果再加上GUI,就更好了。大家一块加吧。

     

    ------------------------------------------------------------------------------


    小外企招聘高级软件测试,月薪最高18K,(北京)


    小外企招聘高级软件测试,月薪最高18K,(北京)

    也不算太小吧,200多人,中国人在美国创办的,原来是风投,后在美国找了个东家,现在是纯美资了,做视频会议的。工作地点是西二旗。

    高级测试工程师
    岗位职责
    1. 根据产品规范编写测试方案,验证系统是否满足需求,设计测试数据和测试用例,并进行相互之间评审;
    2. 实施软件测试,完成对产品的集成测试与系统测试,对产品的功能、性能及其他方
    面的测试负责;
    3. 对软件问题进行跟踪分析和报告,推动测试中发现问题及时合理地解决;
    4. 汇总测试执行情况,编制相关报告;

    任职要求:
    1. 计算机、通信、电子工程等相关专业毕业,本科毕业5年以上,硕士毕业3年以上相
    关工作经验。
    2. 精通系统分析和测试设计,熟悉功能和非功能测试方法
    3. 熟悉测试理论,熟悉功能测试、性能测试,熟悉软件测试的相关工具(测试管理及
    自动化测试工具,LoadRunner等)
    4. 熟悉基于接口的测试方法和子系统测试,能撰写测试程序和脚本。
    5. 熟悉TCP/IP,HTTP和SMTP等网络和应用协议,Linux平台上测试经验1年以上。
    6. 有较强的逻辑分析能力和学习能力,具备较强的总结能力
    7. 热爱软件测试工作,可以胜任重复性工作,工作细致认真,有耐心;拥有较好的沟
    通技巧及团队合作精神,较强的责任感及进取精神
    8. 有pytho等脚本语言编程经验者优先,有c++/java开发项目经验者优先

    补充说明:
    这个职位首选做核心网测试的,或至少是做服务器端测试的,不要做客户端的测试的,且必须要会写测试方案。
    base不超过18k。
    测试人员可以从电信公司找,做过核心网测试的,薪资待遇10-18K之间;
    目标公司:大型通信公司,互联网公司或大型软件公司都行。


     
     
     
    Python   百度
  • Servlet请求转发 RequestDispatcher接口

    2009-05-03 21:56:21

    RequestDispatcher的介绍
    2007年02月15日 星期四 下午 03:40

    RequestDispatcher是一个Web资源的包装器,可以用来把当前request传递到该资源,或者把新的资源包括到当前响应中。RequestDispatcher接口中定义了两个方法:include/forward

    由于<jsp:include>只能指定固定的jsp文件名,不能动态指定jsp文件名。我们需要把<jsp:include>翻译为Java code – RequestDispatcher.include();

    用法:
    <% request.getRequestDispatcher(filename).include(request, response); />

    服务器端的重定向可以有两种方式,一是使用HttpServletResponse的sendRedirect()方法,一是使用RequestDispatcher的forward()方法.

    HttpServletResponse.sendRedirect()方法将响应定向到参数location指定的、新的URL。location可以是一个绝对的URL,如response.sendRedirect("http://java.sun.com")也可以使用相对的URL。如果location以“/”开头,则容器认为相对于当前Web应用的根,否则,容器将解析为相对于当前请求的URL。这种重定向的方法,将导致客户端浏览器的请求URL跳转。从浏览器中的地址栏中可以看到新的URL地址,作用类似于上面设置HTTP响应头信息的实现。


    RequestDispatcher.forward()方法将当前的request和response重定向到该RequestDispacher指定的资源。这在实际项目中大量使用,因为完成一个业务操作往往需要跨越多个步骤,每一步骤完成相应的处理后,转向到下一个步骤。比如,通常业务处理在Servlet中处理,处理的结果转向到一个JSP页面进行显示。这样看起来类似于Servlet链的功能,但是还有一些区别。一个RequestDispatcher对象可以把请求发送到任意一个服务器资源,而不仅仅是另外一个Servlet。 include()方法将把Request Dispatcher资源的输出包含到当前输出中。

    注意,只有在尚未向客户端输出响应时才可以调用forward()方法,如果页面缓存不为空,在重定向前将自动清除缓存。否则将抛出一个IllegalStateException异常。

     

    Servlet请求转发 RequestDispatcher接口
    2008-12-31 15:33

    在Servlet中,利用RequestDispatcher对象,可以将请求转发给另外一个Servlet或JSP页面,甚至是HTML页面,来处理对请求的响应。

    一,RequestDispatcher接口方法简介  

          1,RequestDispatcher对象由Servlet容器来创建,封装一个由路径所标识的服务器资源。    

          2,RequestDispatcher接口中定义了二种方法用于请求转发:    

               forward(ServletRequest,ServletResponse)方法:      

                       将请求转发给服务器上另外一个Servlet,JSP页面,或者HTML文件       这个方法必须在响应被提交给客户端之前调用,否则抛出异常。      

                      方法调用后在响应中的没有提交的内容被自动消除。    

               include(ServletRequest,ServletResponse)方法 :     

                     用于在响应中包含其他资源(Servlet,JSP页面或HTML文件)的内容。      

                     即请求转发后,原先的Servlet还可以继续输出响应信息,转发到的Servlet对请求做出的响应将并入原先Servlet的响应对象中。      

          3,forward方法和include方法的区别:

                      forward方法调用后在响应中的没有提交的内容被自动消除。    include方法使原先的Servlet和转发到的Servlet都可以输出响应信息。   

    二,得到RequestDispatcher对象  

          三种方法可以得到RequestDispatcher对象:   

                 1,利用ServletRequest接口中的getRequestDispatcher(String path)方法。   

                  2,ServletContext接口中getNamedDispatcher(String path)和getRequestDispatcher(String path)方法。

         ServletRequest接口和ServletContext接口中getRequestDispatcher方法区别:   

                  1,参数的区别    

                          参数虽然都是资源路径名,ServletContext接口的中参数路径必须以“/”开始,是相对于当前Servlet上下文根,     ServletRequest接口中的参数路径不仅可以相对于当前Servlet上下文根,还可以相对与当前Servlet路径    

                 2,跨WEB应用程序访问资源    

                          通过ServletContext.getContext()方法获取另个WEB应用程序的上下文环境对象来     调用getRequestDispatcher(String path)方法 将请求转发到另个WEB应用程序的资源。                       

                         还需要在当前WEB应用程序配置中设置<context>元素,指定crossContext属性值为true。

    三,ServletResqonse接口中的sendReadirect()方法和forward()方法的区别  

            二个方法都是用于请求转发的方法,转发给另外的资源为客户端服务。但二者有本质的区别

           sendReadirect()方法原理:   

                  1,客户端发送请求,Servlet1做出处理。   

                  2,Servlet1调用sendReadirect()方法,将客户端的请求 重新定位 到Servlet2。   

                  3,客户端浏览器访问Servlet2.  

                 4,Servlet2对客户端浏览器做出响应。

           forward()方法原理:  

                  1,客户端发送请求,Servlet1做出处理。  

                  2,Servlet1调用sendReadirect()方法,将请求转发给Servlet2来处理请求,为客户端服务。   

                  3,Servlet2对客户端浏览器做出响应。      

          区别:   

               1,定位与转发   

                       sendReadirect()方法是重新定位到另外一个资源来处理请求,URL会重新定位,让客户端重新访问另外一个资源。     forward()方法是转发到另外一个资源来处理请求。URL不会变化。隐藏了处理对象的变化。   

               2,处理请求的资源的范围   

                     sendReadirect()方法可以跨WEB应用程序和服务器重新定位资源来处理请求。     forward()方法只能在应用程序内部转发。


     

  • MVC(Model View Controller)模型-视图-控制器

    2009-05-02 03:25:50

    mvc

    copyright: Apple Inc.

    目录
    MVC与模板概念的理解
    MVC如何工作
    为什么要使用 MVC
    MVC的优点
    MVC的缺点
    开发方式
    常见的MVC组件
        
       
       
      MVC(Model View Controller)模型-视图-控制器
       

       
       
       
      MVC与模板概念的理解

        MVC本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器。使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据你可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
        模型-视图-控制器(MVC)是Xerox PARC在八十年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已被广泛使用。最近几年被推荐为Sun公司J2EE平台的设计模式,并且受到越来越多的使用 ColdFusion 和 PHP 的开发者的欢迎。模型-视图-控制器模式是一个有用的工具箱,它有很多好处,但也有一些缺点。

       
      MVC如何工作

        MVC是一个设计模式,它强制性的使应用程序的输入、处理和输出分开。使用MVC应用程序被分成三个核心部件:模型、视图、控制器。它们各自处理自己的任务。
        视图
        视图是用户看到并与之交互的界面。对老式的Web应用程序来说,视图就是由HTML元素组成的界面,在新式的Web应用程序中,HTML依旧在视图中扮演着重要的角色,但一些新的技术已层出不穷,它们包括Macromedia Flash和象XHTML,XML/XSL,WML等一些标识语言和Web services.
        如何处理应用程序的界面变得越来越有挑战性。MVC一个大的好处是它能为你的应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,不管这些数据是联机存储的还是一个雇员列表,作为视图来讲,它只是作为一种输出数据并允许用户操纵的方式。
        模型
        模型表示企业数据和业务规则。在MVC的三个部件中,模型拥有最多的处理任务。例如它可能用象EJBs和ColdFusion Components这样的构件对象来处理数据库。被模型返回的数据是中立的,就是说模型与数据格式无关,这样一个模型能为多个视图提供数据。由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
        控制器
        
        控制器接受用户的输入并调用模型和视图去完成用户的需求。所以当单击Web页面中的超链接和发送HTML表单时,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后确定用哪个视图来显示模型处理返回的数据。
        现在我们总结MVC的处理过程,首先控制器接收用户的请求,并决定应该调用哪个模型来进行处理,然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视图格式化模型返回的数据,并通过表示层呈现给用户。

       
      为什么要使用 MVC

        大部分Web应用程序都是用像ASP,PHP,或者CFML这样的过程化(自PHP5.0版本后已全面支持面向对象模型)语言来创建的。它们将像数据库查询语句这样的数据层代码和像HTML这样的表示层代码混在一起。经验比较丰富的开发者会将数据从表示层分离开来,但这通常不是很容易做到的,它需要精心的计划和不断的尝试。MVC从根本上强制性的将它们分开。尽管构造MVC应用程序需要一些额外的工作,但是它给我们带来的好处是无庸质疑的。
        首先,最重要的一点是多个视图能共享一个模型,现在需要用越来越多的方式来访问你的应用程序。对此,其中一个解决之道是使用MVC,无论你的用户想要Flash界面或是 WAP 界面;用一个模型就能处理它们。由于你已经将数据和业务规则从表示层分开,所以你可以最大化的重用你的代码了。
        由于模型返回的数据没有进行格式化,所以同样的构件能被不同界面使用。例如,很多数据可能用HTML来表示,但是它们也有可能要用Macromedia Flash和WAP来表示。模型也有状态管理和数据持久性处理的功能,例如,基于会话的购物车和电子商务过程也能被Flash网站或者无线联网的应用程序所重用。
        因为模型是自包含的,并且与控制器和视图相分离,所以很容易改变你的应用程序的数据层和业务规则。如果你想把你的数据库从MySQL移植到Oracle,或者改变你的基于RDBMS数据源到LDAP,只需改变你的模型即可。一旦你正确的实现了模型,不管你的数据来自数据库或是LDAP服务器,视图将会正确的显示它们。由于运用MVC的应用程序的三个部件是相互独立,改变其中一个不会影响其它两个,所以依据这种设计思想你能构造良好的松偶合的构件。
        对我来说,控制器的也提供了一个好处,就是可以使用控制器来联接不同的模型和视图去完成用户的需求,这样控制器可以为构造应用程序提供强有力的手段。给定一些可重用的模型和视图,控制器可以根据用户的需求选择模型进行处理,然后选择视图将处理结果显示给用户。

       
      MVC的优点

        ◆低耦合性。视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。
        ◆高重用性和可适用性。随着技术的不断进步,现在需要用越来越多的方式来访问应用程序。MVC模式允许你使用各种不同样式的视图来访问同一个服务器端的代码。它包括任何WEB(HTTP)浏览器或者无线浏览器(wap),比如,用户可以通过电脑也可通过手机来订购某样产品,虽然订购的方式不一样,但处理订购产品的方式是一样的。由于模型返回的数据没有进行格式化,所以同样的构件能被不同的界面使用。例如,很多数据可能用HTML来表示,但是也有可能用WAP来表示,而这些表示所需要的仅令是改变视图层的实现方式,而控制层和模型层无需做任何改变。
        ◆较低的生命周期成本。MVC使降低开发和维护用户接口的技术含量成为可能。
        ◆快速的部署。使用MVC模式使开发时间得到相当大的缩减,它使程序员(Java开发人员)集中精力于业务逻辑,界面程序员(HTML和JSP开发人员)集中业务于表现形式上。
        ◆可维护性。分熟视图层和业务逻辑层也使得WEB应用更易于维护和修改。
        ◆有利于软件工程化管理。由于不同的层各司其职,每一层不同的应用具有某些相同的特征,有利于通过工程化、工具化管理程序代码。

       
      MVC的缺点

        MVC的缺点是由于它没有明确的定义,所以完全理解MVC并不是很容易。使用MVC需要精心的计划,由于它的内部原理比较复杂,所以需要花费一些时间去思考。
        你将不得不花费相当可观的时间去考虑如何将MVC运用到你的应用程序,同时由于模型和视图要严格的分离,这样也给调试应用程序到来了一定的困难。每个构件在使用之前都需要经过彻底的测试。一旦你的构件经过了测试,你就可以毫无顾忌的重用它们了。
        根据开发者经验,由于开发者将一个应用程序分成了三个部件,所以使用MVC同时也意味着你将要管理比以前更多的文件,这一点是显而易见的。这样好像我们的工作量增加了,但是请记住这比起它所能带给我们的好处是不值一提。
        MVC并不适合小型甚至中等规模的应用程序,花费大量时间将MVC应用到规模并不是很大的应用程序通常会得不偿失。
        MVC设计模式是一个很好创建软件的途径,它所提倡的一些原则,像内容和显示互相分离可能比较好理解。但是如果你要隔离模型、视图和控制器的构件,你可能需要重新思考你的应用程序,尤其是应用程序的构架方面。如果你肯接受MVC,并且有能力应付它所带来的额外的工作和复杂性,MVC将会使你的软件在健壮性,代码重用和结构方面上一个新的台阶。

       
      开发方式

        Java开发Web Application有几种符合MVC设计模式的开发方式。
        1:Jsp+Servlet+JavaBean(EJB)
        2:Jsp+JavaBean(Controller)+JavaBean(EJB)(Model)
        3:TDK(Turbine,Velocity...)
        4:Xsp 5:Jsp+Struts+JavaBean(EJB)

       
        .NET开发Web Application可以采用:
        1: ASP.NET MVC Framework(ASP.NET MVC Beta版)
        2:MonoRail (RC3)
        php 开发Web Application 可以采用:
        1. Zend framework PHP官方框架
        2. fleaphp/Qeephp 等国内流行框架
        3.CakePHP 等国外流行框架

       
      常见的MVC组件

        Struts: Apache的,最流行的MVC组件
        Struts2 :Apache用Struts 和 WebWork的组合出来的新产品,目前上升势头强劲
        WebWork: 这个可是老牌的MVC组件,后来组合成了Struts2, 不过自身仍在发展
        Spring MVC:SpringFramework自己整合自己Spring的优势推出的MVC组件,用户也不少
        JSF: 这个是一个规范,Sun的和 Apache的都有各自的实现。用户量很大,被众多IDE支持。
        Tapestry: 最彻底的MVC开发框架,丰富的组件资源,重用性很高。组件扮演着控制器Controller的角色,是模式层(Model) 中pure-domain objects和包含有组件的HTML模板之间的媒介。大多数情况下,这种方式应用于页面(页面也 是 Tapestry组件),但是在某些情况中,一个组件拥有自己的模板,包含着更多的组件,并且支持与使用者的互交。页面通过配置一系列属性表达式(Property expressions)连接模式层和表现层。属性表达式使用另外一种开源框架OGNL(Object Graph Navigation Language)。OGNL的开源工程(project)独立于Tapestry,但是在Tapestry中起很重要的作用。OGNL主要的目的在于读取和更新对象的Java Bean属性。
       
       
       
      对MVC的讲解不错
    • Java Web实践专题——基本MVC实例------经典转载

      2009-05-02 03:21:00

           Jsp + Servlet + javabean 

          本文介绍了一个MVC实例,涉及文件如下:

      l         login.jsp——视图部分的输入文件
      l         success.jsp——视图部分的输出文件
      l         failure.jsp——视图部分的输出文件
      l         LoginBean.java——模型部分
      l         LoginServlet.java——控制器部分
      l         web.xml——web应用的配置文件
      下面分别介绍:
      1、login.jsp
      该功能的输入文件,用户首先访问这个文件。主要用于输入用户名和口令。
      代码如下:
      <%@ page contentType="text/html;charset=gb2312"%>
      <script. language="JavaScript">
         function isValidate(form)
         {
                // 得到用户输入的信息
                username = form.username.value;
                userpass = form.userpass.value;
       
                // 判断用户名长度
                if(!minLength(username,6))
                {
                       alert("用户名长度小于6位!");
                       form.username.focus();
                       return false;
                }
                if(!maxLength(username,8))
                {
                       alert("用户名长度大于8位!");
                       form.username.focus();
                       return false;
                }
       
                // 判断口令长度
             if(!minLength(userpass,6))
                {
                       alert("口令长度小于6位!");
                       form.userpass.focus();
                       return false;
                }
                if(!maxLength(userpass,8))
                {
                       alert("口令长度大于8位!");
                       form.userpass.focus();
                       return false;
                }
       
       
                return true;
         }
         // 验证是否满足最小长度
         function minLength(str,length)
         {
                if(str.length>=length)
                       return true;
                else
                       return false;
         }
         // 判断是否满足最大长度
         function maxLength(str,length)
         {
                if(str.length<=length)
                       return true;
                else
                       return false;
         }
      </script>
      <html>
         <head>
            <title>用户登陆</title>
         </head>
         <body>
            <h2>用户登录</h2>
            <form. name="form1" action="login" method="post"
                   nsubmit="return isValidate(form1)">
                   用户名:<input type="text" name="username"> <br>
                   口令:<input type="password" name="userpass"><br>
                   <input type="reset" value="重置">
                   <input type="submit" value="提交"><br>
            </form>
         </body>
      </html>
      代码中提供了客户端验证功能(用户名和口令的长度为6-8位)。验证通过之后会把请求提交给控制器Servlet。
      2、success.jsp
      登录成功之后会跳转到这个界面,界面的代码如下:
      <%@ page contentType="text/html;charset=gb2312"%>
      <html>
         <head>
            <title>登录成功</title>
         </head>
         <body>
            <h2>${sessionScope.username}您好,欢迎登录网上书店!</h2>
         </body>
      </html>
      代码中使用表达式语言把登录后的用户信息显示在街面上。
      3、failure.jsp
      登录失败后会跳转到这个界面,界面的代码如下:
      <%@ page contentType="text/html;charset=gb2312"%>
      <html>
         <head>
            <title>登录失败</title>
         </head>
         <body>
            <h2>用户名或者口令不正确,请<a href="login.jsp">重新登录!</a></h2>
         </body>
      </html>
      代码中提供了一个超链接,能够链接到登录界面。
      4、LoginBean.java
          完成登录功能,这里假设用户名和口令相等表示登录成功。
      package beans;
       
      public class LoginBean {
       
             public boolean validate(String username,String userpass){
                    return username.equals(userpass);
             }
       
      }
      5、LoginServlet.java
      该文件完成控制,主要功能可以描述如下:
      l         从login.jsp获取用户输入的用户名和口令;
      l         创建LoginBean的对象,调用LoginBean的方法validate;
      l         根据方法返回的结果,选择success.jsp或者failure.jsp对用户响应。
      完整的代码如下:
      package servlets;
       
      import java.io.IOException;
      import java.io.PrintWriter;
       
      import javax.servlet.*;
      import javax.servlet.http.*;
       
      import beans.*;
       
      public class LoginServlet extends HttpServlet {
       
             public void doGet(HttpServletRequest request, HttpServletResponse response)
                           throws ServletException, IOException {
                      doPost(request,response);
       
             }
       
             public void doPost(HttpServletRequest request, HttpServletResponse response)
                           throws ServletException, IOException {
       
                   // 获取用户输入的用户ID和口令
                   String username = request.getParameter("username");
                   String userpass = request.getParameter("userpass");
                  
                   // 创建模型对象
                   LoginBean loginBean = new LoginBean();
                 
                   // 调用业务方法进行验证
                   boolean b = loginBean.validate(username,userpass);
       
                   // 要转向的文件
                   String forward;
       
                   // 如果登陆成功,把用户名写入session中,并且转向success.jsp,
                   // 否则转向failure.jsp
                   if(b){
                     
                      // 获取session
                      HttpSession session = (HttpSession)request.getSession(true);
              
                      // 把用户名保存到session中
                     session.setAttribute("username",username);
              
                      // 目标转向文件是success.jsp
                      forward = "success.jsp";
       
                   }else{
       
                      // 目标转向文件是failure.jsp
                      forward = "failure.jsp";
       
                   }
                        
                   // 获取Dispatcher对象
                   RequestDispatcher dispatcher = request.getRequestDispatcher(forward);
                   // 完成跳转
                   dispatcher.forward(request,response);
       
             }
       
      }
      代码中把登录用户的用户信息保存在了session中,在实际应用中同样也是这样处理的。
      6、web.xml
      主要代码是Servlet的配置,代码如下:
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app version="2.4"
             xmlns="http://java.sun.com/xml/ns/j2ee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
             http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
       <servlet>
          <description>This is the description of my J2EE component</description>
          <display-name>This is the display name of my J2EE component</display-name>
          <servlet-name>LoginServlet</servlet-name>
          <servlet-class>servlets.LoginServlet</servlet-class>
       </servlet>
       
       <servlet-mapping>
          <servlet-name>LoginServlet</servlet-name>
          <url-pattern>login</url-pattern>
       </servlet-mapping>
       
      </web-app>
       
       
       
       
       
      请问我在开发中能否用多个类继承ActionServlet类来处理不同页面的请求
      如果可以   在web.xml里是否只需要简单的配置一下自己的ActionServlet就可以了
      比如      
      <servlet>
              <servlet-name> myServlet </servlet-name>
              <servlet-class> xxxx.xxx.myServlet </servlet-class>
      </servlet>
      谢谢
       
      发表于:2007-02-20 12:06:391楼 得分:15

      没有必要这样吧

      你的action   就是用来处理不同页面请求的

      ActionServlet   只是一个总的控制引擎   来分发不同页面请求到不同的action

      你如果想这样做   就没有必要写继承ActionServlet   了

      自己写几个简单的servlet   不就得   了

      那么如果我写了servlet的话   jsp页面到底应该发送个servlet还是action啊   麻烦回复下吧   谢谢

       

      那么如果我写了servlet的话   jsp页面到底应该发送个servlet还是action啊   麻烦回复下吧   谢谢

       
      请求   肯定只能   发给servlet   然后servlet帮你处理请求  
      哦   再通过servlet来调用action吗
      对啊
      那么action中
      public   ActionForward   execute(ActionMapping   mapping,   ActionForm.   form,
      HttpServletRequest   request,   HttpServletResponse   response)
      有四个参数呢   而servlet中的doPost只有2个参数   这样的话是不是要在doPost中先获取mapping   和form.   的值   然后再调用action中的execute方法啊  

      呵呵   问题是我不知道怎么获取mapping   和   form.   的值啊   麻烦讲下吧
       
      不用你写这个servletAction   ,   已经有现成的了,   struts自带.
      org.apache.struts.action.ActionServlet   这个类就是你要写的
      把这个配置进Web.xml就行了,   你找点struts的入门看看吧

           web.xml
       
      <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
       

        <servlet>
          <servlet-name>action</servlet-name>
          <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
          <init-param>
            <param-name>config</param-name>
            <param-value>/WEB-INF/struts-config.xml</param-value>
          </init-param>
          <init-param>
            <param-name>debug</param-name>
            <param-value>3</param-value>
          </init-param>
          <init-param>
            <param-name>detail</param-name>
            <param-value>3</param-value>
          </init-param>
          <load-on-startup>0</load-on-startup>
        </servlet>
        <servlet-mapping>
          <servlet-name>action</servlet-name>
          <url-pattern>*.do</url-pattern>
        </servlet-mapping>
      </web-app>
       




       
       
       
       
       
    • 用struts2开发一个简单的登录验证

      2009-05-02 01:18:20

       

        2.2.1 新建WebProject,添加Struts框架支持文件
        2.2.2 视图层V-View的添加   Form&Jsp
        2.2.3 控制层C-Controller的添加  Jsp,Forward
        2.2.4 模型层M-Model的添加  Action ,逻辑功能
        2.2.5 结尾前小小的改动,修改 <html:form. action="/login.do">
        

          2.2.6 struts-config.xml文件
        2.2.7 部署项目并运行

       

      一、开发环境:
      1.  jdk 1.5
      2.  eclipse 3.2.0/3.2.1
      3.  MyEclipse Enterprise Workbench 5.0.1GA
      4.  tomcat 5.5.20

      (环境搭建省略)

      二、第一个struts实例-----登录

        1 添加Struts框架支持文件
             新建一个webProject,
             然后为工程添加 Myeclipse---->Add struts Capabilities
        2 视图层V-View的添加 
         WebRoot节点 New-->Other-->MyEclipse-->Web-Struts-->Struts 1.2
               -->Struts 1.2 Form   -->login.jsp LoginForm.java
        3 控制层C-Controller的添加
             (1)创建JSP文件:
                form节点  new --> JSP(A T) --->true.jsp 和 false.jsp
             (2)创建ActionForward转发:
                 Web-INF-->struts-config.xml-->Design(模式)
                  New-->Forward-->Name:true;Path:/form/true.jsp
                                  Name:false;Path:/form/false.jsp
        4 模型层M-Model的添加 
        (1)WebRoot-->New-->Other-->MyEclipse-->Web-Struts-->Struts 1.2
           -->Struts 1.2 Action -->Use case: login
        (2) Form标签: Name:loginForm    Input Source: /form/login.jsp
        (3) 编写M(模型)层的逻辑功能程序, LoginAction.java
             核心代码:
             package com.yourcompany.struts.action;

             import javax.servlet.http.HttpServletRequest;
             import javax.servlet.http.HttpServletResponse;
             import org.apache.struts.action.Action;
             import org.apache.struts.action.ActionForm;
             import org.apache.struts.action.ActionForward;
             import org.apache.struts.action.ActionMapping;
             import com.yourcompany.struts.form.LoginForm;
            
          public class LoginAction extends Action {

       public ActionForward execute(ActionMapping mapping, ActionForm. form,HttpServletRequest request, HttpServletResponse response) {
        
           LoginForm. loginForm. = (LoginForm) form;
          String username = loginForm.getUsername();
          String password  = loginForm.getPassword();
        
          if((username.equals("abc"))&&(password.equals("xyz"))){
              return mapping.findForward("true");
             }
          else{
              return mapping.findForward("false");
          }
        
       }
      }

         5 结尾前小小的改动
          修改login.jsp中的<html:form. action="/login.do">


        6 struts-config.xml文件
      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">

      <struts-config>
        <data-sources />
        <form-beans >
          <form-bean name="loginForm" type="com.yourcompany.struts.form.LoginForm" />

        </form-beans>

        <global-exceptions />
        <global-forwards >
          <forward name="true" path="/form/true.jsp" />
          <forward name="false" path="/form/false.jsp" />

        </global-forwards>

        <action-mappings >
          <action
            attribute="loginForm"
            input="/form/login.jsp"
            name="loginForm"
            path="/login"
            scope="request"
            type="com.yourcompany.struts.action.LoginAction" />

        </action-mappings>

        <message-resources parameter="com.yourcompany.struts.ApplicationResources" />
      </struts-config>


        7 部署项目并运行

    • java数组的定义与使用方法

      2009-04-30 16:10:06

      数组是有序数据的集合,数组中的每个元素具有相同的数组名和下标来唯一地确定数组中的元素。

      §5.1一维数组

      一、一维数组的定义

      type arrayName[];

      其中类型(type)可以为Java中任意的数据类型,包括简单类型组合类型,数组名arrayName为一个合法的标识符,[]指明该变量是一个数组类型变量。例如:

      int intArray[];

      声明了一个整型数组,数组中的每个元素为整型数据。与C、C++不同,Java在数组的定义中并不为数组元素分配内存,因此[]中不用指出数组中元素个数,即数组长度,而且对于如上定义的一个数组是不能访问它的任何元素的。我们必须为它分配内存空间,这时要用到运算符new,其格式如下:

      arrayName=new type[arraySize];

      其中,arraySize指明数组的长度。如:

      intArray=new int[3];

      为一个整型数组分配3个int型整数所占据的内存空间。

      通常,这两部分可以合在一起,格式如下:

      type arrayName=new type[arraySize];

      例如:

      int intArray=new int[3];

      二、一维数组元素的引用

      定义了一个数组,并用运算符new为它分配了内存空间后,就可以引用数组中的每一个元素了。数组元素的引用方式为:

      arrayName[index]

      其中:index为数组下标,它可以为整型常数或表达式。如a[3],b[i](i为整型),c[6*I]等。下标 从0开始,一直到数组的长度减1。对于上面例子中的in-tArray数来说,它有3个元素,分别为:

      intArray[0],intArray[1],intArray[2]。注意:没有intArray[3]。

      另外,与C、C++中不同,Java对数组元素要进行越界检查以保证安全性。同时,对于每个数组都有一个属性length指明它的长度,例如:intArray.length指明数组intArray的长度。

      例5.1

      public class ArrayTest{
      public static void main(String args[]){
      int i;
      int a[]=newint[5];
      for(i=0;i<5;i++)
      a[i]=i;
      for(i=a.length-1;i>=0;i--)
      System.out.println("a["+i+"]="+a[i]);
      }
      }

      运行结果如下:

      C:\>java ArrayTest

      a[4]=4
      a[3]=3
      a[2]=2
      a[1]=1
      a[0]=0

      该程序对数组中的每个元素赋值,然后按逆序输出。

      三、一维数组的初始化

      对数组元素可以按照上述的例子进行赋值。也可以在定义数组的同时进行初始化。

      例如:

      int a[]={1,2,3,4,5};

      用逗号(,)分隔数组的各个元素,系统自动为数组分配一定空间。

      与C中不同,这时Java不要求数组为静态(static)。

      四、一维数组程序举例:

      例5.2Fibonacci数列

      Fibonacci数列的定义为:

      F1=F2=1,Fn=Fn-1+Fn-2(n>=3)

      public classFibonacci{
      public static void main(String args[]){
      int i;
      int f[]=new int[10];
      f[0]=f[1]=1;
      for(i=2;i<10;i++)
      f[i]=f[i-1]+f[i-2];
      for(i=1;i<=10;i++)
      System.out.println("F["+i+"]="+f[i-1]);
      }
      }

      运行结果为:

      C:\>java Fibonacci

      F[1]=1
      F[2]=1
      F[3]=2
      F[4]=3
      F[5]=5
      F[6]=8
      F[7]=13
      F[8]=21
      F[9]=34
      F[10]=55

      例5.3冒泡法排序(从小到大)

      冒泡法排序对相邻的两个元素进行比较,并把小的元素交到前面。

      public class BubbleSort{
      public static void main(String args[]){
      int i,j;
      int intArray[]={30,1,-9,70,25};
      int l=intArray.length;
      for(i=0;i<l-1;i++)
      for(j=i+1;j<l;j++)
      if(intArray[i]>intArray[j]){
      int t=intArray[i];
      intArray[i]=intArray[j];
      intArray[j]=t;
      }
      for(i=0;i<l;i++)
      System.out.println(intArray[i]+"");
      }
      }

      运行结果为:

      C:\>java BubbleSort
      -9
      1
      25
      30
      70

      §5.2多维数组

      与C、C++一样,Java中多维数组被看作数组的数组。例如二维数组为一个特殊的一维数组,其每个元素又是一个一维数组。下面我们主要以二维数为例来进行说明,高维的情况是类似的。

      一、二维数组的定义

      二维数组的定义方式为:

      type arrayName[][];

      例如:

      int intArray[][];

      与一维数组一样,这时对数组元素也没有分配内存空间,同要使用运算符new来分配内存,然后才可以访问每个元素。

      对高维数组来说,分配内存空间有下面几种方法:

      1直接为每一维分配空间,如:

      int a[][]=new int[2][3];

      2从最高维开始,分别为每一维分配空间,如:

      int a[][]=new int[2][];
      a[0]=new int[3];
      a[1]=new int[3];

      完成1中相同的功能。这一点与C、C++是不同的,在C、C++中必须一次指明每一维的长度。

      二、二维数组元素的引用

      对二维数组中每个元素,引用方式为:arrayName[index1][index2] 其中index1、index2为下标,可为整型常数或表达式,如a[2][3]等,同样,每一维的下标都从0开始。

      三、二维数组的初始化

      有两种方式:

      1直接对每个元素进行赋值。

      2在定义数组的同时进行初始化。

      如:int a[][]={{2,3},{1,5},{3,4}};

      定义了一个3×2的数组,并对每个元素赋值。

      四、二维数组举例:

      例5.4矩阵相乘

      两个矩阵Am×n、Bn×l相乘得到Cm×l,每个元素Cij=aik*bk (i=1..m,n=1..n)

      public class MatrixMultiply{
      public static void main(String args[]){
      int i,j,k;
      int a[][]=new int[2][3];
      int b[][]={{1,5,2,8},{5,9,10,-3},{2,7,-5,-18}};
      int c[][]=new int[2][4];
      for(i=0;i<2;i++)
      for(j=0;j<3;j++)
      a[i][j]=(i+1)*(j+2);
      for(i=0;i<2;i++){
      for(j=0;j<4;j++){
      c[i][j]=0;
      for(k=0;k<3;k++)
      c[i][j]+=a[i][k]*b[k][j];
      }
      }
      System.out.println("\n***MatrixA***");
      for(i=0;i<2;i++){
      for(j=0;j<3;j++)
      System.out.print(a[i][j]+"");
      System.out.println();
      }
      System.out.println("\n***MatrixB***");
      for(i=0;i<3;i++){
      for(j=0;j<4;j++)
      System.out.print(b[i][j]+"");
      System.out.println();
      }
      System.out.println("\n***MatrixC***");
      for(i=0;i<2;i++){
      for(j=0;j<4;j++)
      System.out.print(c[i][j]+"");
      System.out.println();
      }
      }
      }

      其结果为:

      C:\>java MatrixMultiply

      for(j=0;j<4;j++)
      System.out.print(c[i][j]+"");
      System.out.println();
      }
      }
      }

      其结果为:

      C:\>java MatrixMultiply

      ***MatrixA***
      2 3 4
      4 6 8
      ***MatrixB***
      1 5 2 8
      5 9 10 -3
      2 7 -5 -18
      ***MatrixC***
      25 65 14 -65
      50 130 28 -130


      如果你学过线性代数,应该可以比较好地理解多维数组。
      多维数组和矩阵结合紧密。

      a[i][j]就是第i-1行的第j-1列的元素,因为下标是从0开始的。
      比如:
      一个数组:1 2 3
      4 5 6
      a[0][0]=1 a[0][1]=2 a[0][2]=3
      a[1][0]=3 a[1][1]=5 a[1][2]=6
      我推荐你看几本书:
      1.Thinking in Java
      2.Java 2 核心技术
      3.Java2实用教程
      4.面向对象程序设计与java语言

    • 如何用java随机生成一个汉字?

      2009-04-30 11:13:44

       

      思路:生成一个随机数----转换成16进制或其他码值------转换成汉字字符---显示

      生成一个随机数,   在0x5000到0x9000之间的都是汉字

       

      我只讲原理,但具体到你使用什么编程工具是你自己的问题。

      任何编程开发工具都有随机数这个概念,而我们的区位码正好是由四位数字组成的,区位输入法可以输入GB2312-80的全部汉字,因此只需要随机产生一个四位的数字,并把这个数字换成区位码就成输出一个汉字,至于区位码中的空数你自己去查一查,用一段假设语句把它们排除掉。

      =============================================================

       区码:   汉字内码高位   -   0xA0  
        位码:   汉字内码低位   -   0xa0

      区号:01-87,汉字从16区开始,前15区为各种符号  
        位号:01-94  
        第一个汉字“啊”的区号为16,位号为01  
      续:  
        两字节内码:区号+0xA0   ,   位号+0xa0  
        如:第一个汉字“啊”的区号为16,位号为01,则其内码为     0xb0,0xa1

        ======>  区号:16---87 位号:01---94

       

      =========================================================

      JAVA 区位码于汉字的互换

      import java.io.UnsupportedEncodingException;

      public class Test {
      // 发代码之前先转段预备知识
      //
      // 计算机处理汉字信息的前提条件是对每个汉字进行编码,这些编码统称为汉字编码。汉字信息在系统内传送的过程就是汉字编码转换的过程。
      // 汉字交换码:汉字信息处理系统之间或通信系统之间传输信息时,对每一个汉字所规定的统一编码,我国已指定汉字交换码的国家标准“信息交换用汉字编码字符集——基本集”,代号为GB
      // 2312—80,又称为“国标码”。
      // 国标码:所有汉字编码都应该遵循这一标准,汉字机内码的编码、汉字字库的设计、汉字输入码的转换、输出设备的汉字地址码等,都以此标准为基础。GB
      // 2312—80就是国标码。该码规定:一个汉字用两个字节表示,每个字节只有7位,与ASCII码相似。
      // 区位码:将GB
      // 2312—80的全部字符集组成一个94×94的方阵,每一行称为一个“区”,编号为0l~94;每一列称为一个“位”,编号为0l~94,这样得到GB
      // 2312—80的区位图,用区位图的位置来表示的汉字编码,称为区位码。
      // 机内码:为了避免ASCII码和国标码同时使用时产生二义性问题,大部分汉字系统都采用将国标码每个字节高位置1作为汉字机内码。这样既解决了汉字机内码与西文机内码之间的二义性,又使汉字机内码与国标码具有极简单的对应关系。
      // 汉字机内码、国标码和区位码三者之间的关系为:区位码(十进制)的两个字节分别转换为十六进制后加20H得到对应的国标码;机内码是汉字交换码(国标码)两个字节的最高位分别加1,即汉字交换码(国标码)的两个字节分别加80H得到对应的机内码;区位码(十进制)的两个字节分别转换为十六进制后加A0H得到对应的机内码。

      public String bytes2HexString(byte b) {
      return bytes2HexString(new byte[] { b });
      }

      // 汉字转换成区位码
      public String bytes2HexString(byte[] b) {
      String ret = "";
      for (int i = 0; i < b.length; i++) {
      String hex = Integer.toHexString(b[i] & 0xFF);
      if (hex.length() == 1) {
      hex = '0' + hex;
      }
      ret += hex.toUpperCase();
      }
      return ret;
      }

      // 汉字转换成区位码
      public String getString(String chinese) {
      byte[] bs;
      String s = "";
      try {
      bs = chinese.getBytes("GB2312");

      for (int i = 0; i < bs.length; i++) {
      int a = Integer.parseInt(bytes2HexString(bs[i]), 16);
      s += (a - 0x80 - 0x20) + "";
      }
      } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
      }
      return s;
      }

      // 区位码转换成汉字
      public String CodeToChinese(String code) {
      String Chinese = "";
      for (int i = 0; i < code.length(); i += 4) {
      byte[] bytes = new byte[2];
      String lowCode = code.substring(i, i + 2);
      int tempLow = Integer.parseInt(lowCode);
      tempLow += 160;
      bytes[0] = (byte) tempLow;
      String highCode = code.substring(i + 2, i + 4);
      int tempHigh = Integer.parseInt(highCode);
      tempHigh += 160;
      bytes[1] = (byte) tempHigh;
      String chara = new String(bytes);
      Chinese += chara;
      }
      return Chinese;
      }

      // 测试
      public static void main(String[] args) throws Exception {
      String str = "创";
      Test test = new Test();
      String s = test.getString(str);
      System.out.println(s);
      String a = test.CodeToChinese(s);
      System.out.println(a);
      }

      }

       

      --------------------------------------------------------------

      Excel2007生成随机姓名

      在实际生活中,我们经常需要列出一系列随机的数据用以辅助说明问题。使用Excel2007的RAND函数,可以很方便地生成随机数字;可是,当需要用到人员姓名的时候则很头痛,使用张1、张2、张3之类的名字太难看了,而若想要生成看上去“真实”的随机姓名,笔者找遍百度也没有发现合适的,只好自己来实现了。
        国人的姓名,是分别由姓和名两部分组成,因此我们只需要生成随机的姓,再生成随机的名,组合即可。
        常用的姓氏比较好查,在百度(
      www.baidu.com)里搜索“百家姓”就可以找到。打开Excel2007新建一个工作簿,将工作表Sheet2更名为“常用姓氏表”,把这些常见的姓氏复制到其中,并整理为一列。笔者找到的常用姓氏占单元格A2:A158共计157个。(提示:可以使用“数据-数据工具-分列”菜单项方便将数据拆分)
        用作名字的字词比较多,在百度里搜索“常用名”、“常用字”或“常用名字”等都找不倒合适的数据。最终搜索关键词“取名常用字”,找到了大量用在名字中的单字和词。同样的方法将其添加到的Sheet3中,整理为一列,并将工作表更名为“常用名表”。笔者找到的常用名字占单元格A2:A424共计423个。
        将工作表Sheet1更名为“随机姓名”,在A2
      单元格输入公式“=INDEX(常用姓氏表!$A$2:$A$158,INT(RAND()*157+1))&INDEX(常用名表!$A$2:$A$424,INT(RAND()*423 +1))”,然后将此公式复制到表格的其他位置,即可生成批量随机姓名。
        简单介绍一下公式各部分的含义:
        1、RAND函数,可以得到一个介于0和1之间的随机小数。
        2、INT函数,将得到数字的整数部分。
        3、生成指定范围内随机整数通常采用如下公式“INT(RAND()*(上界-下界+1)+下界”。例如“INT(RAND()*157+1)”可以生成1~157之间(含)的随机整数。
        4、INDEX函数可以得到指定范围内指定位置的数值。
        5、“&”符号,可以将两段文字连接起来生成一段新的文字。
        如此,把生成的随机姓名放到数据之中,数据也就显得正规多了。
      参考:http://www.officeba.com.cn/article/htmldata/detail/2008/7/3/2285.html

       

    • Java判断时间,Email,手机号是否为正确格式

      2009-04-30 10:10:29

    • JAVA的整型与字符串相互转换(简单实用)

      2009-04-30 09:29:37

      JAVA的整型与字符串相互转换

      int i = Integer.parseInt([String]);

      String s = Integer.toString([int]);


      1如何将字串 String 转换成整数 int? 
       
        有两个方法:
       
      1). int i = Integer.parseInt([String]); 或 
            int i = Integer.parseInt([String],[int radix]);
       
      2). int i = Integer.valueOf(my_str).intValue();
       
      注: 字串转成 Double, Float, Long 的方法大同小异.
       

      2 如何将整数 int 转换成字串 String ?
       

         有叁种方法:
       
      1.) String s = String.valueOf(i);
       
      2.) String s = Integer.toString(i);
       
      3.) String s = "" + i;
       
      注: Double, Float, Long 转成字串的方法大同小异.

       

      <%@ page contentType="text/html;charset=gb2312"%>
      <html>
      <body>
      <form. action="" method="post">
      <input type="text" name="name">加
      <input type="text" name="pass"><br>
      <input type="submit" value="提交">
      </form>
      <%
      String name=request.getParameter("name");
      String pass=request.getParameter("pass");
      if(name==null){name="1";}
      if(pass==null){pass="2";}
      int a = Integer.valueOf(name).intValue();
      int b = Integer.valueOf(pass).intValue();
      out.print(a+b);
      %>
      </body>
      </html> 

    • 身份证号编码规则[转]

      2009-04-30 09:26:13

      15位的身份证号
      dddddd yymmdd xx p
      18位的身份证号

      dddddd yyyymmdd xx p y
      其中dddddd为地址码(省地县三级)18位中的和15位中的不完全相同

      yyyymmdd yymmdd 为出生年月日

      xx顺号类编码

      p性别

      18位中末尾的y为校验码,在网上可以找到算法

      将前17位的ascii码值经位移、异或运算结果不在0-9的令其为
      x

      现将“18位身份证标准提供如下:

      18位身份证标准在国家质量技术监督局于199971实施

      GB11643-1999《公民身份号码》中做了明确的规定。

      GB11643-1999《公民身份号码》为GB11643-1989《社会保障

      号码》的修订版,其中指出将原标准名称社会保障号码更名

      公民身份号码,另外GB11643-1999《公民身份号码》从实

      施之日起代替GB11643-1989

      GB11643-1999《公民身份号码》主要内容如下:

      一、范围

      该标准规定了公民身份号码的编码对象、号码的结构和表现

      形式,使每个编码对象获得一个唯一的、不变的法定号码。

      二、编码对象

      公民身份号码的编码对象是具有中华人民共和国国籍的公民。

      三、号码的结构和表示形式

      1、号码的结构

      公民身份号码是特征组合码,由十七位数字本体码和一位校

      验码组成。排列顺序从左至右依次为:六位数字地址码,八位数

      字出生日期码,三位数字顺序码和一位数字校验码。

      2、地址码

      表示编码对象常住户口所在县(市、旗、区)的行政区划代码,

      GB/T2260的规定执行。

      3、出生日期码

      表示编码对象出生的年、月、日,按GB/T7408的规定执行,

      年、月、日代码之间不用分隔符。

      4、顺序码

      表示在同一地址码所标识的区域范围内,对同年、同月、同

      日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配

      给女性。

      5、校验码

      (1)十七位数字本体码加权求和公式

      S = Ai * Wi, i = 2, ... , 18
      Y = mod(S, 11)
      i: 表示号码字符从右至左包括校验码字符在内的位置序号

      Ai:表示第i位置上的身份证号码字符值

      Wi:表示第i位置上的加权因子

      i: 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
      Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1
      (2)校验码字符值的计算

      Y: 0 1 2 3 4 5 6 7 8 9 10
      校验码
      : 1 0 X 9 8 7 6 5 4 3 2
      四、举例如下:

      北京市朝阳区
      : 11010519491231002X
      广东省汕头市
      : 440524188001010014

      15位的不需要研究了,很简单的:

      dddddd yymmdd xx p
      dddddd:地区码

      yymmdd:出生年月日

      xx:顺号类编码,无法确定

      p:性别,男的奇数女的偶数


      18位的:

      dddddd yyyymmdd xxx y
      dddddd:地区码

      yyyymmdd:出身年月日,为了应付千年虫问题,年升成4位数

      xxx:顺号类编码,无法确定。但是奇数分配给男性,偶数分配给女性

      y:校验码,最麻烦的地方

      校验码的计算方法:

      假如某身份号码34052419800101001,首先按照公式计算:

      (ai×Wi)(mod 11)……………………………………
      (1)
      公式(1)中:

      i----表示号码字符从由至左包括校验码在内的位置序号;

      ai----表示第i位置上的号码字符值;

      Wi----示第i位置上的加权因子

      i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
      ai 3 4 0 5 2 4 1 9 8 0 0 1 0 1 0 0 1 a1
      Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1 (加权因子,固定的数值
      )
      ai×
      Wi 21 36 0 25 16 16 2 9 48 0 0 9 0 5 0 0 2 a1
      根据公式(1)进行计算:

      (ai×Wi) =
      21+36+0+25+16+16+2+9+48++0+0+9+0+5+0+0+2) = 189
      189 ÷
      11 = 17 + 2/11
      (ai×
      Wi)(mod 11) = 2
      然后根据计算的结果,从下面的表中查出相应的校验码,其中X表示计算结果为10

      (ai×
      WI)(mod 11) 0 1 2 3 4 5 6 7 8 9 10
      校验码字符值
      ai 1 0 X 9 8 7 6 5 4 3 2
      根据上表,查出计算结果为2的校验码为所以该人员的公民身份号码应该为 34052419800101001X


      这样,按以上的算法,加上我的这个行政区代码数据库,除了顺号类编码以外所有的数字都可以确定了。

      数据库下在地址见附件


      注:数据库是根据中华人民共和国国家统计局截至2003630号的数据,但是之前有修改过的数据,详情见:


      http://www.stats.gov.cn/tjbz/index.htm。所以,假如是太早颁发的身份证在地区代码上可能有出入。可以参考国家统计局的数据
      进一步应用:这些资料加上ip地址省份分布数据库(追捕或者qqip地址数据库都可以,qq的地址数据库使用方法可以在精华区找),可以


      更准确地确认访问者的ip地址(不考虑使用代理或者访问者上网地不在其身份证颁发地的情况:>)。这个就不再深入了。

      另:

      我国自1999年实施公民身份号码制度以来,许多公民身份号码末位为“X”的公民,由于不明白“X”的含义,要求给予更换,产生了不必要的误会。目前我国公民身份证号码由18位数字组成:前6位为地址码,第7至14位为出生日期码,第15至17位为顺序码,第18位为校验码。检验码分别是“0、1、2、……10”共11个数字,当检验码为“10”时,为了保证公民身份证号码18位,所以用“X”表示。虽然校验码为“X”不能更换,但若需全用数字表示,只需将18位公民身份号码转换成15位居民身份证号码,去掉第7至8位和最后1位3个数码。

      当今的身份证号码有15位和18位之分。1985年我国实行居民身份证制度,当时签发的身份证号码是15位的,1999年签发的身份证由于年份的扩展(由两位变为四位)和末尾加了效验码,就成了18位。这两种身份证号码将在相当长的一段时期内共存。两种身份证号码的含义如下:

      18位的身份证号码 如:130429####%%%%0078

      1~6位为地区代码,其中1、2位数为各省级政府的代码,3、4位数为地、市级政府的代码,5、6位数为县、区级政府代码。如13(河北省)04(邯郸市)29(永年县)

      7~14位为出生年月日

      15~17位为顺序号,是县、区级政府所辖派出所的分配码,每个派出所分配码为10个连续号码,例如“000-009”或“060-069”,其中单数为男性分配码,双数为女性分配码,如遇同年同月同日有两人以上时顺延第二、第三、第四、第五个分配码。如:007的就是个男生 而且和他同年月日生的男生至少有两个 他们的后四位是001* 和 003*

      18位为效验位(识别码),通过复杂公式算出,普遍采用计算机自动生成。是前面17位的一种检验代码,如果你改变了前面某个数字而后面的效验代码不响应改变就会被计算软件判断为非法身份正号码。X也是效验代码的一中

      15位的身份证号码:

      (1)1~6位为地区代码

      (2)7~8位为出生年份(2位),9~10位为出生月份,11~12位为出生日期

      (3)第13~15位为顺序号,并能够判断性别,奇数为男,偶数为女。


    • Java 写入文件操作(转载)

      2009-04-30 01:11:08

      Java 写入文件操作
      2008年05月26日 星期一 13:49

      示例:

      从键盘中读入字符然后写入文件中,知道遇到“bye”退出

      /**
      * @(#)NewTest54.java
      *java试验五练习四
      *
      * @gaoandgao
      * @version 1.00 2008/5/26
      */
      import java.io.BufferedReader;
      import java.io.InputStreamReader;
      import java.io.IOException;
      import java.io.FileOutputStream;
      import java.io.FileWriter;
      import java.io.FileNotFoundException;
      import java.io.*;
      public class NewTest54 {
             
         
          public NewTest54() {
          }
         
         
          public static void main(String[] args){
          StringBuffer buffer=new StringBuffer();
              BufferedReader br=new BufferedReader(new InputStreamReader(System.in),1);
             
              for(;;){
              try{
              System.out.println("Input bye to exit");
              String string=br.readLine();
              if(string.equals("bye")){
                 File file=new File("output.txt");
                 DataOutputStream utput=new DataOutputStream(new FileOutputStream(file));
                 output.write(buffer.toString().getBytes());
                 output.close();
                 System.exit(0);
              }
                 else {
                  buffer.append(string);//先将字符串暂存到buffer中最后一起写入文件
                 }
              }catch(IOException ex){
              ex.printStackTrace();
              }
              }
             
          }
      }


      File temp = new File(outPut,"pro.xml");
      DataOutputStream uts = new DataOutputStream(new FileOutputStream(temp));
      outs.write(sb.toString().getBytes("utf-8")); //指定编码

      使用Java操作二进制文件一文中讲述了如何使用Java处理二进制的文件,这篇文章主要讲述如何使用java处理文本文件。

      最初java是不支持对文本文件的处理的,为了弥补这个缺憾而引入了Reader和Writer两个类,这两个类都是抽象类,Writer中write (char[] ch,int off,int length),flush()和close()方法为抽象方法,Reader中read(char[] ch,int off,int length)和close()方法是抽象方法。子类应该分别实现他们。

      当我们读写文本文件的时候,采用Reader是非常方便的,比如FileReader,InputStreamReader和 BufferedReader。其中最重要的类是InputStreamReader,它是字节转换为字符的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如GBK等。当使用FileReader读取文件的时候。
      FileReader fr = new FileReader("ming.txt");
      int ch = 0;
      while((ch = fr.read())!=-1 )
      {
      System.out.print((char)ch);
      }
      其中read()方法返回的是读取得下个字符。当然你也可以使用read(char[] ch,int off,int length)这和处理二进制文件的时候类似,不多说了。如果使用InputStreamReader来读取文件的时候
      while((ch = isr.read())!=-1)
      {
      System.out.print((char)ch);
      }
      这和FileReader并没有什么区别,事实上在FileReader中的方法都是从InputStreamReader中继承过来的。read()方法是比较好费时间的,如果为了提高效率我们可以使用BufferedReader对Reader进行包装,这样可以提高读取得速度,我们可以一行一行的读取文本,使用readLine()方法。
      BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ming.txt")));
      String data = null;
      while((data = br.readLine())!=null)
      {
      System.out.println(data);
      }
      当你明白了如何用Reader来读取文本文件的时候那么用Writer写文件同样非常简单。有一点需要注意,当你写文件的时候,为了提高效率,写入的数据会先放入缓冲区,然后写入文件。因此有时候你需要主动调用flush()方法。与上面对应的写文件的方法为
      FileWriter fw = new FileWriter("hello.txt");
      String s = "hello world";
      fw.write(s,0,s.length());
      fw.flush();

      OutputStreamWriter sw = new OutputStreamWriter(new FileOutputStream("hello2.txt"));
      osw.write(s,0,s.length());
      osw.flush();

      PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("hello3.txt")),true);
      pw.println(s);
      不要忘记用完后关闭流!下面是个小例子,帮助新手理解。其实有的时候java的IO系统是需要我们多记记的,不然哪天就生疏了。测试文件的内容为
      ming.txt


      hello world i like java language
      import java.io.*;


      public class TestFile2
      {
      public static void main(String[] args) throws IOException
      {
      FileReader fr = new FileReader("ming.txt");
      char[] buffer = new char[1024];
      int ch = 0;
      while((ch = fr.read())!=-1 )
      {
      System.out.print((char)ch);
      }

      InputStreamReader isr = new InputStreamReader(new FileInputStream("ming.txt"));
      while((ch = isr.read())!=-1)
      {
      System.out.print((char)ch);
      }

      BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("ming.txt")));
      String data = null;
      while((data = br.readLine())!=null)
      {
      System.out.println(data);
      }

      FileWriter fw = new FileWriter("hello.txt");
      String s = "hello world";
      fw.write(s,0,s.length());
      fw.flush();

      OutputStreamWriter sw = new OutputStreamWriter(new FileOutputStream("hello2.txt"));
      osw.write(s,0,s.length());
      osw.flush();

      PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("hello3.txt")),true);
      pw.println(s);

      fr.close();
      isr.close();
      br.close();
      fw.close();
      osw.close();
      pw.close();
      }
      }

    • Java生成18位身份证号-----终于功成

      2009-04-30 00:03:41

      package com.icss.oa.work;

      public class IDCard {
         // wi =2(n-1)(mod 11)
          final int[] wi = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; //

         // verify digit
          final int[] vi = {1,0,'X',9,8,7,6,5,4,3,2}; //

          private int[] ai = new int[18];

           public IDCard() {
            }
         //verify


         //get verify
          public  String getVerify(String eightcardid) { //eightcardid
          int remaining = 0;

          if (eightcardid.length() == 17) {
           int sum = 0;
           for (int i = 0; i < 17; i++) {
           String k = eightcardid.substring(i, i + 1);
           ai[i] = Integer.parseInt(k);
              }
       
           for (int i = 0; i < 17; i++) {
            sum = sum + wi[i]*ai[i];
              }
            remaining = sum % 11;
            return remaining == 2 ? "X" : String.valueOf(vi[remaining]);
       
        }
          else{
           return "出错了!";
          }
         
          }

          

         //用随机数  写出前17位

          public String getSheng(){
           // 第一二位 前两位 01- 64
              // int number = (int)(Math.random()*(tonum-fromnum))+fromnum;
             int number ;
          String str=null;
             number = (int)(Math.random()*(64-1)+1);
          if(number<10)
          {
           //转换成字符串
           
           str = Integer.toString(number);
           str = "0"+number;
           //System.out.println(str);
           return str;
          }
          else{
           
           //System.out.println(Integer.toString(number));
           return Integer.toString(number);
          }
          }
         
         
          public String getShi(){ 
           //第三四位 两位 01-02
             int number ;
             number = (int)(Math.random()*1+1);
          String str=null;
          if(number<10)
          {
           //转换成字符串
           
           str = Integer.toString(number);
           str = "0"+number;
           //System.out.println(str);
           return str;
          }
          else{
           
           //System.out.println(Integer.toString(number));
           return Integer.toString(number);
          }
                }  
        
         
           public String getXian(){
           //第五六位  两位  01-05
          int number ;
             number = (int)(Math.random()*4+1);
          String str=null;
          if(number<10)
          {
           //转换成字符串
           
           str = Integer.toString(number);
           str = "0"+number;
           //System.out.println(str);
           return str;
          }
          else{
           
           //System.out.println(Integer.toString(number));
           return Integer.toString(number);
          }    
              }
         
          public String getYear(){
           //第 7--10位   年份:1970-1990
        int number;
           number = (int)(Math.random()*(1990-1970)+1970);
        String str=null;
        if(number<10)
        {
         //转换成字符串
         
         str = Integer.toString(number);
         str = "0"+number;
         //System.out.println(str);
         return str;
        }
        else{
         
         //System.out.println(Integer.toString(number));
         return Integer.toString(number);
        }
          } 
        
          public String getMonth(){
           //第11 12 位      月份:01-12
        
        int number ;
           number = (int)(Math.random()*(12-1)+1);
        String str=null;
        if(number<10)
        {
         //转换成字符串
         
         str = Integer.toString(number);
         str = "0"+number;
         //System.out.println(str);
         return str;
        }
        else{
         
         //System.out.println(Integer.toString(number));
         return Integer.toString(number);
        }
          } 
        
       public String getDay(){
           //第13   14 位    日期:01-28
        
        int number ;
           number = (int)(Math.random()*(28-1)+1);
        String str=null;
        if(number<10)
        {
         //转换成字符串
         
         str = Integer.toString(number);
         str = "0"+number;
         //System.out.println(str);
         return str;
        }
        else{
         
         //System.out.println(Integer.toString(number));
         return Integer.toString(number);
        }
        
        
          }
         
          public String getSequence(){
           //第15  16 位        两位:01-99
        int number ;
           number = (int)(Math.random()*(99-1)+1);
        String str=null;
        if(number<10)
        {
         //转换成字符串
         
         str = Integer.toString(number);
         str = "0"+number;
         //System.out.println(str);
         return str;
        }
        else{
         
         //System.out.println(Integer.toString(number));
         return Integer.toString(number);
        }
          }
         
          public String getSex(){
               // 第17 位  一位性别:0-9
           int number ;
           number = (int)(Math.random()*(9-0)+0);
        return Integer.toString(number);  
          }

          public  String get17ID(){
           String str=null;
           str = this.getSheng()+this.getShi()+this.getXian()+ this.getYear()+ this.getMonth()+ this.getDay() + this.getSequence() + this.getSex()  ;
           return str;
          }
         
          public String getIDCard(){
           String str=null;
             str = this.get17ID() ;
           str = str + this.getVerify(str); 
           //String test = this.get17ID();
           //System.out.println("身份证号前17位:"+test);
           //System.out.println("身份证号:"+test+this.getVerify(test));
           return str;
          }

       

      public static void main(String[] args){
       
       IDCard card=new IDCard();
        
       //String idcard="41011119820316258";//  41112119821028551  41102219841112602  410111452105122564
      //String idcard = card.get17ID();
       //System.out.println("41124919810612243"+card.getVerify(idcard));
      //System.out.println("身份证的最后一位为:"+card.getVerify(idcard));
      //System.out.println("身份证的最后一位为:"+card.getVerify("你的身份证号前17位"));
       //System.out.println("身份证号前17位为:"+card.get17ID());
       System.out.println("身份证号为:"+card.getIDCard());

      }

      }

       

      /*
       *下面是 身份证号码的规则:

      身份证号码共18位.

      前6位是地址码. 省

      7--14位是出生年月日

      后面4位是生成的代码,

      第17位用来做性别判定:偶数 -- 女 ; 奇数--- 男 .

      前17位的构成: 2(省)+2(市)+2(县)+4(年)+2(月)+2(日)+2(序号)+1(性别)

      第十八位数字的计算方法为:
      1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
      2.将这17位数字和系数相乘的结果相加。
      3.用加出来和除以11,看余数是多少?
      4余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
      5.通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。


       */

       

      ----------------------------------------------------------------------------------------

      关于根据前17位计算第十八位的算法,那个是转的,自己又仿照练习了一遍

      package com.icss.oa.work;

      public class GetVerfycode {

       /**
        * @param args
        */
       
       /*
        *第十八位数字的计算方法为:
      1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
      2.将这17位数字和系数相乘的结果相加。
      3.用加出来和除以11,看余数是多少?
      4余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2。
      5.通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。
       
        */
       //定义一个无参构造方法
       public GetVerfycode(){
        
       }
       
       //准备基本数据
       final int[] coef = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
       final int[] mapping = {1,0,'X',9,8,7,6,5,4,3,2};
       private int[] store = new int[18];
       
       public String getCode(String number){
        String str = null;
        if(number.length()== 17){

         //取出17位的每一个值
         for(int i= 0;i< number.length() ;i++){
          String s = number.substring(i,i+1);
          store[i]= Integer.parseInt(s);
         }
         
         //乘以不同的系数,将这17位数字和系数相乘的结果相加
         int sum  = 0 ;
         for(int i=0;i<17;i++){
          sum = sum +store[i]*coef[i];
         }
         
         //用加出来和除以11,看余数是多少?
         int remaining  = sum % 11;
         //remaining = 2:'X'?
            if(remaining == 2){
             str = "X"; 
            }
            else{
             str = Integer.toString(mapping[remaining]);
            }
        }
        else{
         System.out.println("位数不对,出错!");
        }
        return str;
       }
       
       public static void main(String[] args) {
        // TODO Auto-generated method stub
        GetVerfycode code = new GetVerfycode();
        System.out.println("身份证的最后一位为:"+code.getCode("17位身份证号"));
       }

      }

       

      -------------------------------------------------------------------------------------

      后续,批量生成,将生成的数据,写入Excel表或者文本文件中

      //向文本中写入100个随机的身份证号,加入main方法中即可
      //import java.io.*;


       for(int n =1;n<100;n++){
        try{
         File f = new File("f:\\idcard.txt");
         if(f.exists()){
          //f.delete();
         }
         else{
          f.createNewFile();
         }
         FileWriter fw = new FileWriter(f,true);
         fw.write(card.getIDCard());
         fw.write('\n');
         fw.flush();
         fw.close();
        }catch(Exception e){
         System.out.println(e.getStackTrace());
        }
       }

       

      大功告成,呵呵

      虽然对于java高手来说小菜一碟,但对于我来说还是值得高兴的

      ======================================================

      关于地区码:可以采用已知的地区码常量来生成,利用数组随机取值

           // 得到六位的地区码

        public String getAreacode(){
         String[] area = {"110100","110101","110102","110103"};
           return area[(int)(Math.random()*(3519))] ;
           
          }

       

      身份证号码验证网站:http://qq.ip138.com/idsearch/index.asp
         

    • Java多线程的简单实例

      2009-04-28 17:34:43

      一 通过Thread类创建线程
       

      //ch02.OurClass.java
      public class OurClass extends Thread {
          public void run() ...{
              for (int I = 0; I < 100; I++) {
                  System.out.println("Hello");
              }
          }
      }

      //ch02.OurApplet.java
      import java.applet.Applet;

      public class OurApplet extends Applet {
          public void init() {
              OurClass c = new OurClass();
              oc.start();
          }
      }
       start()方法实际上创建了一个新的线程。这个新的线程,在进行了一些初始化操作后调用run()方法。在run()方法运行结束后,该程序还作了一些与程序终止相关的工作。因而,在新线程中运行的run()方法大概是在start()方法返回到第一个线程的同时开始运行的。

      创建一个线程两个步骤:


      在子类中覆盖run()方法;

      通过构造函数创建子类的一个对象并调用子类的start()方法;

      ==========================================================

      二 使用Runnable接口的线程
      对于一个已经有着详细继承树关系的类而言,如果想让它在自己的线程中运行,就不能如上那样使其从Thread类继承而来。Java中使用接口的机制来解决其不支持多重继承的缺陷。

      实际上,线程化的类实现了Runnable接口。因此,当一个类继承自Thread类时,其子类也同时实现了Runnable接口。

      简单地说,我们可以通过实现Runnable接口来代替从Thread类继承。

      第一步:只需将 extends Thread  替换为 implements Runnable

       

      //ch02.OurRunnableClass.java

      public class OurRunnableClass implements Runnable ...{
          public void run() ...{
              for (int I = 0; I < 100; I++) ...{
                  System.out.println("Hello, from another thread");
              }
          }
      }
      第二步:因为OurRunnableClass不再是Thread对象,不能使用默认的构造函数创建线程。不过可以通过OurRunnableClass对象的引用创建新的线程对象。

       

      //ch02.OurRunnableApplet.java

      import java.applet.Applet;

      public class OurRunnableApplet extends Applet ...{
          public void init() ...{
              Runnable t = new OurRunnableClass();
              Thread th = new Thread(ot);
              th.start();
          }
      }
       为什么会有这样一个构造函数呢?前面曾经提过Thread类的run()方法默认实现是一个空方法。代码如下:

       

      public void run() ...{
                 if ( target != null ) ...{
                            target.run();
                 }
      }
      target其实就是传递给线程的构造函数的可运行对象(实现了Runnable接口的对象)。

      有趣的是,通过使用Runnable接口而不是继承自Thread类的技术,第一步的OurClass类的代码可以和第二步的applet融合在一起了。

       如下所示:

       

      import java.applet.Applet;

      public class OurCompleteApplet extends Applet implements Runnable ...{
          public void init() ...{
              Thread th = new Thread(this);
              th.start();
          }

          public void run() ...{
              for (int I = 0; I < 100; I++) ...{
                  System.out.println("Hello, from another thread");
              }
          }
      }

       

      ===============================================

      改写实例:

      //线程子类
      public class OurClass extends Thread {
          public void run() {
              for (int I = 0; I < 10; I++) {
                  System.out.println("Hello");
              }
          }
      }

      //主体类
      import java.applet.Applet;

      public class OurApplet extends Applet {
         
          //public void init()
         
          public static void main(String[] args)
          {
              OurClass c = new OurClass();
              oc.start();
              OurClass oc2 = new OurClass();
              oc2.start();
          }
      }

      ==============================================================

      Runnable接口的实例化,区别


       

    • java socket 实现服务端与客户端------一对多的服务端和客户机

      2009-04-28 17:16:19

      //一对多的服务端和客户机:一个服务端能同时服务多个客户端,需要使用多线程来实现

      //服务端:调用具体的处理线程完成处理
      package com.socket.multiserver;
      import java.io.*;
      import java.net.*;
      import com.socket.multiserver.ChildTh;

      public class MyMultiServer {
       public static void main(String[] args) throws IOException{
        ServerSocket server=new ServerSocket(5678);
        while (true){
                      Socket client=server.accept();
                      ChildTh child=new ChildTh(client);//用socket实例初始化具体的处理线程对象
                      //使用Runnable接口和使用extends Thread的区别:
                      // 如果是使用Runnable接口,需要这么写:
                         new Thread(child).start();               
                      //注意:不能写成:child.run();
                      // 如果使用extends Thread,只需要child.start()就可以,因为start()是Thread的方法
                      }
              }
      }       

       

      ============================================================

      //处理线程类:
      package com.socket.multiserver;
      import java.io.*;
      import java.net.*;

      public class ChildTh implements Runnable{
              private Socket client;
              public ChildTh(Socket client){
                      this.client=client;
              }
             
              public void run(){       
                 try{       
                   BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
                   PrintWriter ut=new PrintWriter(client.getOutputStream());
                   while(true){
                           String str=in.readLine();
                           System.out.println(str);
                           out.println("has receive....");
                           out.flush();
                           if(str.equals("end"))
                              break;
                   }       
                             
                   client.close();
                  }catch(Exception e){
                        System.out.println("error in the close the socket!");                       
                        e.printStackTrace();
                    }
                    finally{
                                                                     
                    }
              }
             
      }

       

      ===========================================================

      //客户端
      package com.socket.multiserver;
      import java.net.*;
      import java.io.*;

      public class MyMultiClient{
       static Socket client;
       
       public static void main(String[] args)throws Exception{
       
        client=new Socket(InetAddress.getLocalHost(),5678);
       
               BufferedReader in=new BufferedReader(new InputStreamReader(client.getInputStream()));
               PrintWriter ut=new PrintWriter(client.getOutputStream());
              
               //从标准输入接收数据
        BufferedReader wt=new BufferedReader(new InputStreamReader(System.in));
       
        while(true){
                 String str=wt.readLine();
                 //String str = "jonathan";
                 out.println(str);
                 out.flush();
                 if(str.equals("end")){
                          break;
                }
                 System.out.println(in.readLine());
        }
        client.close();
       }
      }

      http://www.360doc.com/showWeb/0/0/174225.aspx

      三个java文件

      编译:javac -d . *.java
      执行:java  包.类名

      implements Runnable :
              Runnable t = new OurRunnableClass();
              Thread th = new Thread(ot);
              th.start();

      java多线程:复写run()方法



    884/5<12345>
    Open Toolbar