发布新日志

  • 学习java web start

    2009-07-08 18:15:02

    Java Web Start(以下简称JWS)是SUN提供的一种通过Web来部署和发布Java 程序的新技术,它既可以用来发布Application,也可以用来发布Applet,它获去年全球Java技术最佳创意奖。它仅在第一次运行时下载程 序,以后的事情,就全全交给JWS,包括版本的自动更新和维护。这是我们曾经梦寐以求的事情,程序运行在客户端(本地运行,当然有足够的速度),但不用去 安装配置客户端,也不用去考虑版本升级后对客户端的维护,这就是JWS提供给我们的好处之一。OK,下面我们就来看看如何玩转JWS,本文仅用发布 Application来做说明。

    系统环境:Win2000Professional+Tomcat3.2.1+JDK1.3。

    JWS简介

    JWS主要用来通过网络部署你的应用程序,它具有安全、稳定、易维护、易使用的特点。用户访问用JWS部署应用程序的站点,下载发布的应用程序,既可以在 线运行,也可以通过JWS的客户端离线运行已下载的应用程序。对同一个应用程序,在第一次运行时下载,以后每次运行时,JWS的客户端会自动去探测是否有 版本更新,有更新就自动下载新版本,没有更新就直接运行本地当前版本,所有的麻烦全由JWS去承担。好,下面我们就一步一步来搭建JWS








    搭建支持JWS的Web站点

    第一步:你的Tomcat3.2.1已经正常运转

    第二步:找到TomcatHOME/conf下的web.xml文件,在其中添加<mime-type>
    application/x-java-jnlp-file
    </mime-type>

    以支持JNLP文件。








    部署应用程序

    第一步:开发你希望发布的应用程序

    第二步:把应用程序及所用到的所有资源打成一个或多个jar包

    第三步:如果你的应用程序不会用到任何运行这个应用程序的机器的本地资源,那么,你的应用程序就可以部署了。

    第四步:如果你的应用程序用到了运行这个应用程序的机器的本地资源,那么,你的应用程序就必须先签名然后才可以发布。

    第五步:如何给应用程序签名

    1:首先确保你已经完全安装了Java2的环境,有keytool工具,它位于J2SE SDk的bin目录下。这一般不会有问题。

    2:到Dos状态下,进入你需发布应用程序的jar包所在的目录,运行下面这句话
    keytool -genkey -keystore myKeystore -alias jwstest

    它将会提示你输入用户名、密码等,不用理它,按照提示随便输入即可,但一定要记住密码。运行结束它将会在当前路径下创建名为myKeystore的文件。

    3:如果你想察看一下刚才生成的myKeystore文件的内容,可以使用下面这句话:
    keytool -list -keystore myKeystore

    显示出来应该类似如下:

    Keystore type: jks
    Keystore provider: SUN
    Your keystore contains 1 entry:
    jwstest, Tue Nov 23 19:29:32 PST 2001, keyEntry,
    Certificate fingerprint (Test):
    C3:A9:CD:F3:D3:AC:4D:3F:3C:5B:AF:9E:CF:0D:46:5C

    4:对你需发布应用程序的jar包进行签名,运行下面这句话:
    jarsigner -keystore myKeystore yourtest.jar jwstest

    其中yourtest.jar是你的jar包名,你需要修改它,别的就不必修改了。运行时会提示你输入密码,就是你刚才在生成myKeystore文件时设定的密码。

    第六步:部署应用程序的jar包。

    1:在Tomcat的webapps中新建目录JWSTest

    2:在JWSTest下新建目录apps,META-INF,WEB-INF

    3:在apps下新建目录images和lib

    4:在META-INF中拷入MANIFEST.MF

    5:在WEB-INF中拷入web.xml

    6:把已经准备好的jar包拷入lib目录下







    Jsp页面

    第一步:编写用于Web访问的页面index.jsp如下:

    <%@page contentType="text/html;charset=gb2312"%>
    <html>
    <title>JWS Test</title>
    <head>
    <SCRIPT. LANGUAGE="Javascript">
    function insertLink(url, name) {
    document.write("<a href=" + url + ">" + name + "</a><br><br>");
    }
    insertLink("http://你的IP:8080/ JWSTest /apps/JWSTest.jnlp"," JWSTest ");
    </SCRIPT>
    </head>
    <body>
    </body>
    </html>

    第二步:在jsp中添加检测访问的客户端是否已经安装了JWS的客户端的代码,示例如下:

    <%@page contentType="text/html;charset=gb2312"%>
    <html>
    <title> JWS Test </title>
    <head>
    <SCRIPT. LANGUAGE="Javascript">
    var javawsInstalled = 0;
    isIE = "false";
    if (navigator.mimeTypes && navigator.mimeTypes.length) {
    x = navigator.mimeTypes['application/x-java-jnlp-file'];
    if (x) javawsInstalled = 1;
    } else {
    isIE = "true";
    }
    function insertLink(url, name) {
    if (javawsInstalled) {
    document.write("<a href=" + url + ">" + name + "</a><br><br>");
    } else {
    document.write("<a href=" + url + ">"+ name +"</a><br><br>");
    }
    }
    </SCRIPT>
    <SCRIPT. LANGUAGE="VBScript">
    on error resume next
    If isIE = "true" Then
    If Not(IsObject(CreateObject("JavaWebStart.IsInstalled"))) Then
    javawsInstalled = 0
    Else
    javawsInstalled = 1
    End If
    End If
    </SCRIPT>
    <SCRIPT. LANGUAGE="Javascript">
    if(javawsInstalled){
    insertLink("http://你的IP:8080/ JWSTest /apps/JWSTest.jnlp"," JWSTest ");
    }else{
    //通知用户要先安装JWS的客户端,你可以自己提供下载或是直接链接到Sun的JWS下载。
    //分为两种,如果客户端已经安装了Java运行环境,则只要下载javaws-1_0_1_01-win-int.exe即可。
    //如果客户端没有安装Java运行环境,则要下载完整的javaws-1_0_1_01-win-int-rt.exe。
    }
    </SCRIPT>
    </head>
    <body>
    </body>
    </html>






    JNLP文件

    第一步:下面我们来编写JWS的核心配置文件JNLP,有了它,才能将以上各部分联系起来,真正让JWS运转起来。JNLP文件符合标准的XML语法,实质就是一个XML文件。当然,编写它的最好方式是对已写好的JNLP进行改写。JWSTest.jnlp示例如下:

    <?xml version="1.0" encoding="utf-8"?>
    <!-- JNLP File for SwingSet2 Demo Application -->
    <jnlp
    spec="1.0+"
    codebase="http://你的IP:8080/JWSTest/apps"
    href=" JWSTest.jnlp">
    <information>
    <title> JWS Test </title>
    <vendor>YOUR Name</vendor>
    <homepage href=" JWSTest.html"/>
    <description> JWS Test </description>
    <icon href="images/ JWSTest.jpg"/>
    <offline-allowed/>
    </information>
    <security>
    <all-permissions/>
    </security>
    <resources>
    <j2se version="1.3"/>
    <jar href="lib/ JWSTest.jar"/>
    </resources>
    <application-desc main-class="运行启动的主类"/>
    </jnlp>

    第二步:部分JNLP的关键语法

    <jnlp>元素
    spec:必须是1.0及以上版本,这里用1.0+,不需修改。
    codebase:资源的URL,是JNLP指向各连接的起始处,需自行修改。
    Href:JNLP文件相对codebase的存放位置,和JNLP文件的全名,需自行修改。

    <infomation>元素

    Title:发布的应用程序简单标题,需自行修改。
    Vendor:发行商信息,可以写上你的大名,需自行修改。
    Homepage:存放有关应用程序的相关文档的URL,如help文件等,可有可无。
    Description:对应用程序的描述,可以有多对<description></description>,可有可无。
    Icon:用户下载你的应用程序后,在JWS里显示的图标的URL,应是gif或jpeg格式。需自行修改。
    Offline-allowed:选择项,允许用户离线运行应用程序,一般都会有,不用修改。

    <security>元素
    选择项,如果没有指明<security>,默认是不允许应用程序访问用户的本地资源,即应用程序是沙箱运行。
    如果设定为<all-permissions/>,则表示允许应用程序访问用户的本地资源。一般都会设定此值。

    <resource>元素
    <j2se version = 指定jdk版本>
    <jar href = 指定需发布的应用程序的jar包存放的位置>
    <application-desc>元素
    main-class:应用程序运行启动的主类

    <argument>:应用程序运行时的参数,可以有多个,每一个参数用一对<argument>参数</argument>。

    至此,你已经完全构建了运转JWS的各部件。






    完整发布和测试

    前面我们已经准备好了需发布的应用程序的jar包,也写好了用来访问的jsp文件和服务器端的核心jnlp文件。

    第一步:在JWSTest下新建目录jsp。把index.jsp拷入jsp目录。

    第二步:把jnlp文件直接拷入apps目录下。

    第三步:在浏览器里输入:http://localhost:8080/JWSTest/jsp/index.jsp 即可访问到jsp页面。页面应出现JWSTest字样。

    第四步:点击JWSTest,连接到apps下的JWSTest.jnlp文件,JWS启动,开始下载你发布的应用程序。

    第五步:下载完毕,直接运行即可。以后,你也可以直接运行JWS客户端里已下载的应用程序。

    不出意外,应恭喜你已经开始享受JWS带来的乐趣了。








    常见问题

    通过上面的讲述,你一定能体会到JWS的易用性。或许事情并没有那么简单,以我的使用经验,还会有许多问题出现,在这里挑几个经常出现的问题,给出相应解决方法,让大家少走弯路,而享受更多的乐趣。

    问题一:JWS不能运行,JNLP文件像普通XML文件一样显示在Browser里

    解决办法:请修改tomcat里,发布程序的路径中的web.xml。

    在其中添加<mime-type>
    application/x-java-jnlp-file
    </mime-type>
    以支持JNLP文件。

    问题二:不能下载资源或下载资源失败

    解决办法:请卸载JWS的客户端,并将注册表里有关JWS的项目都删除,并确保program Files下的Java Web Start目录已被删除,然后,重装JWS。

    问题三:下载资源中有未签名文件

    解决办法:1:确保所有的jar包及其他资源都进行过签名。

    2:确保整个资源中,没有中文的命名。好像签名工具不支持中文命名的文件名,所以未签到名。这可让我郁闷了一下午哦。

    3:察看已经签名的jar包中,meta-inf路径下的jwstest.sf(jwstest是你在进行签名时-alias后的命名)文件,他详细的列出了所有已签名的文件,以分析签名失败的原因。



    参考资料

    详见 http://java.sun.com/products/javawebstart/

    http://java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/contents.html

  • Java Applet与Java Application的区别

    2009-06-25 11:53:25

    在Java语言中,能够独立运行的程序称为Java应用程序(Application)。Java语言还有另外一种程序——Applet程序。Applet程序(也称Java小程序)是运行于各种网页文件中,用于增强网页的人机交互、动画显示、声音播放等功能的程序。

         Java Applet和Java Application在结构方面的主要区别表现在:

         (1)运行方式不同。Java Applet程序不能单独运行,它必须依附于一个用HTML语言编写的网页并嵌入其中,通过与Java兼容的浏览器来控制执行。Java Application是完整的程序,可以独立运行,只要有支持Java的虚拟机,它就可以独立运行而不需要其他文件的支持。

         (2)运行工具不同。运行Java Applet程序的解释器不是独立的软件,而是嵌在浏览器中作为浏览器软件的一部分。Java Application程序被编译以后,用普通的Java解释器就可以使其边解释边执行,而Java Applet必须通过网络浏览器或者Applet观察器才能执行。

         (3)程序结构不同。每个Java Application程序必定含有一个并且只有一个main方法,程序执行时,首先寻找main方法,并以此为入口点开始运行。含有main方法的那个类,常被称为主类,也就是说,Java Application程序都含有一个主类。而Applet程序则没有含main方法的主类,这也正是Applet程序不能独立运行的原因。尽管Applet没有含main方法的主类,但Applet一定有一个从 java.applet.Applet派生的类,它是由Java系统提供的。

         (4)Java Applet程序可以直接利用浏览器或AppletViewer提供的图形用户界面,而Java Application程序则必须另外书写专用代码来营建自己的图形界面。

        (5)受到的限制不同Java Application程序可以设计成能进行各种操作的程序,包括读/写文件的操作,但是 Java Applet 对站点的磁盘文件既不能进行读操作,也不能进行写 操作。然而,由于 Applet的引入,使Web页面具有动态多媒体效果和可交互性能,这使由名为超文本、实为纯文本的HTML语言编写成的Web页面真正具有了超文本功能,不但可以显示文本信息,而且还可以有各种图片效果和动态图形效果,从而使页面显得生动美丽;另外,Applet使Web页面增加了按钮等功能,从而增加了交互性。

         Java Applet和Java Application在执行方面的主要区别表现在:Java Application一般是在本地机上运行,而Java Applet一般放在服务器上,它是根据本地机的请求被下载到本地机,然后才在本地机上运行。

  • keytool用法

    2009-06-23 10:08:44

    http: //java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/keytool.html

    例子:

    keytool -genkey -dname "cn=BeanSoft Studio, u=Java Software, o=BeanSoft Studio, c=China" -alias beansoft -keypass beansoft -storepass beansoft -validity 365 -keystore .\beansoft

    其中:

    CN=commonName
    U=organizationUnit
    O=organizationName
    L=localityName
    S=stateName
    C=country

    ? OU(Organization Unit - 组织单位名称)
    ? O(Organization - 组织名称)
    ? L(Locality - 城市或区域名称)
    ? ST(State - 州或省份名称)
    ? C(Country - 国家名称)

     

  • 如何给jar包进行数字签名

    2009-06-23 09:32:37

    目的:
             为了使Applet或者Java Web Start程序能够访问客户端本地资源,需要对Applet或者JWS程序jar包进行数字签名,之后客户端打开Applet或者JWS程序的时候会提示是否允许该程序访问本地资源,用户如果要用你的程序,当然只能选择OK了。这样你的程序就能按照某种访问权限来访问客户机的本地资源了。

    签名步骤:
             1.将程序打成jar包。
                 这个我就不多说了,用eclipse,netbeans等开发工具很方便就能打包的。

             2.用keytool命令生成.store文件。
                 在任意文件夹下建立一个keytool.bat文件,输入
         
                   keytool -genkey -keystore xxx.keystore -alias xxx -validity 3650

                 保存,双击执行。将在当前目录下生成一个xxx.keystore文件, -alias后接的是别名,-validity后面接的是该证书有效天数,这里3650表示10年。(用这个证书签名的程序10年内有效)。

             3.用jarsigner程序对jar包进行签名。
                新建jarsinger.bat文件,输入

                 jarsigner -keystore xxx.keystore helloworld.jar xxx

                 这样helloworld.jar就被签名了。 

    applet应用程序的数字签名应用实战

       最近在研究applet,打算使用applet来开发一个上传文件上传控件,之前因为一直觉得applet的沙箱控制导致applet不能主动的访问客户端的资源,所以也曾因此而放弃.不过最近在研究applet的签名后,有了点收获,可以通过签名jar文档来达到这样的控制策略,下面是我在实际实验过程中的一些心得和体会,跟大家一起分享下.(注:如果转载此文,请注明出处和作者,尊重作者的劳动成果,谢谢)

    一、压缩你的class类文件为jar包
    1.假设你的需要压缩的类文件存在的包为:cn.mbq.test1和cn.mbq.test2
    2.进入你的classes目录,在DOS窗口中执行命令:jar cf mytest.jar cn.mbq.test1 cn.mbq.test2
    3.执行命令后你会在当前目录中找到mytest.jar文件,这个就是刚才生成的档案文件。你可以修改它的后缀为rar,然后使用winrar压缩程序打开它查看看是否正确。


    二、使用keytool工具生成密匙库
    1.keytool工具位于${java_home}/bin目录下;
    2.在DOS窗口中执行命令:keytool -genkey -keystore mytest.store -alias mbq
      注意:mytest.store 是你的密匙库的名称,可以随意修改,后缀请不要修改!
            mbq 为别名,这个也可以改成自己的名称
    3.执行上述命令后,DOS窗口中会提示你输入keystore的密码、你的姓名、组织单位等等信息。这里要注意的是输入密码请记住,后面要用到的。在最后,我们输入y确认信息。然后再直接回车设置mbq的主密码和store密码一致即可!


    三、使用keytool工具导出签名时用到的证书
    1.在DOS窗口中执行命令:keytool -export -keystore mytest.store -alias mbq -file mbq.cert
      注意:mytest.store 就是第二步生成的密匙库名称
            mbq 也是在第二步中我们指定的别名
            mbq.cert 为我们生成的证书的名称,可以自己修改名称,注意后缀不要改
    2.命令执行成功,我们会在当前目录下找到一个mbq.cert文件,这个就是我们刚才生成的证书。


    四、使用jarsigner工具签名jar压缩文档
    1.jarsigner工具位于${java_home}/bin目录下;
    2.在当前DOS窗口中执行命令:jarsigner -keystore mytest.store mytest.jar mbq
      注意:mytest.store 就是我们在第二步中生成的密匙库名称
            mytest.jar 就是我们这第一步压缩的jar文档
            mbq 是提供者的名称,我们这里设置为我们的别名


    五、创建mytest.policy文件
    1.在当前目录下创建一个mytest.policy文件,其内容如下:
    keystore"file:mytest.store","JKS";
    grantsignedBy"mbq"
    {
    permission java.io.FilePermission"<<ALLFILES>>","read";
    };
    2.这个文件的意思就是说让所有由mbq签名的applet都可以对本地的所有文件进行读操作。


    六、归档文件
        通过上述的五个操作后,我们会在当前目录中找到如下几个文件:mytest.jar-签名后的jar文档、mytest.store-密匙库、mbq.cert-证书、mytest.policy-访问策略文件。如果没有这些文件,那么你的applet数字签名过程就没有正确的完成,请检查上述的操作。以后,如果对打包的java文件做了修改,那么就需要重新签名一次才可以!


    七、在网页中运行applet
    1.假设你的applet中的主启动类为:cn.test.TestApplet.class;整个前面生成的档案文件、证书啊存储在目录:d:\test\myapplet下;
    2.建立一applet_test.html文件存放在任何目录下都可以,然后内容如下:

    Java代码 复制代码
    1. 1 <HTML>...</HTML><HTML>    
    2. 2 <BODY>...</BODY><BODY>    
    3. 3 <APPLET CODEBASE="d:\test\myapplet" CODE="cn.test.TestApplet.class" ARCHIVE="mytest.jar" WIDTH=200 HEIGHT=100 name="myapp">    
    4. 4 </APPLET>    
    5. 5 </BODY>    
    6. 6 </HTML>  



        注意:其中的CODEBASE就是你的类的基础目录,CODE也就是你的APPLET的启动主类,ARCHIVE也就是签名后的JAR文档。
    2.然后在IE中打开该html文件,那么会看到IE提示你是否信任该插件,也就是说我们的证书起作用了,然后确定运行后,就可以在页面上看到applet的运行效果了。

        但是由于SUN和MS的问题,目前IE并不支持最新的JRE,而是使用MS自己开发的JRE,所以这个也是影响APPLET发展壮大的一个原因。而且正是由于这个原因,SUN的java-plugin技术才会出现。使用SUN的java-plugin技术我们就可以在applet中使用最新的JAVA类库了。由于IE在遇到APPLET标签的时候会调用自己的JRE,但是如果客户机器上安装的JRE不是我们想要的版本,那么就会出错了。所谓java-plugin技术就是利用IE的插件机制来制定我们想要的JRE,我们可以在IE中使用OBJECT标签来调用APPLET,这样就不会引用MS的JRE了,从而达到我们想要的效果,而且java-plugin技术不仅仅支持IE,还支持Navigator等浏览器。不过我们需要编写比较复杂的HTML代码了,但是这一且SUN已经帮我们做到了,呵呵,在JDK1.4或更高的版本中SUN提供了一个HtmlConverter.exe工具来帮助将包含applet标签的html转换成包含OBJECT和EMBED标签的html代码,该工具位于${java_home}/bin目录下,对于1.4以前的版本该工具则是单独提供的,不过现在几乎都是1.4或1.5甚至更高版本的JDK了吧,呵呵。

        该工具很简单,是图形化的工具,我们直接运行即可。比如我将上面的包含applet的html转换后(比如我选择只支持IE的),其代码变成了如下:

    Java代码 复制代码
    1. 01 <HTML>...</HTML><HTML>    
    2. 02 <BODY>...</BODY><BODY>    
    3. 03 <!--"CONVERTED_APPLET"-->    
    4. 04 <!-- HTML CONVERTER -->    
    5. 05 <object    
    6. 06     classid = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"    
    7. 07     codebase = "http://java.sun.com/update/1.5.0/jinstall-1_5-windows-i586.cab#Version=5,0,0,3"    
    8. 08     WIDTH = 200 HEIGHT = 100 NAME = "myapp" >    
    9. 09     <PARAM NAME = CODE VALUE = "cn.test.TestApplet.class" >    
    10. 10     <PARAM NAME = CODEBASE VALUE = "d:\test\myapplet" >    
    11. 11     <PARAM NAME = ARCHIVE VALUE = "mytest.jar" >    
    12. 12     <PARAM NAME = NAME VALUE = "myapp" >    
    13. 13     <param name = "type" value = "application/x-java-applet;version=1.5">    
    14. 14     <param name = "scriptable" value = "false">    
    15. 15 </object>    
    16. 16 <!--    
    17. 17 <APPLET CODEBASE="d:\test\myapplet" CODE="cn.test.TestApplet.class" ARCHIVE="mytest.jar"    
    18. 18 WIDTH=200 HEIGHT=100 name="myapp">    
    19. 19 </APPLET>    
    20. 20 -->    
    21. 21 <!--"END_CONVERTED_APPLET"-->    
    22. 22 </BODY>    
    23. 23 </HTML>  



        注意其中的OBJECT标签,可以看到APPLET标签已经被注释掉了。其中PARAM NAME=NAME这一行中的myapp就是我们applet应用程序的名称,在IE提示的确认运行中显示的就是这个名称了,我们可以改为自己的公司或组织的名称。然后提示的提供者也就是我们在签名时用到的名称了。

        另外,还要特别注意的就是这个包含OBJECT标签的html页面必须和你的mytest.jar压缩文档放在同一个目录下,这样才可以正确的加载,否则会一直报ClassNotFound的异常的,即使我们在OBJECT标签中指定了CODEBASE也不行,这个是我在测试的时候遇到的问题!


    八、在Internet上应用签名的applet
        如果要把applet部署在网络上,那么最好是采用OBJECT标签的形式,同时也要兼顾采用EMBED标签来支持诸如FF等浏览器。我们把已签名了的mytest.jar和我们的网页放在同一个目录下,至于其他的如mytest.store和mbq.cert可以不用放在一起,至少我在测试的过程中没有放到一起也不会出错,而且在不同的机器上运行的也非常好,可以读取客户端机器的资源!另外,也发现mytest.policy其实也没什么用处,因为这是参考网络上的,而且他们的版本都是1.3左右,所以估计是版本低的缘故吧!


        到此,我们就已经完成了applet的签名到部署,以及到实际的网络应用中了。这样我们使用applet来开发控件时就不会因为无法读取客户端资源而放弃了,呵呵~~

  • jdk下载网站

    2009-06-16 17:32:41

    各种操作系统下的jdk下载地址:

    http://developers.sun.com.cn/download/java_se.html

    sun的中文官方网站是:

    http://developers.sun.com.cn/

    有关java的一些资源可以从这个官方网站找到的。
  • java入门系列视频

    2009-06-15 11:52:14

    Java入门培训系列 - 1
    本集是第一讲,介绍Java开发环境JDK的安装配置,以及第一个简单的Hello程序的编写、编译和运行,希望大家喜欢!
    =====================================
    在线观看: http://www.boobooke.com/v/bbk2667
    =====================================


    Java入门培训系列 - 2
    本集是第2讲,介绍J2SE面向对象编程,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2693
    =======================================


    Java入门培训系列 - 3
    本集是第3讲,继续介绍J2SE面向对象编程,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2703
    =======================================


    Java入门培训系列 - 4
    本集是第4讲,继续介绍J2SE面向对象编程,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2704
    =======================================


    Java入门培训系列 - 5
    本集是第5讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2731
    =======================================


    Java入门培训系列 - 6
    本集是第6讲,介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2770
    =======================================


    Java入门培训系列 - 7
    本集是第7讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2771
    =======================================


    Java入门培训系列 - 8
    本集是第8讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2782
    =======================================


    Java入门培训系列 - 9
    本集是第9讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2783
    =======================================


    Java入门培训系列 - 10
    本集是第10讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2846
    =======================================


    Java入门培训系列 - 11
    本集是第11讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2847
    =======================================


    Java入门培训系列 - 12
    本集是第12讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2848
    =======================================


    Java入门培训系列 - 13
    本集是第13讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2849
    =======================================


    Java入门培训系列 - 14
    本集是第14讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2855
    =======================================


    Java入门培训系列 - 15
    本集是第15讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2857
    =======================================


    Java入门培训系列 - 16
    本集是第16讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2858
    =======================================


    Java入门培训系列 - 17
    本集是第17讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2859
    =======================================


    Java入门培训系列 - 18
    本集是第18讲,继续介绍J2SE基本语法,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2879
    =======================================


    Java入门培训系列 - 19
    本集是第19讲,介绍J2SE流程控制,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2891
    =======================================


    Java入门培训系列 - 20
    本集是第20讲,继续介绍J2SE流程控制,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2892
    =======================================

    Java入门培训系列 - 21
    本集是第21讲,介绍J2SE中的数组,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2916
    =======================================


    Java入门培训系列 - 22
    本集是第22讲,介绍Uavase数组,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2920
    =======================================


    Java入门培训系列 - 23
    本集是第23讲,介绍Uavase数组,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2921
    =======================================

    Java入门培训系列 - 24
    本集是第24讲,介绍Java中的继承,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2927
    =======================================


    Java入门培训系列 - 25
    本集是第25讲,继续介绍Java中的继承,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2928
    =======================================


    Java入门培训系列 - 26
    本集是第26讲,继续介绍Java中的继承,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk2929
    =======================================


    Java入门培训系列 - 27
    本集是第27讲,介绍Java中的方法重载,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk3001
    =======================================

    Java入门培训系列 - 28
    本集是第28讲,介绍Java中的Static与Final,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk3002
    =======================================



    Java入门培训系列 - 29
    本集是第29讲,介绍Java中的Single ,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk3003
    =======================================


    Java入门培训系列 - 30
    本集是第30讲,介绍Java中的枚举  ,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk3048
    =======================================


    Java入门培训系列 - 31
    本集是第31讲,介绍Java中的抽象类 ,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk3049
    =======================================


    Java入门培训系列 - 32
    本集是第32讲,介绍Java中的接口  ,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk3070
    =======================================


    Java入门培训系列 - 33
    本集是第33讲,介绍Java中的异常,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk3057
    =======================================


    Java入门培训系列 - 34
    本集是第34讲,继续介绍Java中的异常,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk3058
    =======================================


    Java入门培训系列 - 35
    这是小生老师的Java系列培训视频,本集是第35讲,介绍Java中的Object,希望大家喜欢!
    =======================================
    在线观看: http://www.boobooke.com/v/bbk3093
    =======================================



  • java exception

    2009-06-12 15:10:11

    关于异常处理的一个问题就是要对何时(when)和如何(how)使用它们做到了然于心。在本文中我将介绍一些关于异常处理的最佳实践,同时我也会涉及到最近争论十分激烈的checked Exception的使用问题。

    作为开发员,我们都希望能写出解决问题并且是高质量的代码。不幸的是,一些副作用(side effects)伴随着异常在我们的代码中慢慢滋生。无庸置疑,没有人喜欢副作用(side effects),所以我们很快就用我们自己的方式来避免它,我曾经看到一些聪明的程序员用下面的方式来处理异常:

    public void consumeAndForgetAllExceptions(){
    try {
    ...some code that throws exceptions
    } catch (Exception ex){
    ex.printStacktrace();
    }
    }

    上边的代码有什么问题么?

    在回答以前让我们想想怎样才是正确的?是的,一旦程序碰到异常,它就该挂起程序而"做"点什么。那么上边的代码是这样子的么?看吧,它隐瞒了什么?它把所有的"苦水"往肚里咽(在控制台打印出异常信息),然后一切继续,从表面上看就像什么都没有发生过一样......,很显然,上边代码达到的效果并不是我们所期望的。

    后来又怎样?

    public void someMethod() throws Exception{
    }

    上边的代码又有什么问题?

    很明显,上边的方法体是空的,它不实现任何的功能(没有一句代码),试问一个空方法体能抛出什么异常?当然Java并不阻止你这么干。最近,我也遇到类似的情景,方法声明会抛出异常,但是代码中并没有任何"机会"来"展示"异常。当我问开发员为什么要这样做的时候,他回答我说"我知道,它确实有点那个,但我以前就是这么干的并且它确实能为我工作。"

    在C++社区曾经花了数年实践来实践如何使用异常,关于此类的争论在 java社区才刚刚开始。我曾经看到许多Java程序员针对使用异常的问题进行争论。如果对于异常处理不当的话,异常可以大大减慢应用程序的执行速度,因为它将消耗内存和CPU来创建、抛出并捕获异常。如果过分的依赖异常处理,代码对易读和易使用这两方面产生影响,以至于会让我们写出上边两处"糟糕"代码。

    异常原理

    大体上说,有三种不同的"情景"会导致异常的抛出:

    l 编程错误导致异常(Exception due Programming errors): 这种情景下,异常往往处于编程错误(如:NullPointerException 或者 IllegalArgumentException),这时异常一旦抛出,客户端将变得无能为力。

    l 客户端代码错误导致异常(Exception due client code errors): 说白点就是客户端试图调用API不允许的操作。

    l 资源失败导致异常(Exception due to resource failures): 如内存不足或网络连接失败导致出现异常等。这些异常的出现客户端可以采取相应的措施来恢复应用程序的继续运行。

    Java中异常的类型

    Java 中定义了两类异常:

    l Checked exception: 这类异常都是Exception的子类

    l Unchecked exception: 这类异常都是RuntimeException的子类,虽然RuntimeException同样也是Exception的子类,但是它们是特殊的,它们不能通过client code来试图解决,所以称为Unchecked exception

    举个例子,下图为NullPointerException的继承关系:

     

    图中,NullPointerException继承自RuntimeException,所以它是Unchecked exception.

    以往我都是应用checked exception多于Unchecked exception,最近,在java社区激起了一场关于checked exception和使用它们的价值的争论。这场争论起源于JAVA是第一个拥有Checked exception的主流OO语言这样一个事实,而C++和C#都是根本没有Checked exception,它们所有的异常都是unchecked。

    一个checked exception强迫它的客户端可以抛出并捕获它,一旦客户端不能有效地处理这些被抛出的异常就会给程序的执行带来不期望的负担。
    Checked exception还可能带来封装泄漏,看下面的代码:

    public List getAllAccounts() throws
    FileNotFoundException, SQLException{
    ...
    }

    上边的方法抛出两个异常。客户端必须显示的对这两种异常进行捕获和处理即使是在完全不知道这种异常到底是因为文件还是数据库操作引起的情况下。因此,此时的异常处理将导致一种方法和调用之间不合适的耦合。



    接下来我会给出几种设计异常的最佳实践 (Best Practises for Designing the API)

    1. 当要决定是采用checked exception还是Unchecked exception的时候,你要问自己一个问题,"如果这种异常一旦抛出,客户端会做怎样的补救?"
    如果客户端可以通过其他的方法恢复异常,那么这种异常就是checked exception;如果客户端对出现的这种异常无能为力,那么这种异常就是Unchecked exception;从使用上讲,当异常出现的时候要做一些试图恢复它的动作而不要仅仅的打印它的信息,总来的来说,看下表:

    Client's reaction when exception happens
    Exception type

    Client code cannot do anything
    Make it an unchecked exception

    Client code will take some useful recovery action based on information in exception
    Make it a checked exception


    此外,尽量使用unchecked exception来处理编程错误:因为unchecked exception不用使客户端代码显示的处理它们,它们自己会在出现的地方挂起程序并打印出异常信息。Java API中提供了丰富的unchecked excetpion,譬如:NullPointerException , IllegalArgumentException 和 IllegalStateException等,因此我一般使用这些标准的异常类而不愿亲自创建新的异常类,这样使我的代码易于理解并避免的过多的消耗内存。

    2. 保护封装性(Preserve encapsulation)

    不要让你要抛出的checked exception升级到较高的层次。例如,不要让SQLException延伸到业务层。业务层并不需要(不关心?)SQLException。你有两种方法来解决这种问题:

    l 转变SQLException为另外一个checked exception,如果客户端并不需要恢复这种异常的话;

    l 转变SQLException为一个unchecked exception,如果客户端对这种异常无能为力的话;

    多数情况下,客户端代码都是对SQLException无能为力的,因此你要毫不犹豫的把它转变为一个unchecked exception,看看下边的代码:
    public void dataAccessCode(){
    try{
    ..some code that throws SQLException
    }catch(SQLException ex){
    ex.printStacktrace();
    }
    }


    上边的catch块紧紧打印异常信息而没有任何的直接操作,这是情有可原的,因为对于SQLException你还奢望客户端做些什么呢?(但是显然这种就象什么事情都没发生一样的做法是不可取的)那么有没有另外一种更加可行的方法呢?

    public void dataAccessCode(){
    try{
    ..some code that throws SQLException
    }catch(SQLException ex){
    throw new RuntimeException(ex);
    }
    }

    上边的做法是把SQLException转换为RuntimeException,一旦SQLException被抛出,那么程序将抛出RuntimeException,此时程序被挂起并返回客户端异常信息。

    如果你有足够的信心恢复它当SQLException被抛出的时候,那么你也可以把它转换为一个有意义的checked exception, 但是我发现在大多时候抛出RuntimeException已经足够用了。

    3. 不要创建没有意义的异常(Try not to create new custom exceptions if they do not have useful information for client code.)

    看看下面的代码有什么问题?

    public class DuplicateUsernameException
    extends Exception {}


    它除了有一个"意义明确"的名字以外没有任何有用的信息了。不要忘记Exception跟其他的Java类一样,客户端可以调用其中的方法来得到更多的信息。

    我们可以为其添加一些必要的方法,如下:

    public class DuplicateUsernameException
    extends Exception {
    public DuplicateUsernameException 
    (String username){....}
    public String requestedUsername(){...}
    public String[] availableNames(){...}
    }



    在新的代码中有两个有用的方法:reqeuestedUsername(),客户但可以通过它得到请求的名称;availableNames(),客户端可以通过它得到一组有用的usernames。这样客户端在得到其返回的信息来明确自己的操作失败的原因。但是如果你不想添加更多的信息,那么你可以抛出一个标准的Exception:

    throw new Exception("Username already taken");
    更甚的情况,如果你认为客户端并不想用过多的操作而仅仅想看到异常信息,你可以抛出一个unchecked exception:

    throw new RuntimeException("Username already taken");

    另外,你可以提供一个方法来验证该username是否被占用。

    很有必要再重申一下,checked exception应该让客户端从中得到丰富的信息。要想让你的代码更加易读,请倾向于用unchecked excetpion来处理程序中的错误(Prefer unchecked exceptions for all programmatic errors)。

    4. Document exceptions.

    你可以通过Javadoc's @throws 标签来说明(document)你的API中要抛出checked exception或者unchecked exception。然而,我更倾向于使用来单元测试来说明(document)异常。不管你采用哪中方式,你要让客户端代码知道你的API中所要抛出的异常。这里有一个用单元测试来测试IndexOutOfBoundsException的例子:

    public void testIndexOutOfBoundsException() {
    ArrayList blankList = new ArrayList();
    try {
    blankList.get(10);
    fail("Should raise an IndexOutOfBoundsException");
    } catch (IndexOutOfBoundsException success) {}
    }



    上边的代码在请求blankList.get(10)的时候会抛出IndexOutOfBoundsException,如果没有被抛出,将fail ("Should raise an IndexOutOfBoundsException")显示说明该测试失败。通过书写测试异常的单元测试,你不但可以看到异常是怎样的工作的,而且你可以让你的代码变得越来越健壮。


    下面作者将介绍界中使用异常的最佳实践(Best Practices for Using Exceptions)
    1. 总是要做一些清理工作(Always clean up after yourself)

    如果你使用一些资源例如数据库连接或者网络连接,请记住要做一些清理工作(如关闭数据库连接或者网络连接),如果你的API抛出Unchecked exception,那么你要用try-finally来做必要的清理工作:

    java 代码
    1. public   void  dataAccessCode(){   
    2. Connection conn =  null ;   
    3. try {   
    4. conn = getConnection();   
    5. ..some code that  throws  SQLException   
    6. } catch (SQLException ex){   
    7. ex.printStacktrace();   
    8.  finally {   
    9. DBUtil.closeConnection(conn);   
    10. }   
    11. }   
    12.   
    13. class  DBUtil{   
    14. public   static   void  closeConnection   
    15. (Connection conn){   
    16. try {   
    17. conn.close();   
    18.  catch (SQLException ex){   
    19. logger.error( "Cannot close connection" );   
    20. throw   new  RuntimeException(ex);   
    21. }   
    22. }   
    23. }   

    DBUtil是一个工具类来关闭Connection.有必要的说的使用的finally的重要性是不管程序是否碰到异常,它都会被执行。在上边的例子中,finally中关闭连接,如果在关闭连接的时候出现错误就抛出RuntimeException.



    2. 不要使用异常来控制流程(Never use exceptions for flow control)

    下边代码中,MaximumCountReachedException被用于控制流程:

    java 代码
    1. public   void  useExceptionsForFlowControl() {   
    2. try  {   
    3. while  ( true ) {   
    4. increaseCount();   
    5. }   
    6.  catch  (MaximumCountReachedException ex) {   
    7. }   
    8. //Continue execution   
    9. }   
    10.   
    11. public   void  increaseCount()   
    12. throws  MaximumCountReachedException {   
    13. if  (count >=  5000 )   
    14. throw   new  MaximumCountReachedException();   
    15. }    

    上边的useExceptionsForFlowControl()用一个无限循环来增加count直到抛出异常,这种做法并没有说让代码不易读,但是它是程序执行效率降低。

    记住,只在要会抛出异常的地方进行异常处理。



    3. 不要忽略异常

    当有异常被抛出的时候,如果你不想恢复它,那么你要毫不犹豫的将其转换为unchecked exception,而不是用一个空的catch块或者什么也不做来忽略它,以至于从表面来看象是什么也没有发生一样。



    4. 不要捕获顶层的Exception

    unchecked exception都是RuntimeException的子类,RuntimeException又继承Exception,因此,如果单纯的捕获Exception,那么你同样也捕获了RuntimeException,如下代码:

    try{
    ..
    }catch(Exception ex){
    }
    一旦你写出了上边的代码(注意catch块是空的),它将忽略所有的异常,包括unchecked exception.

    5. Log exceptions just once

    Logging the same exception stack trace more than once can confuse the programmer examining the stack trace about the original source of exception. So just log it once.

  • java exception

    2009-06-12 14:50:02

    本文重在Java中异常机制的一些概念。写本文的目的在于方便我很长时间后若是忘了这些东西可以通过这片文章迅速回忆起来。 
    1. 异常机制
    1.1
    异常机制是指当程序出现错误后,程序如何处理。具体来说,异常机制提供了程序退出的安全通道。当出现错误后,程序执行的流程发生改变,程序的控制权转移到异常处理器。
    1.2
    传统的处理异常的办法是,函数返回一个特殊的结果来表示出现异常(通常这个特殊结果是大家约定俗称的),调用该函数的程序负责检查并分析函数返回的结果。这样做有如下的弊端:例如函数返回-1代表出现异常,但是如果函数确实要返回-1这个正确的值时就会出现混淆;可读性降低,将程序代码与处理异常的代码混爹在一起;由调用函数的程序来分析错误,这就要求客户程序员对库函数有很深的了解。
    1.3 异常处理的流程
    1.3.1 遇到错误,方法立即结束,并不返回一个值;同时,抛出一个异常对象
    1.3.2 调用该方法的程序也不会继续执行下去,而是搜索一个可以处理该异常的异常处理器,并执行其中的代码

    2 异常的分类
    2.1 异常的分类
    2.1.1
    异常的继承结构:基类为Throwable,Error和Exception继承Throwable,RuntimeException和IOException等继承Exception,具体的RuntimeException继承RuntimeException。
    2.1.2
    Error和RuntimeException及其子类成为未检查异常(unchecked),其它异常成为已检查异常(checked)。
    2.2 每个类型的异常的特点
    2.2.1 Error体系
    Error类体系描述了Java运行系统中的内部错误以及资源耗尽的情形。应用程序不应该抛出这种类型的对象(一般是由虚拟机抛出)。如果出现这种错误,除了尽力使程序安全退出外,在其他方面是无能为力的。所以,在进行程序设计时,应该更关注Exception体系。
    2.2.2 Exception体系
    Exception体系包括RuntimeException体系和其他非RuntimeException的体系
    2.2.2.1 RuntimeException
    RuntimeException体系包括错误的类型转换、数组越界访问和试图访问空指针等等。处理RuntimeException的原则是:如果出现RuntimeException,那么一定是程序员的错误。例如,可以通过检查数组下标和数组边界来避免数组越界访问异常。
    2.2.2.2 其他(IOException等等)
    这类异常一般是外部错误,例如试图从文件尾后读取数据等,这并不是程序本身的错误,而是在应用环境中出现的外部错误。
    2.3 与C++异常分类的不同
    2.3.1
    其实,Java中RuntimeException这个类名起的并不恰当,因为任何异常都是运行时出现的。(在编译时出现的错误并不是异常,换句话说,异常就是为了解决程序运行时出现的的错误)。
    2.3.2
    C++中logic_error与Java中的RuntimeException是等价的,而runtime_error与Java中非RuntimeException类型的异常是等价的。
    3 异常的使用方法

    3.1 声明方法抛出异常
    3.1.1 语法:throws(略)
    3.1.2 为什么要声明方法抛出异常?
    方法是否抛出异常与方法返回值的类型一样重要。假设方法抛出异常确没有声明该方法将抛出异常,那么客户程序员可以调用这个方法而且不用编写处理异常的代码。那么,一旦出现异常,那么这个异常就没有合适的异常控制器来解决。
    3.1.3 为什么抛出的异常一定是已检查异常?
    RuntimeException与Error可以在任何代码中产生,它们不需要由程序员显示的抛出,一旦出现错误,那么相应的异常会被自动抛出。而已检查异常是由程序员抛出的,这分为两种情况:客户程序员调用会抛出异常的库函数(库函数的异常由库程序员抛出);客户程序员自己使用throw语句抛出异常。遇到Error,程序员一般是无能为力的;遇到RuntimeException,那么一定是程序存在逻辑错误,要对程序进行修改(相当于调试的一种方法);只有已检查异常才是程序员所关心的,程序应该且仅应该抛出或处理已检查异常。
    3.1.4
    注意:覆盖父类某方法的子类方法不能抛出比父类方法更多的异常,所以,有时设计父类的方法时会声明抛出异常,但实际的实现方法的代码却并不抛出异常,这样做的目的就是为了方便子类方法覆盖父类方法时可以抛出异常。
    3.2 如何抛出异常
    3.2.1 语法:throw(略)
    3.2.2 抛出什么异常?
    对于一个异常对象,真正有用的信息时异常的对象类型,而异常对象本身毫无意义。比如一个异常对象的类型是ClassCastException,那么这个类名就是唯一有用的信息。所以,在选择抛出什么异常时,最关键的就是选择异常的类名能够明确说明异常情况的类。
    3.2.3
    异常对象通常有两种构造函数:一种是无参数的构造函数;另一种是带一个字符串的构造函数,这个字符串将作为这个异常对象除了类型名以外的额外说明。
    3.2.4
    创建自己的异常:当Java内置的异常都不能明确的说明异常情况的时候,需要创建自己的异常。需要注意的是,唯一有用的就是类型名这个信息,所以不要在异常类的设计上花费精力。
    3.3 捕获异常
    如果一个异常没有被处理,那么,对于一个非图形界面的程序而言,该程序会被中止并输出异常信息;对于一个图形界面程序,也会输出异常的信息,但是程序并不中止,而是返回用Ы缑娲硌分小?BR> 3.3.1 语法:try、catch和finally(略)
    控制器模块必须紧接在try块后面。若掷出一个异常,异常控制机制会搜寻参数与异常类型相符的第一个控制器随后它会进入那个catch
    从句,并认为异常已得到控制。一旦catch 从句结束对控制器的搜索也会停止。
    3.3.1.1 捕获多个异常(注意语法与捕获的顺序)(略)
    3.3.1.2 finally的用法与异常处理流程(略)
    3.3.2 异常处理做什么?
    对于Java来说,由于有了垃圾收集,所以异常处理并不需要回收内存。但是依然有一些资源需要程序员来收集,比如文件、网络连接和图片等资源。
    3.3.3 应该声明方法抛出异常还是在方法中捕获异常?
    原则:捕捉并处理哪些知道如何处理的异常,而传递哪些不知道如何处理的异常
    3.3.4 再次抛出异常
    3.3.4.1 为什么要再次抛出异常?
    在本级中,只能处理一部分内容,有些处理需要在更高一级的环境中完成,所以应该再次抛出异常。这样可以使每级的异常处理器处理它能够处理的异常。
    3.3.4.2 异常处理流程
    对应与同一try块的catch块将被忽略,抛出的异常将进入更高的一级。
    4 关于异常的其他问题
    4.1 过度使用异常
    首先,使用异常很方便,所以程序员一般不再愿意编写处理错误的代码,而仅仅是简简单单的抛出一个异常。这样做是不对的,对于完全已知的错误,应该编写处理这种错误的代码,增加程序的鲁棒性。另外,异常机制的效率很差。
    4.2 将异常与普通错误区分开
    对于普通的完全一致的错误,应该编写处理这种错误的代码,增加程序的鲁棒性。只有外部的不能确定和预知的运行时错误才需要使用异常。
    4.3 异常对象中包含的信息
    一般情况下,异常对象唯一有用的信息就是类型信息。但使用异常带字符串的构造函数时,这个字符串还可以作为额外的信息。调用异常对象的getMessage()、toString()或者printStackTrace()方法可以分别得到异常对象的额外信息、类名和调用堆栈的信息。并且后一种包含的信息是前一种的超集。
  • java开发为什么要配置JDK及Tomcat的环境变量?

    2009-06-10 17:48:34

    我不是说如何配置环境变量,我要说的是配置环境变量的原因.
    大家有没有这样的发现,如果不配置JAVA_HOME运行Tomcat会出错,但Tomcat环境变量不配置却可以,为什么还有好多网友说要配置Tomcat环境变量呢? 

    先说不配置tomcat的环境变量为什么tomcat可以运行吧
    
    用记事本打开tomcat/bin目录下面的startup.bat
    
    在文本的前一部分有下面的脚本代码
    rem Guess CATALINA_HOME if not defined
    set CURRENT_DIR=%cd%
    if not "%CATALINA_HOME%" == "" goto gotHome
    set CATALINA_HOME=%CURRENT_DIR%
    ........
    
    
    其中的
    set XXXXXXXX=******
    就是增加一个临时的环境变量.只对当前的进程起作用的
    
    %cd%是windows控制台程序自带的一个变量.指这个脚本所在的那个目录的路径
    
    
    set CATALINA_HOME=%CURRENT_DIR%
    自然就是设置一个临时的环境变量CATALINA_HOME...这个就是一些教程里边所要配置的环境变量啦...以前版本的tomcat是要配置的..但是比较新版本的现在都不用了...4.0以后吧..
    如果某些项目或工具有要求配置tomcat环境变量,就是TOMECAT_HOME=tomcat的路径。tomcat通过这个参数找到对应的JDK进行操作。
    再来一个就是jdk的JAVA_HOME了
    ...其实也是相类似的
    windows版本的jdk安装以后会将安装的路径写入系统的注册表里边的...很多程序不用配置JAVA_HOME是因为那些程序是直接通过读取注册表里边的路径获取了jdk的路径.比如eclipse;  netbeans则是在安装的时候,安装程序会去注册表里边读取jdk的路径,直接把它写到netbeans的配置文件里边去了
    而tomcat就没有这样去处理,只是简单地通过环境变量去获取jdk的路径,所以要运行tomcat一般都是要配置环境变量的..如果不配置也可以,修改tomcat/bin/startup.bat...tomcat这样做也是出于跨平台考虑的...因为系统注册表是只有windows系统才有的 
  • Tomcat,Java,apache,jdk是什么?之间的关系是?

    2009-06-10 16:45:28

    JAVA是一门面向对象的编程语言,分为j2se,j2ee,j2me三种平台.其中j2ee中包含jsp和servlet.
    jdk是JAVA的编译器,写java代码时需要使用jdk进行编译运行
    tomcat是一种WEB服务器.是jsp和servlet的运行时的WEB容器.
    apache是一种最流行的HTTP服务器,与tomcat属于统一机构出产.如果想要apache支持jsp和servlet需要将tomcat和apathe集成. 
  • Java的工作原理

    2009-06-09 14:19:31

    Java语言引入了Java虚拟机,具有跨平台运行的功能,能够很好地适应各种Web应用。同时,为了提高Java语言的性能和健壮性,还引入了如垃圾回收机制等新功能,通过这些改进让Java具有其独特的工作原理。

    Java虚拟机(Java Virtual Machine,JVM)是软件模拟的计算机,它可以在任何处理器上(无论是在计算机中还是在其他电子设备中)安全兼容地执行保存在.class文件中的字节码。Java虚拟机的“机器码”保存在.class文件中,有时也可以称之为字节码文件。

    Java程序的跨平台特性主要是指字节码文件可以在任何具有Java虚拟机的计算机或者电子设备上运行,Java虚拟机中的Java解释器负责将字节码文件解释成为特定的机器码进行运行。因此在运行时,Java源程序需要通过编译器编译成为.class文件。

    Java虚拟机的建立需要针对不同的软硬件平台来实现,既要考虑处理器的型号,也要考虑操作系统的种类。由此在SPARC结构、X86结构、MIPS和PPC等嵌入式处理芯片上,在UNIX、Linux、Windows和部分实时操作系统上都可实现Java虚拟机。

    在程序的执行过程中,部分内存在使用过后就处于废弃状态,如果不及时进行回收,很有可能会导致内存泄漏,进而引发系统崩溃。在Java运行环境中,始终存在着一个系统级的线程,专门跟踪内存的使用情况,定期检测出不再使用的内存,并自动进行回收,避免了内存的泄露,也减轻了程序员的工作量。

    Java语言通过Applet程序来控制非法程序的安全性,Java编程语言的出现使得客户端计算机可以方便地从网络上上传或下载Java程序到本地计算机上运行,为保证保证该Java程序不携带病毒或者没有其他危险目的,Java提供了代码安全性检查机制 。Java字节码的执行需要经过以下3个步骤:

    (1)由类装载器(class loader)负责把类文件(.class文件)加载到Java虚拟机中。在此过程需要检验该类文件是否符合类文件规范。

    (2)字节码校验器(bytecode verifier)检查该类文件的代码中是否存在着某些非法操作,例如Applet程序中写本地计算机文件系统的操作。

    (3)如果字节码校验器检验通过,由Java解释器负责把该类文件解释成为机器码进行执行。

    Java虚拟机采用“沙箱”运行模式,即把Java程序的代码和数据都限制在一定内存空间里执行,不允许程序访问该内存空间以外的内存。如果是Applet程序,还不允许访问客户端机器的文件系统。

    JVM是Java平台的核心,为了让编译产生的字节码能更好地解释与执行,因此把JVM分成了6个部分:JVM解释器、指令系统、寄存器、栈、存储区和碎片回收区。

    ◆JVM解释器:即这个虚拟机处理字段码的CPU。

    ◆JVM指令系统:该系统与计算机很相似,一条指令由操作码和操作数两部分组成。操作码为8位二进制数,主要是为了说明一条指令的功能,操作数可以根据需要而定,JVM有多达256种不同的操作指令。

    ◆寄存器:JVM有自己的虚拟寄存器,这样就可以快速地与JVM的解释器进行数据交换。为了功能的需要,JVM设置了4个常用的32位寄存器:pc(程序计数器)、optop(操作数栈顶指针)、frame(当前执行环境指针)和vars(指向当前执行环境中第一个局部变量的指针)。

    ◆JVM栈:指令执行时数据和信息存储的场所和控制中心,它提供给JVM解释器运算所需要的信息。

    ◆存储区:JVM存储区用于存储编译过后的字节码等信息。

    ◆碎片回收区:JVM碎片回收是指将使用过的Java类的具体实例从内存进行回收,这就使得开发人员免去了自己编程控制内存的麻烦和危险。随着JVM的不断升级,其碎片回收的技术和算法也更加合理。JVM 1.4.1版后产生了一种叫分代收集技术,简单来说就是利用对象在程序中生存的时间划分成代,以此为标准进行碎片回收。

    Java Application Programming Interface简称Java API,其中文名为Java应用程序设计接口。它是一个软件集合,其中有许多开发时所需要的控件,可以用它来辅助开发。

    Java API和JVM构成了Java运行的基本环境,这两种软件整合在一起处于计算机之上,通过这两种软件,Java平台把一个Java应用程序从硬件系统分离开,从而很好地保证了程序的独立性。为了更好地适应开发的需要,Java的设计者们提供了3种版本的Java平台:Java 2 Micro Edition (J2ME )、Java 2 Standard Edition(J2SE)和 Java 2 Enterprise Edition (J2EE),每一种版本都提供了丰富的开发工具以适应不同的开发需要。

    Java发展到现在,按应用来分主要分为三大块:J2SE,J2MEJ2EE,这也就是Sun   ONE(Open   Net   Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EEJava2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。J2SE开发桌面应用软件比起VC,VB,DEPHI这些传统开发语言来说,优势好象并不明显。J2ME对于初学者来说,好象又有点深奥,而且一般开发者很难有开发环境。所以现在应用最广泛又最好学的就是J2EE了。J2EE又包括许多组件,如Jsp,Servlet,JavaBean,EJB,JDBC,JavaMail等。

  • JDK安装完成之后设置环境变量

    2009-06-03 16:57:34

    JDK安装完成之后我们来设置环境变量:

    我的电脑点右键,选择“属性”,选择“高级”标签,进入环境变量设置,分别设置如下三个环境变量:
    (1)设置好path变量,使得我们能够在系统中的任何地方运行java应用程序,比如javac、java、javah等等这就要找到我们安装JDK的目录,比如我们的JDK安装在C:\jdk1.6.0目录下那么在C:\jdk1.6.0\bin目录下就是我们常用的java应用程序我们就需要把C:\jdk1.6.0\bin这个目录加到path环境变量里面。

    在系统变量里找到path变量选择->编辑;(里面已经有很多的变量值是在变量值的最前面加上C:\jdk1.6.0\bin)
    变量名: path
    变量值: C:\jdk1.6.0\bin


    (2)classpath环境变量,是当我们在开发java程序时需要引用别人写好的类时,要让java解释器知道到哪里去找这个类。通常,sun为我们提供了一些额外的丰富的类包,一个是dt.jar,一个是tools.jar,这两个jar包都位于C:\jdk1.6.0\lib目录下,所以通常我们都会把这两个jar包加到我们的classpath环境变量中set classpath=.;C:\jdk1.6.0\lib\tools.jar;C:\jdk1.6.0\lib\dt.jar。

    在系统环境变量那一栏中点->新建classpath
    变量名: classpath
    变量值: .;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar(注意,CLASSPATH最前面是有个“.”的,表示当前目录,这样当我们运行java AClass的时候,系统就会先在当前目录寻找AClass文件了。);

    (3)设置JAVA_HOME:

    一是为了方便引用,比如,JDK安装在C:\jdk1.6.0目录里,则设置JAVA_HOME为该目录路径 那么以后要使用这个路径的时候 只需输入JAVA_HOME即可 避免每次引用都输入很长的路径串

    二则是归一原则 当JDK路径改变的时候 仅需更改JAVA_HOME的变量值即可 否则就要更改任何用绝对路径引用JDK目录的文档 要是万一没有改全 某个程序找不到JDK 后果是可想而知的系统崩溃!

    三则是第三方软件会引用约定好的JAVA_HOME变量 不然 你不能正常使用该软件.

    在系统环境变量那一栏中点->新建JAVA_HOME (JAVA_HOME指向的是JDK的安装路径)
    变量名: JAVA_HOME
    变量值: C:\jdk1.6.0

    配置完成下面写一个简单的java程式来测试J2SDK是否已安装成功:

    public class HelloWorld{

    public static void main(String[] args){

    ystem.out.println("Hello world!")

    }

    }


    将程式保存为文档名为HelloWorld.java的文档。

    打开命令提示符窗口,进入到HelloWorld.java所在目录,键入下面的命令

    javac HelloWorld.java

    java HelloWorld

    此时若打印出来HelloWorld则安装成功,若没有打印出这句话,仔细检查以上配置是否正确。

    环境变量配置成功后你就可以着手学习java了
  • Java异常处理的特殊情况

    2009-05-21 15:21:45

    1、不能在finally块中执行return,continue等语句,否则会把异常“吃掉”;

      2、在try,catch中如果有return语句,则在执行return之前先执行finally块

      请大家仔细看下面的例子:
    以下是引用片段:
    public class TryTest {  
        public static void main(String[] args) {  
            try {  
                System.out.println(TryTest.test());// 返回结果为true其没有任何异常  
            } catch (Exception e) {  
                System.out.println("Exception from main");  
                e.printStackTrace();  
            }  
            doThings(0);  
        }  
      
        public static boolean test() throws Exception {  
            try {  
                throw new Exception("Something error");// 第1步.抛出异常  
            } catch (Exception e) {// 第2步.捕获的异常匹配(声明类或其父类),进入控制块  
                System.out.println("Exception from e");// 第3步.打印

                return false;// 第5步. return前控制转移到finally块,执行完后再返回(这一步被吃掉了,不执行)  
            } finally {  
                return true; // 第4步. 控制转移,直接返回,吃掉了异常  
            }  
        }  
          
        public static void doThings(int i)  
        {  
         try  
         {  
          if(i==0)  
          {  
           //在执行return之前会先执行finally  
           return;  
          }  
          int t=100/i;  
          System.out.println(t);  
         }catch(Exception ex)  
         {  
          ex.printStackTrace();  
         }  
         finally  
         {  
          System.out.println("finally");  
         }  
        }  
    }

  • 面向过程与面向对象的区别

    2009-05-21 15:09:08

    两种方法都是编程中的比较常用的方法,从理论上来说,都能达到用计算机程序来解决实际问题的目的,

    只不过是其中所体现出来的思想不一样而已。


    面向过程:面向过程的思想是把一个项目、一件事情按照一定的顺序,从头到尾一步一步地做下去,先做

    什么,后做什么,一直到结束。这种思想比较好理解,其实这也是一个人做事的方法。


    面向对象:面向对象的思想是把一个项目、一件事情分成更小的项目,或者说分成一个个更小的部分,每

    一部分负责什么方面的功能,最后再由这些部分组合而成为一个整体。这种思想比较适合多人的分工合作

    ,就像一个大的机关,分成各个部门,每个部门分别负责某样职能,各个部门可以充分发挥自己的特色,

    只要符合一定前提就行了。


    举例说明1:比如刚才说的一个大的机关,要做某一个项目,从面向过程的思想来说,应该是这样分析的

    ,先怎么样,再怎么样,最后怎么样。第一样应该如何完成,第二样应该如何完成等等。等到每一步骤都

    完成,项目也就完成了。而面向对象的思想则应该是这样想的,这个项目是由几个部分组成的,我们就做

    好分工,成立一个部门来做一个部分的功能,另一个部门来做另一个部分。各个部门可以不用理解其他部

    门的事,只要完成自己那一部分的事情就OK了。


    举例说明2:又比如我们有一台演出,为简单起见,假设有如下流程:主持人开场——演员一表演——演

    员二表演——主持人总结。用面向过程的思想来分析,就是先完成主持人开场,再完成演员一的表演,再

    完成演员二的表演,最后完成主持人的总结。而如果用面向对象的思想来分析,就应该是这样的。这个演

    出由两大部分组成:主持人、演员。与主持人相关的:开场、总结。与演员相关的:演员编号、所演的节

    目。然后这台演出就可以这样策划:需要一个主持人a,需要两个演员b、c。演出的事情可以表示为:a的

    开场——> b、c的编号和节目——> a的总结。



  • J2SE简介

    2009-05-21 15:03:04

    多数编程语言都有预选编译好的类库以支持各种特定的功能,在Java中,类库以包(package)的形式提供,不同版本的Java提供不同的包,以面向特定的应用。

    Java2平台包括:标准版(J2SE)、企业版(J2EE)和微缩版(J2ME)三个版本。J2SE,J2ME和J2EE,这也就是SunONE(Open NetEnvironment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。

    Standard Edition(标准版) J2SE 包含那些构成Java语言核心的类。比如:数据库连接、接口定义、输入/输出、网络编程

    Enterprise Edition(企业版) J2EE 包含J2SE 中的类,并且还包含用于开发企业级应用的类。比如:EJB、servlet、JSP、XML、事务控制

    Micro Edition(微缩版) J2ME 包含J2SE中一部分类,用于消费类电子产品的软件开发。比如:呼机、智能卡、手机、PDA、机顶盒

    简单讲就是:

    j2se java 2 simple edtion 小型程序用

    j2ee java 2 enterprise edtion 大型程序用

    j2me java 2 micro editon 手机上用

    他们的范围是:J2SE包含于J2EE中,J2ME包含了J2SE的核心类,但新添加了一些专有类

    应用场合,API的覆盖范围各不相同。

    笼统的讲,可以这样理解:J2SE是基础;压缩一点,再增加一些CLDC等方面的特性就是J2ME;扩充一点,再增加一些EJB等企业应用方面的特性就是J2EE。

    补充一点J2EE更恰当的说,应该是JAVA2企业开发的技术规范,不仅仅是比标准版多了一些类。J2EE又包括许多组件,如Jsp, Servlet, JavaBean, EJB, JDBC, JavaMail等。

  • 实战[jnlp]权限

    2009-05-21 14:54:47

    第一次要用jnlp就闹出了不少问题,真郁闷了老长时间.
         苦战baidu,终于左弄右弄被我驯服了.
         problem.1
         第一次试jnlp就出现了错误,那个错误报什么忘了,反正要是使用jnlp调用的jar程序不需要对本地系统上的文件做读写操作时候就把
    <security>

    <all-permissions/>

    </security>
    这三行代码去掉就行了.
         problem.2
         真正难题就是这个,当jnlp调用的jar程序需要对本地系统的文件做读写操作的时候就需要做如下的步骤(我知道的解决方法):
    说明,我用jnlp调用的文件名为:myreport.jar
    (1)为jar文件签名.
    先cd到myreport.jar所在的目录
    执行:
    keytool -genkey -keystore fox.report -alias fox

    接下来它会问一些问题包括keystore的密码,key的密码等,如下所示:

    输入keystore密码: 123456

    您的名字与姓氏是什么?

    [Unknown]: jingle

    您的组织单位名称是什么?

    [Unknown]: nankai

    您的组织名称是什么?

    [Unknown]: c2

    您所在的城市或区域名称是什么?

    [Unknown]: tj

    您所在的州或省份名称是什么?

    [Unknown]: tj

    该单位的两字母国家代码是什么

    [Unknown]: CN

    CN=jingle, U=nankai, O=c2, L=tj, ST=tj, C=CN 正确吗?

    [否]: y

    输入<mykey>的主密码

             (如果和 keystore 密码相同,按回车): keypass



    执行:

    keytool -export -keystore fox.report -alias fox -file fox.cer

    接下来它会要求你输入keystore密码:,如下所示:

    输入keystore密码: 123456

    保存在文件中的认证<fox.cer>



    执行:

    jarsigner -keystore fox.report myreport.jar fox

    跟着提示你输入密码:

    Enter Passphrase for keystore: 123456

    Warning: The signer certificate will expire within six months.

    /*****    签证完成 *****/

    运行上面程序所生成的文件都放到和jar的同一级目录里面,我做的时候多点击了那个fox.cer签证,把签证加入了系统.

    (2)修改客户端 policy文件,开方权限.

    更改${JAVA_HOME}/jre1.5.0/lib/security/java.policy

    和${JAVA_HOME}/jdk1.5.0/jre/lib/security/java.policy

    (至于是不是两个文件都得改,我就不试了)



    grant {

    }

    代码里面加入需要的权限代码,

    对应我所做的jar需要提供如下的权限,

    // MODIFY fox add

    permission java.io.FilePermission "<<ALL FILES>>", "read";

    permission java.util.PropertyPermission "user.dir","read,write";

    permission java.util.PropertyPermission "user.home","read,write";

    permission java.util.PropertyPermission "mrj.version","read";

    具体要提供什么权限,可以根据所保的access denied来加.

    permission java.io.FilePermission "<<ALL FILES>>", "read";

    话应该都需要.



    (3)修改*.jnlp文件.

    这次就得加上权限了,三句话:

    <security>

    <all-permissions/>

    </security>

    over,这样就ok了.

    /************ 记录下这次的文件 **************/

    my.jnlp



    <?xml version="1.0" encoding="UTF-8"?>

    <jnlp spec="1.0+" codebase="http://localhost:8081/upload" href="my.jnlp">

    <information>

    <title>Fox jnlp</title>

    <vendor>XXX Corporation</vendor>

    <description>MyIE just demo how to program with jnlp.</description>

    <homepage href="http://localhost:8081" />

    <icon href="./../images/rookie.gif"/>

    <icon kind="splash" href="./../images/logo.gif"/>

    <offline-allowed/> 

    <security>

    <all-permissions/>

    </security>

    </information>

    <resources>

    <j2se version="1.3+"/>

    <jar href="finerreport.jar"/>

    </resources>

    <application-desc main-class="com.vanda.report.ZDesigner"/>

    </jnlp>



    java.policy



    // Standard extensions get all permissions by default

    grant codeBase "file:${{java.ext.dirs}}/*" {

    permission java.security.AllPermission;

    };

    // default permissions granted to all domains

    grant { 

    // Allows any thread to stop itself using the java.lang.Thread.stop()

    // method that takes no argument.

    // Note that this permission is granted by default only to remain

    // backwards compatible.

    // It is strongly recommended that you either remove this permission

    // from this policy file or further restrict it to code sources

    // that you specify, because Thread.stop() is potentially unsafe.

    // See "http://java.sun.com/notes" for more information.

    permission java.lang.RuntimePermission "stopThread";

    // allows anyone to listen on un-privileged ports

    permission java.net.SocketPermission "localhost:1024-", "listen";

    // "standard" properies that can be read by anyone

    permission java.util.PropertyPermission "java.version", "read";

    permission java.util.PropertyPermission "java.vendor", "read";

    permission java.util.PropertyPermission "java.vendor.url", "read";

    permission java.util.PropertyPermission "java.class.version", "read";

    permission java.util.PropertyPermission "os.name", "read";

    permission java.util.PropertyPermission "os.version", "read";

    permission java.util.PropertyPermission "os.arch", "read";

    permission java.util.PropertyPermission "file.separator", "read";

    permission java.util.PropertyPermission "path.separator", "read";

    permission java.util.PropertyPermission "line.separator", "read";



    // MODIFY fox add

    permission java.io.FilePermission "<<ALL FILES>>", "read";

    permission java.util.PropertyPermission "user.dir","read,write";

    permission java.util.PropertyPermission "user.home","read,write";

        permission java.util.PropertyPermission "mrj.version","read";

    permission java.util.PropertyPermission "java.specification.version", "read";

    permission java.util.PropertyPermission "java.specification.vendor", "read";

    permission java.util.PropertyPermission "java.specification.name", "read";

    permission java.util.PropertyPermission "java.vm.specification.version", "read";

    permission java.util.PropertyPermission "java.vm.specification.vendor", "read";

    permission java.util.PropertyPermission "java.vm.specification.name", "read";

    permission java.util.PropertyPermission "java.vm.version", "read";

    permission java.util.PropertyPermission "java.vm.vendor", "read";

    permission java.util.PropertyPermission "java.vm.name", "read";

    };



    在动态生成jnlp的问题上.要是用struts框架,需要在action上这样处理:

    (如果tomcat版本老还得去配置conf/web.xml,加上

    <mime-mapping>

    <extension>jnlp</extension>

    <mime-type>application/x-java-jnlp-file</mime-type>

    </mime-mapping>)



    PrintWriter ut = response.getWriter();

         response.setContentType("application/x-java-jnlp-file");

         out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");

         out.println("<jnlp spec=\"1.0+\" codebase=\"http://localhost\" href=\"report/jnlp/openFile.do\">");

         out.println("<information>");

         out.println("<title>JNLP</title>");

         out.println("<vendor>Hust</vendor>");

         out.println("<homepage href=\"\"/>");

         out.println("<description>Web Start</description>");

         out.println("</information>");

         out.println("<security>");

         out.println("</security>");

         out.println("<resources>");

         out.println("<j2se version=\"1.3+\"/>");

         out.println("<jar href=\"finereport.jar\"/>");

         out.println("</resources>");

         out.println("<application-desc main-class=\"com.vanda.report.ZDesigner\">");

         out.println("</application-desc>");

         out.println("</jnlp>");

    out.flush();
  • Java网络加载协议(JNLP)及Java Web Start

    2009-05-21 14:45:51

    在java开发的早期,重点被放在了客户端开发。语言中对于applet和安全下载的支持
    对于万维网(WWW)的发布看上去是个不错的主意。但是现实是java最大的成功在于服务器端,java的强大功能和适应性赢得了服务器端开发者的心。同时,客户端的开发落后了。棘手的开发问题限制了applet的效用,开发者被迫转向基于浏览器的瘦客户端。

    Java Network Launching Protocol (JNLP,java网络加载协议) 承诺改变这个现状。通过JCP(Java Community Process)的JSR-56的开发,
    JNLP解决了很多先前用java开发针对客户端的功能的问题。一个JNLP客户端是一个应用程序或者说服务,它可以从宿主于网络的资源中加载应用程序。如果你使用JNLP打包一个应用程序,那么一个JNLP客户端能够:

    o 为该应用探测,安装并且使用正确版本的JRE(java运行时环境)
    o 从浏览器或者桌面加载应用程序
    o 当新版本的应用出现时自动下载最新的版本。
    o 为了加速启动速度在本机缓存应用程序需要的类
    o 可以作为applet或者应用程序运行
    o 在必要的情况下下载原始的库
    o 以安全的方式使用诸如文件系统这样的本机资源
    o 自动定位和加载外部依赖资源

    Sun 提供了一个实现JNLP的称为Java Web Start(JWS)的参考实现。让我们使用它开发一个使用JFC Swing的简单应用。为了做这个,你需要从http://java.sun.com/products/javawebstart下载JWS。(译者注:JDK的新版本JDK1.4已经内置JWS,无须另外下载。)

    下面是应用程序的代码:

    //File HelloJNLP.java
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;

    public class HelloJNLP extends JFrame. {
       public HelloJNLP() {
         super("Hello JNLP");
         String loadedFrom = this.getClass().getClassLoader().toString();
         JLabel jl = new JLabel("loaded by " + loadedFrom);
         JEditorPane jtp = new JEditorPane("text/plain", 
                                                       "Edit this text");
         getContentPane().add(jl, BorderLayout.NORTH);
         getContentPane().add(jtp, BorderLayout.CENTER);
       }

       public static void main(String [] args) {
         JFrame. f = new HelloJNLP();
         f.setBounds(100,100,325,250);
         f.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
         f.setVisible(true);
         f.addWindowListener(new WindowAdapter() {
           public void windowClosed(WindowEvent e) {
             System.out.println("Shutting down...");
             System.exit(0);
           }
         });
       }
    }

    JNLP的核心是一个发布清单(deployment manifest)。它是一个使用.jnlp做
    扩展名的XML文件(JNLP规范简单的称之为"JNLP 文件")。要发布HelloJNLP,你需要在JNLP文件中描述它,就像下面这样:

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- file Hello.jnlp -->
    <jnlp codebase="http://staff.develop.com/halloway/TechTips/May2001"
    href="http://staff.develop.com/halloway/TechTips/May2001/Hello.jnlp">
             <information>
         <title>Hello</title>
         <vendor>Tech Tips Sample May 2001</vendor>
         <icon href="HelloJNLP.jpg"/>
       </information>
       <resources>
         <j2se version="1.2+"/>
         <jar href="HelloJNLP.jar"/>
       </resources>
       <application-desc main-class="HelloJNLP"/>
    </jnlp>

    这个清单包含客户端需要下载和使用HelloJNLP的所有信息:

    o jnlp元素的codebase属性指出搜索应用程序资源的顶级URL。
    o information元素指出一个JNLP用户接口可以显示给客户端的信息。
    o j2se元素指出客户端必须有1.2版本或者更新的J2SE(tm)。(这是对于applet开发的一个大的提高,因为它常常受限于浏览器提供的VM(虚拟机)) 
    o jar元素指出程序的JAR文件的相对于jnlp codebase位置。
    o application-desc元素指出要运行的类。你可以添加子元素用以指定命令行参数或者系统属性。

    要将这个应用程序发布给一个web服务器,你需要执行以下的步骤:

    1. 修改jnlp的codebase和hrefURL为你自己的web服务器的合适的URL。
        
    2. 将JNLP文件发布到web服务器。

    3. 编译并打包HelloJNLP.java并发布到web服务器。例如:
       
        jar cvf HelloJNLP.jar HelloJNLP.class HelloJNLP$1.class
       
    4. 创建一个图标HelloJNLP.jpg并将之安装在web服务器上。你可以使用
       http://staff.develop.com/halloway/TechTips/May2001/HelloJNLP.jpg
       
    5. 设置你的web服务器的mime-type关联:.jnlp映射到mime-type application/x-java-jnlp-file。例如,对于Apache,添加如下一行到mime.types:
       
        application/x-java-jnlp-file     jnlp
       
        重新启动web服务器。

    从客户端执行那个应用程序,首先确认你已经安装了JWS。然后简单的在浏览器中指向该jnlp文件。JWS客户端将下载该jnlp文件,下载必要的 资源,加载应用程序。你所看到的将是在一个编辑区中显示的文本"Edit this text" 。如果你在配置web服务器上有问题或者不能使用web服务器,你可以从
    http://staff.develop.com/halloway/TechTips/May2001/Hello.jnlp
    加载这个程序。

    注意HelloJNLP不是作为一个applet运行在浏览器中,而是作为一个独立的应用程序。

    当你关闭程序时,HelloJNLP使用System.out打印消息"Shutting down...",然而没有控制台可见。控制台是JWS的诸多设置中缺省设置为"off"的其中一个。这是你可以修改的一对设置中的一个值,就像下面这样:

    1. 编辑JWS安装目录中的javaws.cfg文件。添加一行"javaws.cfg.forceUpdate=true"。
    这会导致JWS在启动应用程序前自动检查更新的版本。
       
    2. 运行JWS。使用菜单File->Preferences,进入Advanced标签并且选择"Show Java Console"。(由于JDK1.4中的本机化,JWS将显示中文的界面,所以此处的因为被自动显示为对应的中文)同意,选择"Log Output"将日志输出到你选择的文件。当你在调试时并且需要捕获System.out和System.err时是非常有用的。

    HelloJNLP显示一个编辑器,但是编辑器的内容在你关闭程序后将丢失。将下面的代码添加到HelloJNLP.java会自动的将编辑器的状态存储到客户端的硬盘上:

    //changes to HelloJNLP.java
    import java.io.*;
    import java.net.*;
    import javax.jnlp.*;

       //replace the constructor with this new version:  
       JEditorPane jtp;
       public HelloJNLP() {
         super("Hello JNLP, Second Version");
         String loadedFrom = this.getClass().getClassLoader().toString();
         JLabel jl = new JLabel("loaded by " + loadedFrom);
         jtp = new JEditorPane("text/plain", "Edit this text");
         readEditorContents();
         getContentPane().add(jl, BorderLayout.NORTH);
         getContentPane().add(jtp, BorderLayout.CENTER);

         addWindowListener(new WindowAdapter() {
             public void windowClosed(WindowEvent e) {
               System.out.println("Shutting down...");
               try {
                 writeEditorContents();
               }
               catch (Exception ex) {
                 System.out.println("Yoinks!");
                 ex.printStackTrace();
               }
               System.exit(0);
             }
           });
       }

       //add these helper methods
       private void writeEditorContents() throws 
                     UnavailableServiceException, IOException {
           System.out.println("writeEditorContents");
         PersistenceService ps = (PersistenceService) 
           ServiceManager.lookup("javax.jnlp.PersistenceService");
         BasicService bs = (BasicService)
           ServiceManager.lookup("javax.jnlp.BasicService");
         URL baseURL = bs.getCodeBase();
         System.out.println("CodeBase was " + baseURL);
         URL editorURL = new URL(baseURL, "Editor");
         try {
           ps.create(editorURL, 1024);
         }
         catch (Exception e) {
           e.printStackTrace();
         }
         FileContents fc = ps.get(editorURL);
         DataOutputStream s = new DataOutputStream(
                                      fc.getOutputStream(false));
         String s = jtp.getText();
         os.writeUTF(s);
         os.flush();
         os.close();
       }

       private void readEditorContents() {
         try {
           PersistenceService ps = (PersistenceService) 
             ServiceManager.lookup("javax.jnlp.PersistenceService");
           BasicService bs = (BasicService)
             ServiceManager.lookup("javax.jnlp.BasicService");
           URL baseURL = bs.getCodeBase();
           URL editorURL = new URL(baseURL, "Editor");
           FileContents fc = ps.get(editorURL);
           DataInputStream is = new DataInputStream(fc.getInputStream());
           jtp.setText(is.readUTF());
           is.close();
         }
         catch (Exception e) {
           e.printStackTrace();
         }
       }

    (译者注:正常编译需要在CLASSPATH中添加javaws.jar的路径,在windows下为C:\Program Files\Java Web Start目录下)
    JNLP API定义了一套的服务用以绕过安全沙盒使得一些通常的客户端操作可以使用。
    在writeEditorContents方法中,BasicService查找应用程序的代码目录,然后
    PersistenceService将编辑区的内容缓存在本机硬盘上,这些内容被键入到一个和应用程序目录相对的URL下。 PersistenceService提供的名字/值对数据和浏览器的cookies很相似。JWS通过一对被称为"muffins"的东西实现了这 个,muffins不时候用来存储大数据,他们应该用于在客户端缓存小的标识符。然后这些标识符能被用于在服务器上定位大的信息。

    在web服务器上重新发布修改过的应用程序,然后试着从客户端运行它--依然通过URL。如果你没有web服务器,你可以从
    http://staff.develop.com/halloway/TechTips/May2001/Hello2.jnlp 运行这个新版本。JWS自动探测程序被改变并运行新的版本。你可以通过检查标题条的字符串来证实这点,它现在将显示"Hello JNLP,Second Version." 修改编辑区的内容,然后关闭它。当你再次加载该程序时,你的改变会出现。(当你第一次运行新版的程序时你会在控制台看到一个异常,这是因为 readEditorContents 第一次不能找到muffin。)
    (译者注:实际上第一次运行时出现的异常导致程序无法正常结束,从而使得编辑区的内容无法写入客户端,下次运行时也相当于第一次运行。即此程序无法展示文章的特性,可能是于笔者的JWS的版本有关,笔者使用的是最新的1.0.1_02(build b03))
    JNLP提供了比这里演示的更多的服务。例如,你可以:

    o 很好的控制程序如何被下载
    o 描述各个JAR之间的依赖关系
    o 下载并运行本机代码安装程序
    o 对签名的代码授予附件的权限
    o 请求指定版本的程序或者applet

    要了解更多有关JNLP的情况,请到
    http://java.sun.com/products/javawebstart/download-spec.html
    下载JNLP规范。

    要了解更多JWS的情况,请参考http://java.sun.com/products/javawebstart/
  • JNLP

    2009-05-21 11:49:14

           在java开发的早期,重点被放在了客户端开发。语言中对于applet和安全下载的支持对于万维网(WWW)的发布看上去是个不错的主意。但是现实是java最大的成功在于服务器端,java的强大功能和适应性赢得了服务器端开发者的心。同时,客户端的开发落后了。棘手的开发问题限制了applet的效用,开发者被迫转向基于浏览器的瘦客户端。 
      Java Network Launching Protocol (JNLP,java网络加载协议) 承诺改变这个现状。通过JCP(Java Community Process)的JSR-56的开发, JNLP解决了很多先前用java开发针对客户端的功能的问题。一个JNLP客户端是一个应用程序或者说服务,它可以从宿主于网络的资源中加载应用程序。如果你使用JNLP打包一个应用程序,那么一个JNLP客户端能够: 
      o 为该应用探测,安装并且使用正确版本的JRE(java运行时环境)
           o 从浏览器或者桌面加载应用程序
           o 当新版本的应用出现时自动下载最新的版本。
           o 为了加速启动速度在本机缓存应用程序需要的类 
           o 可以作为applet或者应用程序运行 
           o 在必要的情况下下载原始的库 
           o 以安全的方式使用诸如文件系统这样的本机资源
           o 自动定位和加载外部依赖资源.

     一。jnlp是什么?是java提供的一种让你可以通过浏览器直接执行java应用程序的途径,它使你可以直接通过一个网页上的url连接打开一个 java应 用程序.好处就不用说了,如果你的java应用程序以jnlp 的方式发布,如果版本升级后,不需要再向所有用户发布版本,只需要更新服务器的版本,这就相当于让java应用程序有了web应用的优点了.
          二。jnlp文件的具体说明

    <?xml version="1.0" encoding="UTF-8"?> dl.bitsCN.com网管软件下载

    <!--codebase 属性指出搜索应用程序资源的顶级URL,下面的icon/jar元素都是以这个URL为基本.-->

    <jnlp codebase="http://127.0.0.1:8081/webstart"> blog.bitsCN.com网管博客等你来搏

        <information>

           <!-- "开始"-"运行"菜单中输入"javaws""javaws -viewer"启动Web Start,会看到客户端已经安装的webstart应用程序-->

           <!--title :应用程序标题 vendor:供应商 so.bitsCN.com网管资料库任你搜

            title/vendor 元素必须,会显示在用"javaws -viewer"命令

            打开的应用程序缓存查看器(Java Application Cache Viewer)中--> www.bitsCN.net中国网管博客

            <title>HelloWorld</title>

            <vendor>Lively Corporation</vendor>

            <description>HelloWorld Test Example for WebStart.</description>

           <!--homepage :存放有关应用程序的相关文档的URL,如help文件等,仅仅是description作用--> bitsCN.com中国网管联盟

            <homepage href="http://127.0.0.1:8081/webstart/index.html"/>

            <!--icon 指定图标会显示在应用程序缓存查看器中,

            在查看器中新建webstart快捷方式到桌面时也会显示为快捷方式图标,

            只支持GIF/JPEG格式,其它格式无效-->

            <icon href="./images/logo.jpg"/>

           <!--splash sun的文档中提到会出现在webstart启动时的闪屏中,不过可能由于速度问题,我没有观察到-->

            <icon kind="splash" href="./images/logo.jpg"/>

            <!-- 允许离线启动,可以使用javaws -offline命令-->

            <offline-allowed/> 需要什么来搜一搜吧so.bitsCN.com

        </information>

        <resources>

           <!-- 指定客户端需要安装的j2se版本,下面指定为1.5+

            如果版本是1.4,在链接此jnlp文件时会提示更新j2se版本-->

            <j2se version="1.5+"/>

           <!-- 指定要下载到本地的jar文件(注意,所有的文件都需要打包才能够下载)

            可以包含一些资源文件,如icons/configuration files,可以使用getResource方法取得-->

            <jar href="./jar/jws/helloworld.jar"/>

        </resources>

        <!--application-desc 必须,指定webstart启动时执行jar文件中的哪个类-->

        <application-desc main-class="jws.HelloWorld"/> 

    </jnlp>
              三。应用JNLP部署应用
            (1)编写相关应用,打包成一系列jar;
            (2)根据jnlp文件说明修改相应的jnlp内容,修改相应的url和jar;
            (3)部署jnlp文件和jar到相应的web容器;
            (4)编写访问网页,即可使用该应用〔亦可下载jnlp文件使用jws运行应用〕;
              四。补充
             如果jar需要访问本地文件资源,需要为你的jar文件签名
            先在命令行用keytool产生一个keystore文件.
            keytool -genkey -keystore you.keystore –alias youApp

            命令行用jarsigner签名,当然这时候需要生成keystore时的密码
            jarsigner -keystore you.keystore appTest.jar youApp

    重新部署即可.

  • applet java 介绍

    2009-05-15 14:12:58

    介绍
    applet(小应用程序)采用java创建的基于html的程序。浏览器将其暂时下载到用户的硬盘上,并在web页打开时在本地运行。

    applet的工作原理


           含有applet的网页的html文件代码中部带有<applet>和</applet>这样一对标记,当支持java的网络浏览器遇到折兑标记时,就下载相应的小应用程序代码并在本地计算机上执行该applet。java applet是用java语言编写的一些小应用程序,这些程序是直接嵌入到页面中,由支持java的浏览器(ie或nescape)解释执行能够产生特殊效果的程序。它可以大大提高web页面的交互能力和动态执行能力。包含applet的网页被称为java-powered页。


           当用户访问这样的网页时,applet被下载到用户的计算机上执行,但前提是用户使用的时支持java的网络浏览器。由于applet是在用户的计算机上执行的,所以它的执行速度不受到网络宽带或者modem存取速度的限制,用户可以更好的欣赏网页上applet产生的多媒体效果。


           在java applet中,可以实现图形绘制,字体和颜色控制,动画和声音的插入,人机交互网络交流等功能。applet还提供了名为抽象窗口工具箱(abstract window toolkit,awt)的窗口环境开发工具。awt利用用户计算机的gui元素,可以建立标准的图形用户界面,如窗口、按钮、滚动条等。目前,在网络上由非常多的applet范例来生动地展现这些功能,读者可以去调阅相应的网页以观看它们的效果。


           applet小应用程序的实现主要依靠java.applet包中的applet类。与一般的应用程序不同,applet应用程序必须嵌入在html页面中,才能得到解释执行;同时applet可以从web页面中获得参数,并和web页面进行交互。


           含有applet的网页的html文件代码中必须带有<applet>和</applet>这样一对标记,当支持java的网络浏览器遇到这对标记时,就将下载相应的小程序代码并在本地计算机上执行applet小程序 。


           applet 是一种java的小应用程序,它通过使用该applet的html文件,由支持java的网页浏览器下载运行。也可以通过java开发工具的appletviewer来运行。applet程序离不开使用它的html文件。这个html文件中关于applet的信息至少应包含一下三点:

            1) 字节码文件名(编译后的java文件,以.class为后缀)

            2) 字节码文件地址

            3)在网页上显示applet的方式。


          一个html文件增加applet有关的内容只是使网页更加富有生气,如添加声音、动画等这些吸引人的特征,它并不会改变html文件中与applet无关的元素。


    applet的安全性限制


         为了防止这样的问题出现,在缺省的情况下,大多数浏览器在applet安全方面受到诸多的限制,几乎不能对系统进行任何“读”或“写”的操作:

         1.不允许applet访问本地文件系统

         2.applet不能执行任何本地计算机 上的程序

         3.不允许applet尝试打开除提供applet的服务器之外的任何系统的socket。

         4.不允许applet访问用户名、电子邮件地址等与本地系统有关的信息。

         5.对于applet而言,java环境中的某些标准系统属性使只读的

         6.applet不能创建或装载applet的机器的网络连接

         7.applet不能充当网络服务器,监听或接收来自远程系统的连接请求。

         8.不允许applet装载动态库或定义本地方法调用。

         9.applet不能操纵不在自己线程组中的任何线程。

         10.applet不能关闭jvm。


    参考网址:

    http://www.8ttt8.com/jishu/w2123.htm

  • jdk与jre区别

    2009-05-04 11:36:52

    jdk和jre有什么区别?

    简单的说JDK是面向开发人员使用的SDK,它提供了Java的开发环境和运行环境。SDK是Software Development Kit 一般指软件开发包,可以包括函数库、编译程序等。
    JDK就是Java Development Kit
    JRE是Java Runtime Enviroment是指Java的运行环境,是面向Java程序的使用者,而不是开发者。

    如果安装了JDK,会发现你的电脑有两套JRE,一套位于 \jre 另外一套位于 C:\Program Files\Java\j2re1.4.1_01 目录下,后面这套比前面那套少了Server端的Java虚拟机,不过直接将前面那套的Server端Java虚拟机复制过来就行了。而且在安装JDK可以选择是否安装这个位于 C:\Program Files\Jav a 目录下的JRE。如果你只安装JRE,而不是JDK,那么只会在 C:\Program Files\Java 目录下安装唯一的一套JRE。

    JRE的地位就象一台PC机一样,我们写好的 Win32应用程序需要操作系统帮我们运行,同样的,我们编写的Java程序也必须要JRE才能运行。所以当你装完JDK后,如果分别在硬盘上的两个不同地方安装了两套JRE,那么你可以想象你的电脑有两台虚拟的Java PC机,都具有运行Java程序的功能。所以我们可以说,只要你的电脑安装了JRE,就可以正确运行Jav a应用程序。

    1、为什么Sun要让JDK安装两套相同的JRE?
      这是因为JDK里面有很多用Java所编写的开发工具(如javac.exe、jar.exe 等),而且都放置在 \lib\tools.jar 里。从下面例子可以看出,先将tools.jar改名为tools1.jar,然后运行javac.exe,显示如下结果: Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/tools/javac /Main 这个意思是说,你输入javac.exe与输入 java -cp c:\jdk\lib\tools.jar com.sun.tools.javac.Main 是一样的,会得到相同的结果。从这里我们可以证明javac.exe只是一个包装器(Wrapper),而制作的目的是为了让开发者免于输入太长的指令。而且可以发现\lib目录下的程序都很小,不大于2 9K,从这里我们可以得出一个结论。就是JDK里的工具几乎是用Java所编写,所以也是Java应用程序,因此要使用JDK所附的工具来开发Java程序,也必须要自行附一套JRE才行,所以位于C:\Program Files\Java目录下的那套JRE就是用来运行一般Java程序用的。

    2、如果一台电脑安装两套以上的JRE,谁来决定呢?
      这个重大任务就落在java.exe身上。Java.exe的工作就是找到合适的JRE来运行 Java程序。 Java.exe依照底下的顺序来查找JRE:自己的目录下有没有JRE;父目录有没有JRE;查询注册表: [HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment] 所以java.exe的运行结果与你的电脑里面哪个JRE被执行有很大的关系。

    3、介绍JVM
     JRE目录下的Bin目录有两个目录:server与client。这就是真正的jvm.dll所在。 jvm.dll无法单独工作,当jvm.dll启动后,会使用explicit的方法(就是使用Win32 API之中的LoadLibrary()与GetProcAddress()来载入辅助用的动态链接库),而这些辅助用的动态链接库(.dll)都必须位于jvm.dll所在目录的父目录之中。因此想使用哪个JVM,只需要设置PATH,指向JRE所在目录底下的jvm.dll。

    JDK包含的基本组件包括: 
    ·javac – 编译器,将源程序转成字节码 
    ·jar – 打包工具,将相关的类文件打包成一个文件 
    ·javadoc – 文档生成器,从源码注释中提取文档 
    ·jdb – debugger,查错工具

Open Toolbar