修改httpd.conf中文編碼
          ?
          AddDefaultCharset GB2312
          DefaultLanguage GB2312
          AddLanguage zh-cn .cn
          下載 mod_jk2.so 并加載mod_jk2.so
          ?
          LoadModule jk2_module modules/mod_jk2.so
          在conf目錄新建workers2.properties文件
          ?
          ?
          [shm]
          file=${serverRoot}/logs/shm.file
          size=1048576
          #The socket channel
          [channel.socket:localhost:8009]
          port=8009
          host=127.0.0.1
          #define the worker
          [ajp13:localhost:8009]
          channel=channel.socket:localhost:8009
          #uri mapping
          [uri:/*.jsp]
          worker=ajp13:localhost:8009

          虛擬主機(jī)
          ?
          <VirtualHost *:80>
          ??? ServerAdmin?wweidong@sina.com
          ??? DocumentRoot "I:/Job/Java"
          ??? ServerName localhost
          ??? ErrorLog logs/sdg.com-error_log
          ??? CustomLog logs/sdg.com-access_log common
          </VirtualHost>
          posted @ 2006-12-18 17:28 edsonjava 閱讀(254) | 評論 (0)編輯 收藏
           
          Log4j基本使用方法

            Log4j由三個(gè)重要的組件構(gòu)成:日志級別ERROR、WARN、INFO、DEBUG,分別用來指定這條日志信息的重要程度;日志信息的輸出目的地指定了日志將打印到控制臺還是文件中;而輸出格式則控制了日志信息的顯示內(nèi)容。

            一、定義配置文件

            其實(shí)您也可以完全不使用配置文件,而是在代碼中配置Log4j環(huán)境。但是,使用配置文件將使您的應(yīng)用程序更加靈活。Log4j支持兩種配置文件格式,一種是XML格式的文件,一種是Java特性文件(鍵=值)。下面我們介紹使用Java特性文件做為配置文件的方法:

            1.配置根Logger,其語法為:

            log4j.rootLogger = [ level ] , appenderName, appenderName, …

            其中,level 是日志記錄的優(yōu)先級,分為OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定義的級別。Log4j建議只使用四個(gè)級別,優(yōu)先級從高到低分別是ERROR、WARN、INFO、DEBUG。通過在這里定義的級別,您可以控制到應(yīng)用程序中相應(yīng)級別的日志信息的開關(guān)。比如在這里定義了INFO級別,則應(yīng)用程序中所有DEBUG級別的日志信息將不被打印出來。 appenderName就是指定日志信息輸出到哪個(gè)地方。您可以同時(shí)指定多個(gè)輸出目的地。

            2.配置日志信息輸出目的地Appender,其語法為:

            log4j.appender.appenderName = fully.qualified.name.of.appender.class
            log4j.appender.appenderName.option1 = value1
            …
            log4j.appender.appenderName.option = valueN

            其中,Log4j提供的appender有以下幾種:
            org.apache.log4j.ConsoleAppender(控制臺),
            org.apache.log4j.FileAppender(文件),
            org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個(gè)日志文件),
            org.apache.log4j.RollingFileAppender(文件大小到達(dá)指定尺寸的時(shí)候產(chǎn)生一個(gè)新的文件),
            org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)

            3.配置日志信息的格式(布局),其語法為:

            log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
            log4j.appender.appenderName.layout.option1 = value1
            …
            log4j.appender.appenderName.layout.option = valueN

            其中,Log4j提供的layout有以下幾種:
            org.apache.log4j.HTMLLayout(以HTML表格形式布局),
            org.apache.log4j.PatternLayout(可以靈活地指定布局模式),
            org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串),
            org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時(shí)間、線程、類別等等信息)

            Log4J采用類似C語言中的printf函數(shù)的打印格式格式化日志信息,打印參數(shù)如下: %m 輸出代碼中指定的消息

            %p 輸出優(yōu)先級,即DEBUG,INFO,WARN,ERROR,F(xiàn)ATAL
            %r 輸出自應(yīng)用啟動到輸出該log信息耗費(fèi)的毫秒數(shù)
            %c 輸出所屬的類目,通常就是所在類的全名
            %t 輸出產(chǎn)生該日志事件的線程名
            %n 輸出一個(gè)回車換行符,Windows平臺為“\r\n”,Unix平臺為“\n”
            %d 輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},輸出類似:2002年10月18日 22:10:28,921
            %l 輸出日志事件的發(fā)生位置,包括類目名、發(fā)生的線程,以及在代碼中的行數(shù)。舉例:Testlog4.main(TestLog4.java:10)

            二、在代碼中使用Log4j

            1.得到記錄器

            使用Log4j,第一步就是獲取日志記錄器,這個(gè)記錄器將負(fù)責(zé)控制日志信息。其語法為:

            public static Logger getLogger( String name)

            通過指定的名字獲得記錄器,如果必要的話,則為這個(gè)名字創(chuàng)建一個(gè)新的記錄器。Name一般取本類的名字,比如:

            static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )

            2.讀取配置文件

            當(dāng)獲得了日志記錄器之后,第二步將配置Log4j環(huán)境,其語法為:

            BasicConfigurator.configure (): 自動快速地使用缺省Log4j環(huán)境。
            PropertyConfigurator.configure ( String configFilename) :讀取使用Java的特性文件編寫的配置文件。
            DOMConfigurator.configure ( String filename ) :讀取XML形式的配置文件。

            3.插入記錄信息(格式化日志信息)

            當(dāng)上兩個(gè)必要步驟執(zhí)行完畢,您就可以輕松地使用不同優(yōu)先級別的日志記錄語句插入到您想記錄日志的任何地方,其語法如下:

            Logger.debug ( Object message ) ;
            Logger.info ( Object message ) ;
            Logger.warn ( Object message ) ;
            Logger.error ( Object message ) ;

          posted @ 2006-11-21 17:04 edsonjava 閱讀(158) | 評論 (0)編輯 收藏
           

          說來奇怪,昨夜調(diào)了很久沒成功,今天上來第一次就成功了。

          這次的實(shí)驗(yàn)是為了獲得WS提供的一個(gè)person復(fù)雜對象其中的某一屬性。

          服務(wù)端提供getPerson,getPersons接口。getPerson根據(jù)PersonId提供一個(gè)Person對象。而Person包含三個(gè)屬性,personid,firstname,lastname所以說這個(gè)實(shí)驗(yàn)的主要目的就是去實(shí)驗(yàn)一下非純字符或數(shù)字操作的WS服務(wù)的客戶端怎么做。

          具體是這么來做的:

          1、在ECLIPSE里新建一個(gè)JAVA PROJECT

          ?

          2、在項(xiàng)目名稱上點(diǎn)右鍵,加入add xfire nature將xfire所需要的庫導(dǎo)入進(jìn)來。關(guān)于XFIRE的ECLIPSE插件可以參看這篇文章http://xfire.codehaus.org/Eclipse+Plugin

          ?

          3、點(diǎn)擊新建->其他,選擇xfire的eclipse插件提供的代碼生成工具

          ?

          4、填入WSDL的URL以及選擇要將代碼輸出的項(xiàng)目名稱

          ?

          5、確定后就能夠看到生成的代碼了,生成了很多文件,這些都是根據(jù)WSDL生成的,因?yàn)榉?wù)端提供的person是個(gè)復(fù)雜對象,不是簡單的一個(gè)加減操作,所以需要對復(fù)雜對象進(jìn)行生成。

          這里最關(guān)鍵的是兩個(gè)文件,PersonWebServiceClient以及PersonWebServicePortType(interface)。

          PersonWebServiceImpl是PersonWebServicePortType的實(shí)現(xiàn)。

          ?

          6、下面這部當(dāng)然就是我們自己開始寫客戶端了,我們寫個(gè)junit的測試

          先將junit庫導(dǎo)入到項(xiàng)目中,右鍵項(xiàng)目名稱,選擇properties-->java build path-->libraries-->add library-->JUNIT導(dǎo)入JUNIT庫,然后就能看到:

          準(zhǔn)備工作還沒有完成,但是先不做了,等一會再回來做。

          現(xiàn)在開始寫case吧。

          我建立了一個(gè)命叫motion.test的package,在里面加入文件WebServiceTest.java

          package motion.test;

          import junit.framework.TestCase;

          public class WebServiceTest extends TestCase {

          }

          現(xiàn)在我們加入test:

          ?public void testShow(){
          ??
          ??PersonWebServiceClient service = new PersonWebServiceClient();
          ??PersonWebServicePortType client = service.getPersonWebServiceHttpPort();
          ??
          ??System.out.print(client.getPerson("1").getFirstName());
          ??
          ?}

          這個(gè)test的目的是想打印出personid為1的那個(gè)person的firstname。

          現(xiàn)在運(yùn)行一下,如果不出意外肯定有錯(cuò)誤

          看下錯(cuò)誤怎么說吧:

          原來是有些包沒導(dǎo)進(jìn)來。

          然后我們再右鍵點(diǎn)擊項(xiàng)目,選xfire那項(xiàng)。

          將Commons Codec 和Commons HttpClient前面的勾打上,確定返回,run WebServiceTest.java?as junit test

          在Console里我們就能看到這么一行:javax.xml.bind.JAXBElement@198cb3d

          驚喜了一會突然發(fā)現(xiàn)這不是我們要的結(jié)果啊,我們是要顯示那個(gè)personid為1的那個(gè)人的firstname,難道他的firstname是這種奇怪的東西嗎?

          其實(shí)這只是xml元素的JAXB的表示形式。如果我們需要得到具體的值,要用getValue()方法,修改剛才的顯示語句如下:

          System.out.print(client.getPerson("1").getFirstName().getValue());

          再次run WebServiceTest.java?as junit test

          Console里出現(xiàn):yang

          這是便正確的結(jié)果。

          ?

          這個(gè)實(shí)驗(yàn)其實(shí)是非常簡單的,但是通過這個(gè)實(shí)驗(yàn)?zāi)軌蚩闯龊芏嗉?xì)節(jié)是需要去考慮的。

          對于選了web service課程或者想了解這方面的內(nèi)容的人來說,我希望通過這個(gè)能夠幫助你掌握一些客戶端的制作技術(shù)。

          在工具盛行的今天,做個(gè)服務(wù)端已經(jīng)是一項(xiàng)再簡單不過的事情了,而客戶端要相對麻煩一些。

          這篇就是一個(gè)入門級的復(fù)雜對象客戶端的制作過程。我也是剛剛開始學(xué)習(xí)這方面的知識,所以如果我有什么錯(cuò)誤歡迎您來指出,我也很樂意與你討論這些問題,希望大家都能一點(diǎn)一點(diǎn)的進(jìn)步。

          posted @ 2006-11-13 17:01 edsonjava 閱讀(409) | 評論 (0)編輯 收藏
           

          常聽大家討論哪個(gè) Java 開發(fā)工具比較好,JBuilder,Virtual Cafe ?

          今天介紹一個(gè)簡單易用的 Java 開發(fā),編譯,集成,測試工具:Jakarta Ant

          他被稱為 java 環(huán)境里的 make (make 在 C 程序開發(fā)里人人皆知)

          Java 程序編輯器愛用啥用啥,我喜歡用 UltraEdit。

          以 HelloWorld 為例介紹他的使用。

          此示例可在此下載:

          ftp://cinc.dns2go.com/pub/doc/code/ant/HelloWorld.zip

          .下載 ant :(最新版 1.5)

          http://jakarta.apache.org/builds/jakarta-ant/release/v1.5/bin/

          windows 下請下載 zip 文件

          unix 下請下載 tar.gz 文件

          .安裝 JDK:

          安裝到 c:/jdk,并確認(rèn)能找到 c:/jdk/bin/java

          .安裝 ant:

          把 ant 解壓到本地硬盤 c:/ant,并確認(rèn)能找到 c:/ant/bin/ant.bat

          .設(shè)置環(huán)境變量:

          JDK_HOME:c:/jdk

          ANT_HOME:c:/ant

          PATH:在原來的 PATH 開頭加上 c:/ant/bin;c:/jdk/bin

          注:

          windows 下做操作:我的電腦 -> 屬性 -> 高級 -> 環(huán)境變量 -> 用戶變量

          每次修改完環(huán)境變量,要重新打開 MS-DOS 窗口才能生效

          .開始開發(fā):

          一個(gè) ant 項(xiàng)目目錄結(jié)構(gòu):

          c:/HelloWorld :項(xiàng)目主目錄

          /src :源程序目錄

          /classes :編譯后的 class 文件目錄

          /lib :開發(fā)項(xiàng)目所需要的類庫目錄,比如開發(fā)數(shù)據(jù)庫時(shí)所需要的 jdbc lib(這次沒用到)

          /jar :打包好的 jar 程序目錄(這次沒用到)

          /build.xml :項(xiàng)目配置文件

          1.建立一個(gè)項(xiàng)目的主目錄

          mkdir c:/Helloworld

          2.創(chuàng)建項(xiàng)目配置文件:

          c:/HelloWorld/builder.xml

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

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

          3.建立源代碼目錄,所有的 Java 程序放在里面

          mkdir c:/HelloWorld/src

          4.創(chuàng)建 HelloWorld.java

          c:/HelloWorld/src/HelloWorld.java

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

          /**

          * Demo class for run HelloWorld by ANT

          */

          public class HelloWorld {

          public static void main(String args[]){

          System.out.println ("Hello World!");

          }

          } //EOC

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

          5.編譯 HelloWorld

          C:/HelloWorld>ant build

          Buildfile: build.xml

          build:

          BUILD SUCCESSFUL

          Total time: 2 seconds

          說明:

          調(diào)用 builder.xml 中的 target build

          在 c:/HelloWorld/classes 里會出現(xiàn) HelloWorld.class

          此命令會把 src 目錄下所有的 java 文件(包括子目錄下的)都編譯

          6.運(yùn)行 HelloWorld

          C:/HelloWorld>ant run

          Buildfile: build.xml

          build:

          run:

          [exec] Hello World!

          BUILD SUCCESSFUL

          Total time: 2 seconds

          調(diào)用 builder.xml 中的 target run

          注意 target run 后的 depends="build",只有 build 成功后 run 才可以被調(diào)用

          7.清除 class 文件:

          C:/HelloWorld>ant clean

          Buildfile: build.xml

          clean:

          [delete] Deleting 1 files from C:/Helloworld/classes

          [delete] Deleted 1 directory from C:/Helloworld/classes

          BUILD SUCCESSFUL

          Total time: 2 seconds

          使用 ANT 的好處:

          1.相對于其他項(xiàng)目管理工具,只有一個(gè)文本配置文件 build.xml,配置簡單

          2.命令簡單,一學(xué)就會,ant run, ant clean ...

          3.安裝簡單,占用資源少,只要安裝 Jdk, ANT 就可以運(yùn)行

          用 ANT 進(jìn)行 Java 程序開發(fā),已經(jīng)成了 Java 界的一個(gè)共識。

          在此基礎(chǔ)上,可以建立更復(fù)雜的項(xiàng)目

          在以后會繼續(xù)介紹:

          用 ANT 開發(fā) 數(shù)據(jù)庫項(xiàng)目

          用 ANT 開發(fā) WEB 應(yīng)用

          用 ANT 和 CVS 開發(fā)多人項(xiàng)目,并進(jìn)行項(xiàng)目版本管理。

          推薦閱讀:

          Apache Ant 1.5 Manual

          http://jakarta.apache.org/ant/manual/index.html

          如果有時(shí)間,應(yīng)該閱讀,能發(fā)現(xiàn)許多 ant 的強(qiáng)大功能。

          posted @ 2006-11-13 16:32 edsonjava 閱讀(278) | 評論 (1)編輯 收藏
           
          在平時(shí)工作中,難免會遇到把 XML 作為數(shù)據(jù)存儲格式。面對目前種類繁多的解決方案,哪個(gè)最適合我們呢?在這篇文章中,我對這四種主流方案做一個(gè)不完全評測,僅僅針對遍歷 XML 這塊來測試,因?yàn)楸闅v XML 是工作中使用最多的(至少我認(rèn)為)。

            預(yù) 備

            測試環(huán)境:

            AMD 毒龍1.4G OC 1.5G、256M DDR333、Windows2000 Server SP4、Sun JDK 1.4.1+Eclipse 2.1+Resin 2.1.8,在 Debug 模式下測試。

            XML 文件格式如下:

            <?xml version="1.0" encoding="GB2312"?>
            <RESULT>
            <VALUE>
            <NO>A1234</NO>
            <ADDR>四川省XX縣XX鎮(zhèn)XX路X段XX號</ADDR>
            </VALUE>
            <VALUE>
            <NO>B1234</NO>
            <ADDR>四川省XX市XX鄉(xiāng)XX村XX組</ADDR>
            </VALUE>
            </RESULT>

            測試方法:

            采用 JSP 端調(diào)用Bean(至于為什么采用JSP來調(diào)用,請參考:http://blog.csdn.net/rosen/archive/2004/10/15/138324.aspx),讓每一種方案分別解析10K、100K、1000K、10000K的 XML 文件,計(jì)算其消耗時(shí)間(單位:毫秒)。

            JSP 文件:

            <%@ page contentType="text/html; charset=gb2312" %>
            <%@ page import="com.test.*"%>

            <html>
            <body>
            <%
            String args[]={""};
            MyXMLReader.main(args);
            %>
            </body>
            </html>

            測 試

            首先出場的是 DOM(JAXP Crimson 解析器)

            DOM 是用與平臺和語言無關(guān)的方式表示 XML 文檔的官方 W3C 標(biāo)準(zhǔn)。DOM 是以層次結(jié)構(gòu)組織的節(jié)點(diǎn)或信息片斷的集合。這個(gè)層次結(jié)構(gòu)允許開發(fā)人員在樹中尋找特定信息。分析該結(jié)構(gòu)通常需要加載整個(gè)文檔和構(gòu)造層次結(jié)構(gòu),然后才能做任何工作。由于它是基于信息層次的,因而 DOM 被認(rèn)為是基于樹或基于對象的。DOM 以及廣義的基于樹的處理具有幾個(gè)優(yōu)點(diǎn)。首先,由于樹在內(nèi)存中是持久的,因此可以修改它以便應(yīng)用程序能對數(shù)據(jù)和結(jié)構(gòu)作出更改。它還可以在任何時(shí)候在樹中上下導(dǎo)航,而不是像 SAX 那樣是一次性的處理。DOM 使用起來也要簡單得多。

            另一方面,對于特別大的文檔,解析和加載整個(gè)文檔可能很慢且很耗資源,因此使用其他手段來處理這樣的數(shù)據(jù)會更好。這些基于事件的模型,比如 SAX。

            Bean文件:

            package com.test;

            import java.io.*;
            import java.util.*;
            import org.w3c.dom.*;
            import javax.xml.parsers.*;

            public class MyXMLReader{

            public static void main(String arge[]){
            long lasting =System.currentTimeMillis();
            try{
             File f=new File("data_10k.xml");
             DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
             DocumentBuilder builder=factory.newDocumentBuilder();
             Document doc = builder.parse(f);
             NodeList nl = doc.getElementsByTagName("VALUE");
             for (int i=0;i<nl.getLength();i++){
              System.out.print("車牌號碼:" + doc.getElementsByTagName("NO").item(i).getFirstChild().getNodeValue());
              System.out.println(" 車主地址:" + doc.getElementsByTagName("ADDR").item(i).getFirstChild().getNodeValue());
            }
            }catch(Exception e){
             e.printStackTrace();
            }
            System.out.println("運(yùn)行時(shí)間:"+(System.currentTimeMillis() - lasting)+" 毫秒");
            }
            }


            10k消耗時(shí)間:265 203 219 172
            100k消耗時(shí)間:9172 9016 8891 9000
            1000k消耗時(shí)間:691719 675407 708375 739656
            10000k消耗時(shí)間:OutOfMemoryError

            接著是 SAX

            這種處理的優(yōu)點(diǎn)非常類似于流媒體的優(yōu)點(diǎn)。分析能夠立即開始,而不是等待所有的數(shù)據(jù)被處理。而且,由于應(yīng)用程序只是在讀取數(shù)據(jù)時(shí)檢查數(shù)據(jù),因此不需要將數(shù)據(jù)存儲在內(nèi)存中。這對于大型文檔來說是個(gè)巨大的優(yōu)點(diǎn)。事實(shí)上,應(yīng)用程序甚至不必解析整個(gè)文檔;它可以在某個(gè)條件得到滿足時(shí)停止解析。一般來說,SAX 還比它的替代者 DOM 快許多。

             選擇 DOM 還是選擇 SAX ?

            對于需要自己編寫代碼來處理 XML 文檔的開發(fā)人員來說,選擇 DOM 還是 SAX 解析模型是一個(gè)非常重要的設(shè)計(jì)決策。

            DOM 采用建立樹形結(jié)構(gòu)的方式訪問 XML 文檔,而 SAX 采用的事件模型。

            DOM 解析器把 XML 文檔轉(zhuǎn)化為一個(gè)包含其內(nèi)容的樹,并可以對樹進(jìn)行遍歷。用 DOM 解析模型的優(yōu)點(diǎn)是編程容易,開發(fā)人員只需要調(diào)用建樹的指令,然后利用navigation APIs訪問所需的樹節(jié)點(diǎn)來完成任務(wù)。可以很容易的添加和修改樹中的元素。然而由于使用 DOM 解析器的時(shí)候需要處理整個(gè) XML 文檔,所以對性能和內(nèi)存的要求比較高,尤其是遇到很大的 XML 文件的時(shí)候。由于它的遍歷能力,DOM 解析器常用于 XML 文檔需要頻繁的改變的服務(wù)中。

            SAX 解析器采用了基于事件的模型,它在解析 XML 文檔的時(shí)候可以觸發(fā)一系列的事件,當(dāng)發(fā)現(xiàn)給定的tag的時(shí)候,它可以激活一個(gè)回調(diào)方法,告訴該方法制定的標(biāo)簽已經(jīng)找到。SAX 對內(nèi)存的要求通常會比較低,因?yàn)樗岄_發(fā)人員自己來決定所要處理的tag。特別是當(dāng)開發(fā)人員只需要處理文檔中所包含的部分?jǐn)?shù)據(jù)時(shí),SAX 這種擴(kuò)展能力得到了更好的體現(xiàn)。但用 SAX 解析器的時(shí)候編碼工作會比較困難,而且很難同時(shí)訪問同一個(gè)文檔中的多處不同數(shù)據(jù)。

            Bean文件:

            package com.test;
            import org.xml.sax.*;
            import org.xml.sax.helpers.*;
            import javax.xml.parsers.*;

            public class MyXMLReader extends DefaultHandler {

            java.util.Stack tags = new java.util.Stack();

            public MyXMLReader() {
            super();
            }

            public static void main(String args[]) {
            long lasting = System.currentTimeMillis();
            try {
             SAXParserFactory sf = SAXParserFactory.newInstance();
             SAXParser sp = sf.newSAXParser();
             MyXMLReader reader = new MyXMLReader();
             sp.parse(new InputSource("data_10k.xml"), reader);
            } catch (Exception e) {
             e.printStackTrace();
            }
            System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting) + " 毫秒");
            }

            public void characters(char ch[], int start, int length) throws SAXException {
            String tag = (String) tags.peek();
            if (tag.equals("NO")) {
             System.out.print("車牌號碼:" + new String(ch, start, length));
            }
            if (tag.equals("ADDR")) {
            System.out.println(" 地址:" + new String(ch, start, length));
            }
            }

            public void startElement(
            String uri,
            String localName,
            String qName,
            Attributes attrs) {
            tags.push(qName);
            }
            }

            10k消耗時(shí)間:110 47 109 78
            100k消耗時(shí)間:344 406 375 422
            1000k消耗時(shí)間:3234 3281 3688 3312
            10000k消耗時(shí)間:32578 34313 31797 31890 30328

            然后是 JDOM http://www.jdom.org/

            JDOM 的目的是成為 Java 特定文檔模型,它簡化與 XML 的交互并且比使用 DOM 實(shí)現(xiàn)更快。由于是第一個(gè) Java 特定模型,JDOM 一直得到大力推廣和促進(jìn)。正在考慮通過“Java 規(guī)范請求 JSR-102”將它最終用作“Java 標(biāo)準(zhǔn)擴(kuò)展”。從 2000 年初就已經(jīng)開始了 JDOM 開發(fā)。

            JDOM 與 DOM 主要有兩方面不同。首先,JDOM 僅使用具體類而不使用接口。這在某些方面簡化了 API,但是也限制了靈活性。第二,API 大量使用了 Collections 類,簡化了那些已經(jīng)熟悉這些類的 Java 開發(fā)者的使用。

            JDOM 文檔聲明其目的是“使用 20%(或更少)的精力解決 80%(或更多)Java/XML 問題”(根據(jù)學(xué)習(xí)曲線假定為 20%)。JDOM 對于大多數(shù) Java/XML 應(yīng)用程序來說當(dāng)然是有用的,并且大多數(shù)開發(fā)者發(fā)現(xiàn) API 比 DOM 容易理解得多。JDOM 還包括對程序行為的相當(dāng)廣泛檢查以防止用戶做任何在 XML 中無意義的事。然而,它仍需要您充分理解 XML 以便做一些超出基本的工作(或者甚至理解某些情況下的錯(cuò)誤)。這也許是比學(xué)習(xí) DOM 或 JDOM 接口都更有意義的工作。

            JDOM 自身不包含解析器。它通常使用 SAX2 解析器來解析和驗(yàn)證輸入 XML 文檔(盡管它還可以將以前構(gòu)造的 DOM 表示作為輸入)。它包含一些轉(zhuǎn)換器以將 JDOM 表示輸出成 SAX2 事件流、DOM 模型或 XML 文本文檔。JDOM 是在 Apache 許可證變體下發(fā)布的開放源碼。

            Bean文件:

            package com.test;

            import java.io.*;
            import java.util.*;
            import org.jdom.*;
            import org.jdom.input.*;

            public class MyXMLReader {

            public static void main(String arge[]) {
            long lasting = System.currentTimeMillis();
            try {
             SAXBuilder builder = new SAXBuilder();
             Document doc = builder.build(new File("data_10k.xml"));
             Element foo = doc.getRootElement();
             List allChildren = foo.getChildren();
             for(int i=0;i<allChildren.size();i++) {
              System.out.print("車牌號碼:" + ((Element)allChildren.get(i)).getChild("NO").getText());
              System.out.println(" 車主地址:" + ((Element)allChildren.get(i)).getChild("ADDR").getText());
             }
            } catch (Exception e) {
             e.printStackTrace();
            }
            System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting) + " 毫秒");
            }
            }

            10k消耗時(shí)間:125 62 187 94
            100k消耗時(shí)間:704 625 640 766
            1000k消耗時(shí)間:27984 30750 27859 30656
            10000k消耗時(shí)間:OutOfMemoryError

            最后是 DOM4J http://dom4j.sourceforge.net/

            雖然 DOM4J 代表了完全獨(dú)立的開發(fā)結(jié)果,但最初,它是 JDOM 的一種智能分支。它合并了許多超出基本 XML 文檔表示的功能,包括集成的 XPath 支持、XML Schema 支持以及用于大文檔或流化文檔的基于事件的處理。它還提供了構(gòu)建文檔表示的選項(xiàng),它通過 DOM4J API 和標(biāo)準(zhǔn) DOM 接口具有并行訪問功能。從 2000 下半年開始,它就一直處于開發(fā)之中。

            為支持所有這些功能,DOM4J 使用接口和抽象基本類方法。DOM4J 大量使用了 API 中的 Collections 類,但是在許多情況下,它還提供一些替代方法以允許更好的性能或更直接的編碼方法。直接好處是,雖然 DOM4J 付出了更復(fù)雜的 API 的代價(jià),但是它提供了比 JDOM 大得多的靈活性。

            在添加靈活性、XPath 集成和對大文檔處理的目標(biāo)時(shí),DOM4J 的目標(biāo)與 JDOM 是一樣的:針對 Java 開發(fā)者的易用性和直觀操作。它還致力于成為比 JDOM 更完整的解決方案,實(shí)現(xiàn)在本質(zhì)上處理所有 Java/XML 問題的目標(biāo)。在完成該目標(biāo)時(shí),它比 JDOM 更少強(qiáng)調(diào)防止不正確的應(yīng)用程序行為。

            DOM4J 是一個(gè)非常非常優(yōu)秀的Java XML API,具有性能優(yōu)異、功能強(qiáng)大和極端易用使用的特點(diǎn),同時(shí)它也是一個(gè)開放源代碼的軟件。如今你可以看到越來越多的 Java 軟件都在使用 DOM4J 來讀寫 XML,特別值得一提的是連 Sun 的 JAXM 也在用 DOM4J。

            Bean文件:

            package com.test;

            import java.io.*;
            import java.util.*;
            import org.dom4j.*;
            import org.dom4j.io.*;

            public class MyXMLReader {

            public static void main(String arge[]) {
            long lasting = System.currentTimeMillis();
            try {
             File f = new File("data_10k.xml");
             SAXReader reader = new SAXReader();
             Document doc = reader.read(f);
             Element root = doc.getRootElement();
             Element foo;
             for (Iterator i = root.elementIterator("VALUE"); i.hasNext();) {
              foo = (Element) i.next();
              System.out.print("車牌號碼:" + foo.elementText("NO"));
              System.out.println(" 車主地址:" + foo.elementText("ADDR"));
             }
            } catch (Exception e) {
             e.printStackTrace();
            }
            System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting) + " 毫秒");
            }
            }

            10k消耗時(shí)間:109 78 109 31
            100k消耗時(shí)間:297 359 172 312
            1000k消耗時(shí)間:2281 2359 2344 2469
            10000k消耗時(shí)間:20938 19922 20031 21078

            JDOM 和 DOM 在性能測試時(shí)表現(xiàn)不佳,在測試 10M 文檔時(shí)內(nèi)存溢出。在小文檔情況下還值得考慮使用 DOM 和 JDOM。雖然 JDOM 的開發(fā)者已經(jīng)說明他們期望在正式發(fā)行版前專注性能問題,但是從性能觀點(diǎn)來看,它確實(shí)沒有值得推薦之處。另外,DOM 仍是一個(gè)非常好的選擇。DOM 實(shí)現(xiàn)廣泛應(yīng)用于多種編程語言。它還是許多其它與 XML 相關(guān)的標(biāo)準(zhǔn)的基礎(chǔ),因?yàn)樗将@得 W3C 推薦(與基于非標(biāo)準(zhǔn)的 Java 模型相對),所以在某些類型的項(xiàng)目中可能也需要它(如在 JavaScript 中使用 DOM)。

            SAX表現(xiàn)較好,這要依賴于它特定的解析方式。一個(gè) SAX 檢測即將到來的XML流,但并沒有載入到內(nèi)存(當(dāng)然當(dāng)XML流被讀入時(shí),會有部分文檔暫時(shí)隱藏在內(nèi)存中)。

            無疑,DOM4J是這場測試的獲勝者,目前許多開源項(xiàng)目中大量采用 DOM4J,例如大名鼎鼎的 Hibernate 也用 DOM4J 來讀取 XML 配置文件。如果不考慮可移植性,那就采用DOM4J吧!

          posted @ 2006-11-08 11:47 edsonjava 閱讀(195) | 評論 (0)編輯 收藏
           

          HTTP 1.1狀態(tài)代碼及其含義

            

          下表顯示了常見的HTTP 1.1狀態(tài)代碼以及它們對應(yīng)的狀態(tài)信息和含義。

          應(yīng)當(dāng)謹(jǐn)慎地使用那些只有HTTP 1.1支持的狀態(tài)代碼,因?yàn)樵S多瀏覽器還只能夠支持HTTP 1.0。如果你使用了HTTP 1.1特有的狀態(tài)代碼,最好能夠檢查一下請求的HTTP版本號。

          狀態(tài)代碼 狀態(tài)信息 含義
          100 Continue 初始的請求已經(jīng)接受,客戶應(yīng)當(dāng)繼續(xù)發(fā)送請求的其余部分。(HTTP 1.1新)
          101 Switching Protocols 服務(wù)器將遵從客戶的請求轉(zhuǎn)換到另外一種協(xié)議(HTTP 1.1新)
          200 OK 一切正常,對GET和POST請求的應(yīng)答文檔跟在后面。
          201 Created 服務(wù)器已經(jīng)創(chuàng)建了文檔,Location頭給出了它的URL。
          202 Accepted 已經(jīng)接受請求,但處理尚未完成。
          203 Non-Authoritative Information 文檔已經(jīng)正常地返回,但一些應(yīng)答頭可能不正確,因?yàn)槭褂玫氖俏臋n的拷貝(HTTP 1.1新)。
          204 No Content 沒有新文檔,瀏覽器應(yīng)該繼續(xù)顯示原來的文檔。如果用戶定期地刷新頁面,而Servlet可以確定用戶文檔足夠新,這個(gè)狀態(tài)代碼是很有用的。
          205 Reset Content 沒有新的內(nèi)容,但瀏覽器應(yīng)該重置它所顯示的內(nèi)容。用來強(qiáng)制瀏覽器清除表單輸入內(nèi)容(HTTP 1.1新)。
          206 Partial Content 客戶發(fā)送了一個(gè)帶有Range頭的GET請求,服務(wù)器完成了它(HTTP 1.1新)。
          300 Multiple Choices 客戶請求的文檔可以在多個(gè)位置找到,這些位置已經(jīng)在返回的文檔內(nèi)列出。如果服務(wù)器要提出優(yōu)先選擇,則應(yīng)該在Location應(yīng)答頭指明。
          301 Moved Permanently 客戶請求的文檔在其他地方,新的URL在Location頭中給出,瀏覽器應(yīng)該自動地訪問新的URL。
          302 Found 類似于301,但新的URL應(yīng)該被視為臨時(shí)性的替代,而不是永久性的。注意,在HTTP1.0中對應(yīng)的狀態(tài)信息是“Moved Temporatily”。

          出現(xiàn)該狀態(tài)代碼時(shí),瀏覽器能夠自動訪問新的URL,因此它是一個(gè)很有用的狀態(tài)代碼。

          注意這個(gè)狀態(tài)代碼有時(shí)候可以和301替換使用。例如,如果瀏覽器錯(cuò)誤地請求http://host/~user(缺少了后面的斜杠),有的服務(wù)器返回301,有的則返回302。

          嚴(yán)格地說,我們只能假定只有當(dāng)原來的請求是GET時(shí)瀏覽器才會自動重定向。請參見307。

          303 See Other 類似于301/302,不同之處在于,如果原來的請求是POST,Location頭指定的重定向目標(biāo)文檔應(yīng)該通過GET提取(HTTP 1.1新)。
          304 Not Modified 客戶端有緩沖的文檔并發(fā)出了一個(gè)條件性的請求(一般是提供If-Modified-Since頭表示客戶只想比指定日期更新的文檔)。服務(wù)器告訴客戶,原來緩沖的文檔還可以繼續(xù)使用。
          305 Use Proxy 客戶請求的文檔應(yīng)該通過Location頭所指明的代理服務(wù)器提取(HTTP 1.1新)。
          307 Temporary Redirect 和302(Found)相同。許多瀏覽器會錯(cuò)誤地響應(yīng)302應(yīng)答進(jìn)行重定向,即使原來的請求是POST,即使它實(shí)際上只能在POST請求的應(yīng)答是303時(shí)才能重定向。由于這個(gè)原因,HTTP 1.1新增了307,以便更加清除地區(qū)分幾個(gè)狀態(tài)代碼:當(dāng)出現(xiàn)303應(yīng)答時(shí),瀏覽器可以跟隨重定向的GET和POST請求;如果是307應(yīng)答,則瀏覽器只能跟隨對GET請求的重定向。(HTTP 1.1新)
          400 Bad Request 請求出現(xiàn)語法錯(cuò)誤。
          401 Unauthorized 客戶試圖未經(jīng)授權(quán)訪問受密碼保護(hù)的頁面。應(yīng)答中會包含一個(gè)WWW-Authenticate頭,瀏覽器據(jù)此顯示用戶名字/密碼對話框,然后在填寫合適的Authorization頭后再次發(fā)出請求。
          403 Forbidden 資源不可用。服務(wù)器理解客戶的請求,但拒絕處理它。通常由于服務(wù)器上文件或目錄的權(quán)限設(shè)置導(dǎo)致。
          404 Not Found 無法找到指定位置的資源。這也是一個(gè)常用的應(yīng)答。
          405 Method Not Allowed 請求方法(GET、POST、HEAD、DELETE、PUT、TRACE等)對指定的資源不適用。(HTTP 1.1新)
          406 Not Acceptable 指定的資源已經(jīng)找到,但它的MIME類型和客戶在Accpet頭中所指定的不兼容(HTTP 1.1新)。
          407 Proxy Authentication Required 類似于401,表示客戶必須先經(jīng)過代理服務(wù)器的授權(quán)。(HTTP 1.1新)
          408 Request Timeout 在服務(wù)器許可的等待時(shí)間內(nèi),客戶一直沒有發(fā)出任何請求。客戶可以在以后重復(fù)同一請求。(HTTP 1.1新)
          409 Conflict 通常和PUT請求有關(guān)。由于請求和資源的當(dāng)前狀態(tài)相沖突,因此請求不能成功。(HTTP 1.1新)
          410 Gone 所請求的文檔已經(jīng)不再可用,而且服務(wù)器不知道應(yīng)該重定向到哪一個(gè)地址。它和404的不同在于,返回407表示文檔永久地離開了指定的位置,而404表示由于未知的原因文檔不可用。(HTTP 1.1新)
          411 Length Required 服務(wù)器不能處理請求,除非客戶發(fā)送一個(gè)Content-Length頭。(HTTP 1.1新)
          412 Precondition Failed 請求頭中指定的一些前提條件失敗(HTTP 1.1新)。
          413 Request Entity Too Large 目標(biāo)文檔的大小超過服務(wù)器當(dāng)前愿意處理的大小。如果服務(wù)器認(rèn)為自己能夠稍后再處理該請求,則應(yīng)該提供一個(gè)Retry-After頭(HTTP 1.1新)。
          414 Request URI Too Long URI太長(HTTP 1.1新)。
          416 Requested Range Not Satisfiable 服務(wù)器不能滿足客戶在請求中指定的Range頭。(HTTP 1.1新)
          500 Internal Server Error 服務(wù)器遇到了意料不到的情況,不能完成客戶的請求。
          501 Not Implemented 服務(wù)器不支持實(shí)現(xiàn)請求所需要的功能。例如,客戶發(fā)出了一個(gè)服務(wù)器不支持的PUT請求。
          502 Bad Gateway 服務(wù)器作為網(wǎng)關(guān)或者代理時(shí),為了完成請求訪問下一個(gè)服務(wù)器,但該服務(wù)器返回了非法的應(yīng)答。
          503 Service Unavailable 服務(wù)器由于維護(hù)或者負(fù)載過重未能應(yīng)答。例如,Servlet可能在數(shù)據(jù)庫連接池已滿的情況下返回503。服務(wù)器返回503時(shí)可以提供一個(gè)Retry-After頭。
          504 Gateway Timeout 由作為代理或網(wǎng)關(guān)的服務(wù)器使用,表示不能及時(shí)地從遠(yuǎn)程服務(wù)器獲得應(yīng)答。(HTTP 1.1新)
          505 HTTP Version Not Supported 服務(wù)器不支持請求中所指明的HTTP版本。(HTTP 1.1新)
          posted @ 2006-11-08 11:25 edsonjava 閱讀(237) | 評論 (0)編輯 收藏
           

          HttpClient入門

          developerWorks
          文檔選項(xiàng)
          將此頁作為電子郵件發(fā)送

          將此頁作為電子郵件發(fā)送

          未顯示需要 JavaScript 的文檔選項(xiàng)


          拓展 Tomcat 應(yīng)用

          下載 IBM 開源 J2EE 應(yīng)用服務(wù)器 WAS CE 新版本 V1.1


          級別: 高級

          金發(fā)華 , 軟件工程師,IBM CSDL, IBM
          陳樟洪 , 軟件工程師,IBM CSDL, IBM

          2005 年 11 月 10 日

          HttpClient 是 Apache Jakarta Common 下的子項(xiàng)目,可以用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議。本文首先介紹 HTTPClient,然后根據(jù)作者實(shí)際工作經(jīng)驗(yàn)給出了一些常見問題的解決方法。

          HttpClient簡介

          HTTP 協(xié)議可能是現(xiàn)在 Internet 上使用得最多、最重要的協(xié)議了,越來越多的 Java 應(yīng)用程序需要直接通過 HTTP 協(xié)議來訪問網(wǎng)絡(luò)資源。雖然在 JDK 的 java.net 包中已經(jīng)提供了訪問 HTTP 協(xié)議的基本功能,但是對于大部分應(yīng)用程序來說,JDK 庫本身提供的功能還不夠豐富和靈活。HttpClient 是 Apache Jakarta Common 下的子項(xiàng)目,用來提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議。HttpClient 已經(jīng)應(yīng)用在很多的項(xiàng)目中,比如 Apache Jakarta 上很著名的另外兩個(gè)開源項(xiàng)目 Cactus 和 HTMLUnit 都使用了 HttpClient,更多使用 HttpClient 的應(yīng)用可以參見http://wiki.apache.org/jakarta-httpclient/HttpClientPowered。HttpClient 項(xiàng)目非常活躍,使用的人還是非常多的。目前 HttpClient 版本是在 2005.10.11 發(fā)布的 3.0 RC4 。





          回頁首


          HttpClient 功能介紹

          以下列出的是 HttpClient 提供的主要的功能,要知道更多詳細(xì)的功能可以參見 HttpClient 的主頁。

          • 實(shí)現(xiàn)了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
          • 支持自動轉(zhuǎn)向
          • 支持 HTTPS 協(xié)議
          • 支持代理服務(wù)器等

          下面將逐一介紹怎樣使用這些功能。首先,我們必須安裝好 HttpClient。





          回頁首


          HttpClient 基本功能的使用

          GET 方法

          使用 HttpClient 需要以下 6 個(gè)步驟:

          1. 創(chuàng)建 HttpClient 的實(shí)例

          2. 創(chuàng)建某種連接方法的實(shí)例,在這里是 GetMethod。在 GetMethod 的構(gòu)造函數(shù)中傳入待連接的地址

          3. 調(diào)用第一步中創(chuàng)建好的實(shí)例的 execute 方法來執(zhí)行第二步中創(chuàng)建好的 method 實(shí)例

          4. 讀 response

          5. 釋放連接。無論執(zhí)行方法是否成功,都必須釋放連接

          6. 對得到后的內(nèi)容進(jìn)行處理

          根據(jù)以上步驟,我們來編寫用GET方法來取得某網(wǎng)頁內(nèi)容的代碼。

          • 大部分情況下 HttpClient 默認(rèn)的構(gòu)造函數(shù)已經(jīng)足夠使用。
            HttpClient httpClient = new HttpClient();
            

          • 創(chuàng)建GET方法的實(shí)例。在GET方法的構(gòu)造函數(shù)中傳入待連接的地址即可。用GetMethod將會自動處理轉(zhuǎn)發(fā)過程,如果想要把自動處理轉(zhuǎn)發(fā)過程去掉的話,可以調(diào)用方法setFollowRedirects(false)。
            GetMethod getMethod = new GetMethod("http://www.ibm.com/");
            

          • 調(diào)用實(shí)例httpClient的executeMethod方法來執(zhí)行g(shù)etMethod。由于是執(zhí)行在網(wǎng)絡(luò)上的程序,在運(yùn)行executeMethod方法的時(shí)候,需要處理兩個(gè)異常,分別是HttpException和IOException。引起第一種異常的原因主要可能是在構(gòu)造getMethod的時(shí)候傳入的協(xié)議不對,比如不小心將"http"寫成"htp",或者服務(wù)器端返回的內(nèi)容不正常等,并且該異常發(fā)生是不可恢復(fù)的;第二種異常一般是由于網(wǎng)絡(luò)原因引起的異常,對于這種異常 (IOException),HttpClient會根據(jù)你指定的恢復(fù)策略自動試著重新執(zhí)行executeMethod方法。HttpClient的恢復(fù)策略可以自定義(通過實(shí)現(xiàn)接口HttpMethodRetryHandler來實(shí)現(xiàn))。通過httpClient的方法setParameter設(shè)置你實(shí)現(xiàn)的恢復(fù)策略,本文中使用的是系統(tǒng)提供的默認(rèn)恢復(fù)策略,該策略在碰到第二類異常的時(shí)候?qū)⒆詣又卦?次。executeMethod返回值是一個(gè)整數(shù),表示了執(zhí)行該方法后服務(wù)器返回的狀態(tài)碼,該狀態(tài)碼能表示出該方法執(zhí)行是否成功、需要認(rèn)證或者頁面發(fā)生了跳轉(zhuǎn)(默認(rèn)狀態(tài)下GetMethod的實(shí)例是自動處理跳轉(zhuǎn)的)等。
            //設(shè)置成了默認(rèn)的恢復(fù)策略,在發(fā)生異常時(shí)候?qū)⒆詣又卦?次,在這里你也可以設(shè)置成自定義的恢復(fù)策略
            getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
                		new DefaultHttpMethodRetryHandler()); 
            //執(zhí)行g(shù)etMethod
            int statusCode = client.executeMethod(getMethod);
            if (statusCode != HttpStatus.SC_OK) {
              System.err.println("Method failed: " + getMethod.getStatusLine());
            }
            

          • 在返回的狀態(tài)碼正確后,即可取得內(nèi)容。取得目標(biāo)地址的內(nèi)容有三種方法:第一種,getResponseBody,該方法返回的是目標(biāo)的二進(jìn)制的byte流;第二種,getResponseBodyAsString,這個(gè)方法返回的是String類型,值得注意的是該方法返回的String的編碼是根據(jù)系統(tǒng)默認(rèn)的編碼方式,所以返回的String值可能編碼類型有誤,在本文的"字符編碼"部分中將對此做詳細(xì)介紹;第三種,getResponseBodyAsStream,這個(gè)方法對于目標(biāo)地址中有大量數(shù)據(jù)需要傳輸是最佳的。在這里我們使用了最簡單的getResponseBody方法。
            byte[] responseBody = method.getResponseBody();
            

          • 釋放連接。無論執(zhí)行方法是否成功,都必須釋放連接。
            method.releaseConnection();
            

          • 處理內(nèi)容。在這一步中根據(jù)你的需要處理內(nèi)容,在例子中只是簡單的將內(nèi)容打印到控制臺。
            System.out.println(new String(responseBody));
            

          下面是程序的完整代碼,這些代碼也可在附件中的test.GetSample中找到。


          												
          														package test;
          import java.io.IOException;
          import org.apache.commons.httpclient.*;
          import org.apache.commons.httpclient.methods.GetMethod;
          import org.apache.commons.httpclient.params.HttpMethodParams;
          
          public class GetSample{
            public static void main(String[] args) {
            //構(gòu)造HttpClient的實(shí)例
            HttpClient httpClient = new HttpClient();
            //創(chuàng)建GET方法的實(shí)例
            GetMethod getMethod = new GetMethod("http://www.ibm.com");
            //使用系統(tǒng)提供的默認(rèn)的恢復(fù)策略
            getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
              new DefaultHttpMethodRetryHandler());
            try {
             //執(zhí)行g(shù)etMethod
             int statusCode = httpClient.executeMethod(getMethod);
             if (statusCode != HttpStatus.SC_OK) {
              System.err.println("Method failed: "
                + getMethod.getStatusLine());
             }
             //讀取內(nèi)容 
             byte[] responseBody = getMethod.getResponseBody();
             //處理內(nèi)容
             System.out.println(new String(responseBody));
            } catch (HttpException e) {
             //發(fā)生致命的異常,可能是協(xié)議不對或者返回的內(nèi)容有問題
             System.out.println("Please check your provided http address!");
             e.printStackTrace();
            } catch (IOException e) {
             //發(fā)生網(wǎng)絡(luò)異常
             e.printStackTrace();
            } finally {
             //釋放連接
             getMethod.releaseConnection();
            }
           }
          }
          
          												
          										

          POST方法

          根據(jù)RFC2616,對POST的解釋如下:POST方法用來向目的服務(wù)器發(fā)出請求,要求它接受被附在請求后的實(shí)體,并把它當(dāng)作請求隊(duì)列(Request-Line)中請求URI所指定資源的附加新子項(xiàng)。POST被設(shè)計(jì)成用統(tǒng)一的方法實(shí)現(xiàn)下列功能:

          • 對現(xiàn)有資源的注釋(Annotation of existing resources)
          • 向電子公告欄、新聞組,郵件列表或類似討論組發(fā)送消息
          • 提交數(shù)據(jù)塊,如將表單的結(jié)果提交給數(shù)據(jù)處理過程
          • 通過附加操作來擴(kuò)展數(shù)據(jù)庫

          調(diào)用HttpClient中的PostMethod與GetMethod類似,除了設(shè)置PostMethod的實(shí)例與GetMethod有些不同之外,剩下的步驟都差不多。在下面的例子中,省去了與GetMethod相同的步驟,只說明與上面不同的地方,并以登錄清華大學(xué)BBS為例子進(jìn)行說明。

          • 構(gòu)造PostMethod之前的步驟都相同,與GetMethod一樣,構(gòu)造PostMethod也需要一個(gè)URI參數(shù),在本例中,登錄的地址是http://www.newsmth.net/bbslogin2.php。在創(chuàng)建了PostMethod的實(shí)例之后,需要給method實(shí)例填充表單的值,在BBS的登錄表單中需要有兩個(gè)域,第一個(gè)是用戶名(域名叫id),第二個(gè)是密碼(域名叫passwd)。表單中的域用類NameValuePair來表示,該類的構(gòu)造函數(shù)第一個(gè)參數(shù)是域名,第二參數(shù)是該域的值;將表單所有的值設(shè)置到PostMethod中用方法setRequestBody。另外由于BBS登錄成功后會轉(zhuǎn)向另外一個(gè)頁面,但是HttpClient對于要求接受后繼服務(wù)的請求,比如POST和PUT,不支持自動轉(zhuǎn)發(fā),因此需要自己對頁面轉(zhuǎn)向做處理。具體的頁面轉(zhuǎn)向處理請參見下面的"自動轉(zhuǎn)向"部分。代碼如下:
            String url = "http://www.newsmth.net/bbslogin2.php";
            PostMethod postMethod = new PostMethod(url);
            // 填入各個(gè)表單域的值
            NameValuePair[] data = { new NameValuePair("id", "youUserName"),				
            new NameValuePair("passwd", "yourPwd") };
            // 將表單的值放入postMethod中
            postMethod.setRequestBody(data);
            // 執(zhí)行postMethod
            int statusCode = httpClient.executeMethod(postMethod);
            // HttpClient對于要求接受后繼服務(wù)的請求,象POST和PUT等不能自動處理轉(zhuǎn)發(fā)
            // 301或者302
            if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || 
            statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
                // 從頭中取出轉(zhuǎn)向的地址
                Header locationHeader = postMethod.getResponseHeader("location");
                String location = null;
                if (locationHeader != null) {
                 location = locationHeader.getValue();
                 System.out.println("The page was redirected to:" + location);
                } else {
                 System.err.println("Location field value is null.");
                }
                return;
            }
            

          完整的程序代碼請參見附件中的test.PostSample





          回頁首


          使用HttpClient過程中常見的一些問題

          下面介紹在使用HttpClient過程中常見的一些問題。

          字符編碼

          某目標(biāo)頁的編碼可能出現(xiàn)在兩個(gè)地方,第一個(gè)地方是服務(wù)器返回的http頭中,另外一個(gè)地方是得到的html/xml頁面中。

          • 在http頭的Content-Type字段可能會包含字符編碼信息。例如可能返回的頭會包含這樣子的信息:Content-Type: text/html; charset=UTF-8。這個(gè)頭信息表明該頁的編碼是UTF-8,但是服務(wù)器返回的頭信息未必與內(nèi)容能匹配上。比如對于一些雙字節(jié)語言國家,可能服務(wù)器返回的編碼類型是UTF-8,但真正的內(nèi)容卻不是UTF-8編碼的,因此需要在另外的地方去得到頁面的編碼信息;但是如果服務(wù)器返回的編碼不是UTF-8,而是具體的一些編碼,比如gb2312等,那服務(wù)器返回的可能是正確的編碼信息。通過method對象的getResponseCharSet()方法就可以得到http頭中的編碼信息。
          • 對于象xml或者h(yuǎn)tml這樣的文件,允許作者在頁面中直接指定編碼類型。比如在html中會有<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>這樣的標(biāo)簽;或者在xml中會有<?xml version="1.0" encoding="gb2312"?>這樣的標(biāo)簽,在這些情況下,可能與http頭中返回的編碼信息沖突,需要用戶自己判斷到底那種編碼類型應(yīng)該是真正的編碼。

          自動轉(zhuǎn)向

          根據(jù)RFC2616中對自動轉(zhuǎn)向的定義,主要有兩種:301和302。301表示永久的移走(Moved Permanently),當(dāng)返回的是301,則表示請求的資源已經(jīng)被移到一個(gè)固定的新地方,任何向該地址發(fā)起請求都會被轉(zhuǎn)到新的地址上。302表示暫時(shí)的轉(zhuǎn)向,比如在服務(wù)器端的servlet程序調(diào)用了sendRedirect方法,則在客戶端就會得到一個(gè)302的代碼,這時(shí)服務(wù)器返回的頭信息中l(wèi)ocation的值就是sendRedirect轉(zhuǎn)向的目標(biāo)地址。

          HttpClient支持自動轉(zhuǎn)向處理,但是象POST和PUT方式這種要求接受后繼服務(wù)的請求方式,暫時(shí)不支持自動轉(zhuǎn)向,因此如果碰到POST方式提交后返回的是301或者302的話需要自己處理。就像剛才在POSTMethod中舉的例子:如果想進(jìn)入登錄BBS后的頁面,必須重新發(fā)起登錄的請求,請求的地址可以在頭字段location中得到。不過需要注意的是,有時(shí)候location返回的可能是相對路徑,因此需要對location返回的值做一些處理才可以發(fā)起向新地址的請求。

          另外除了在頭中包含的信息可能使頁面發(fā)生重定向外,在頁面中也有可能會發(fā)生頁面的重定向。引起頁面自動轉(zhuǎn)發(fā)的標(biāo)簽是:<meta http-equiv="refresh" content="5; url=http://www.ibm.com/us">。如果你想在程序中也處理這種情況的話得自己分析頁面來實(shí)現(xiàn)轉(zhuǎn)向。需要注意的是,在上面那個(gè)標(biāo)簽中url的值也可以是一個(gè)相對地址,如果是這樣的話,需要對它做一些處理后才可以轉(zhuǎn)發(fā)。

          處理HTTPS協(xié)議

          HttpClient提供了對SSL的支持,在使用SSL之前必須安裝JSSE。在Sun提供的1.4以后的版本中,JSSE已經(jīng)集成到JDK中,如果你使用的是JDK1.4以前的版本則必須安裝JSSE。JSSE不同的廠家有不同的實(shí)現(xiàn)。下面介紹怎么使用HttpClient來打開Https連接。這里有兩種方法可以打開https連接,第一種就是得到服務(wù)器頒發(fā)的證書,然后導(dǎo)入到本地的keystore中;另外一種辦法就是通過擴(kuò)展HttpClient的類來實(shí)現(xiàn)自動接受證書。

          方法1,取得證書,并導(dǎo)入本地的keystore:

          • 安裝JSSE (如果你使用的JDK版本是1.4或者1.4以上就可以跳過這一步)。本文以IBM的JSSE為例子說明。先到IBM網(wǎng)站上下載JSSE的安裝包。然后解壓開之后將ibmjsse.jar包拷貝到<java-home>\lib\ext\目錄下。
          • 取得并且導(dǎo)入證書。證書可以通過IE來獲得:

            1. 用IE打開需要連接的https網(wǎng)址,會彈出如下對話框:



            2. 單擊"View Certificate",在彈出的對話框中選擇"Details",然后再單擊"Copy to File",根據(jù)提供的向?qū)纱L問網(wǎng)頁的證書文件



            3. 向?qū)У谝徊剑瑲g迎界面,直接單擊"Next",



            4. 向?qū)У诙剑x擇導(dǎo)出的文件格式,默認(rèn),單擊"Next",



            5. 向?qū)У谌剑斎雽?dǎo)出的文件名,輸入后,單擊"Next",



            6. 向?qū)У谒牟剑瑔螕?Finish",完成向?qū)?/p>

            7. 最后彈出一個(gè)對話框,顯示導(dǎo)出成功



          • 用keytool工具把剛才導(dǎo)出的證書倒入本地keystore。Keytool命令在<java-home>\bin\下,打開命令行窗口,并到<java-home>\lib\security\目錄下,運(yùn)行下面的命令:

            																
            																		keytool -import -noprompt -keystore cacerts -storepass changeit -alias yourEntry1 -file your.cer
            
            																
            														

            其中參數(shù)alias后跟的值是當(dāng)前證書在keystore中的唯一標(biāo)識符,但是大小寫不區(qū)分;參數(shù)file后跟的是剛才通過IE導(dǎo)出的證書所在的路徑和文件名;如果你想刪除剛才導(dǎo)入到keystore的證書,可以用命令:

            																
            																		keytool -delete -keystore cacerts -storepass changeit -alias yourEntry1
            
            																
            														

          • 寫程序訪問https地址。如果想測試是否能連上https,只需要稍改一下GetSample例子,把請求的目標(biāo)變成一個(gè)https地址。
            GetMethod getMethod = new GetMethod("https://www.yourdomain.com");
            

            運(yùn)行該程序可能出現(xiàn)的問題:

            1. 拋出異常java.net.SocketException: Algorithm SSL not available。出現(xiàn)這個(gè)異常可能是因?yàn)闆]有加JSSEProvider,如果用的是IBM的JSSE Provider,在程序中加入這樣的一行:

             if(Security.getProvider("com.ibm.jsse.IBMJSSEProvider") == null)
             Security.addProvider(new IBMJSSEProvider());
             

            或者也可以打開<java-home>\lib\security\java.security,在行

            security.provider.1=sun.security.provider.Sun
            security.provider.2=com.ibm.crypto.provider.IBMJCE
            

            后面加入security.provider.3=com.ibm.jsse.IBMJSSEProvider

            2. 拋出異常java.net.SocketException: SSL implementation not available。出現(xiàn)這個(gè)異常可能是你沒有把ibmjsse.jar拷貝到<java-home>\lib\ext\目錄下。

            3. 拋出異常javax.net.ssl.SSLHandshakeException: unknown certificate。出現(xiàn)這個(gè)異常表明你的JSSE應(yīng)該已經(jīng)安裝正確,但是可能因?yàn)槟銢]有把證書導(dǎo)入到當(dāng)前運(yùn)行JRE的keystore中,請按照前面介紹的步驟來導(dǎo)入你的證書。

          方法2,擴(kuò)展HttpClient類實(shí)現(xiàn)自動接受證書

          因?yàn)檫@種方法自動接收所有證書,因此存在一定的安全問題,所以在使用這種方法前請仔細(xì)考慮您的系統(tǒng)的安全需求。具體的步驟如下:

          • 提供一個(gè)自定義的socket factory(test.MySecureProtocolSocketFactory)。這個(gè)自定義的類必須實(shí)現(xiàn)接口org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory,在實(shí)現(xiàn)接口的類中調(diào)用自定義的X509TrustManager(test.MyX509TrustManager),這兩個(gè)類可以在隨本文帶的附件中得到
          • 創(chuàng)建一個(gè)org.apache.commons.httpclient.protocol.Protocol的實(shí)例,指定協(xié)議名稱和默認(rèn)的端口號
            Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);
            

          • 注冊剛才創(chuàng)建的https協(xié)議對象
            Protocol.registerProtocol("https ", myhttps);
            

          • 然后按照普通編程方式打開https的目標(biāo)地址,代碼請參見test.NoCertificationHttpsGetSample

          處理代理服務(wù)器

          HttpClient中使用代理服務(wù)器非常簡單,調(diào)用HttpClient中setProxy方法就可以,方法的第一個(gè)參數(shù)是代理服務(wù)器地址,第二個(gè)參數(shù)是端口號。另外HttpClient也支持SOCKS代理。


          												
          														httpClient.getHostConfiguration().setProxy(hostName,port);
          
          												
          										





          回頁首


          結(jié)論

          從上面的介紹中,可以知道HttpClient對http協(xié)議支持非常好,使用起來很簡單,版本更新快,功能也很強(qiáng)大,具有足夠的靈活性和擴(kuò)展性。對于想在Java應(yīng)用中直接訪問http資源的編程人員來說,HttpClient是一個(gè)不可多得的好工具。





          回頁首


          參考資料

          • Commons logging包含了各種各樣的日志API的實(shí)現(xiàn),讀者可以通過站點(diǎn)http://jakarta.apache.org/commons/logging/得到詳細(xì)的內(nèi)容

          • Commons codec包含了一些一般的解碼/編碼算法。包含了語音編碼、十六進(jìn)制、Base64和URL編碼等,通過http://jakarta.apache.org/commons/codec/可以得到詳細(xì)的內(nèi)容

          • rfc2616是關(guān)于HTTP/1.1的文檔,可以在http://www.faqs.org/rfcs/rfc2616.html上得到詳細(xì)的內(nèi)容,另外rfc1945是關(guān)于HTTP/1.0的文檔,通過http://www.faqs.org/rfcs/rfc1945.html可以得到詳細(xì)內(nèi)容

          • SSL――SSL 是由 Netscape Communications Corporation 于 1994 年開發(fā)的,而 TLS V1.0 是由 Internet Engineering Task Force(IETF)定義的標(biāo)準(zhǔn),它基于 SSL V3.0,并且在使用的加密算法上與其有些許的不同。例如,SSL 使用 Message Authentication Code(MAC)算法來生成完整性校驗(yàn)值,而 TLS 應(yīng)用密鑰的 Hashing for Message Authentication Code(HMAC)算法。

          • IBM JSSE提供了SSL(Secure Sockets Layer)和TLS(Transport Layer Security)的java實(shí)現(xiàn),在http://www-03.ibm.com/servers/eserver/zseries/software/java/jsse.html中可以得到詳細(xì)的信息

          • Keytool是一個(gè)管理密鑰和證書的工具。關(guān)于它詳細(xì)的使用信息可以在http://www.doc.ic.ac.uk/csg/java/1.3.1docs/tooldocs/solaris/keytool.html上得到

          • HTTPClient的主頁是http://jakarta.apache.org/commons/httpclient/,你可以在這里得到關(guān)于HttpClient更加詳細(xì)的信息
          posted @ 2006-11-08 11:21 edsonjava 閱讀(279) | 評論 (0)編輯 收藏
           


          //以下部分為通過AJAX讀取商品信息
          var req;

          function Change_Select()
          {
          ??? var useTypeID=document.getElementById("msgtype1").value;
          ?var flowerTypeID=document.getElementById("msgtype2").value;
          ?var flowerPriceID=document.getElementById("msgtype3").value;
          ?var url="/12580/jsp/ShowProductServlet?msgtype1="+ useTypeID +"&msgtype2="+flowerTypeID+"&msgtype3="+flowerPriceID;
          ??? ?if(window.XMLHttpRequest)
          ??????? {
          ??????????? req=new XMLHttpRequest();
          ??????? }else if(window.ActiveXObject)
          ??????? {
          ??????????? req=new ActiveXObject("Microsoft.XMLHTTP");
          ??????? }
          ???????
          ??????? if(req)
          ??????? {
          ??????????? req.open("GET",url,true);
          ??????????? req.onreadystatechange = callback;
          ??????????? req.send(null);
          ??????? }
          }

          function callback()
          {
          ??? if(req.readyState == 4)
          ??? {
          ??????? if(req.status == 200)
          ??????? {
          ?????????? var dataTableBody=document.getElementById("tbProduct");
          ?????????? dataTableBody.innerHTML=req.responseText;
          ??????? }else{
          ??????????? alert("Not able to retrieve description:"+req.statusText);
          ??????? }
          ??? }
          }

          ?


          //--------------------------------------------
          //以下部分為通過AJAX動態(tài)顯示小窗口內(nèi)容

          function distChange(htmlStr){
          ?distHelp.innerHTML = htmlStr;
          }

          var req1;

          function Change_Select1()
          {?
          ??? var cityID=document.getElementById("stage2").value.substr(0,document.getElementById("stage2").value.indexOf("/"));
          ?var url="/12580/jsp/SelectCityChangeServlet?isFront=1&id="+cityID;
          ??? ?if(window.XMLHttpRequest)
          ??????? {
          ??????????? req1=new XMLHttpRequest();
          ??????? }else if(window.ActiveXObject)
          ??????? {
          ??????????? req1=new ActiveXObject("Microsoft.XMLHTTP");
          ??????? }
          ???????
          ??????? if(req1)
          ??????? {
          ??????????? req1.open("GET",url,true);
          ??????????? req1.onreadystatechange = callback1;
          ??????????? req1.send(null);
          ??????? }
          }

          function callback1()
          {
          ??? if(req1.readyState == 4)
          ??? {
          ??????? if(req1.status == 200)
          ??????? {
          ?????????? var dataTableBody=document.getElementById("distHelp");
          ?????????? dataTableBody.innerHTML=req1.responseText;
          ??????? }else{
          ??????????? alert("Not able to retrieve description:"+req1.statusText);
          ??????? }
          ??? }
          }

          posted @ 2006-10-27 23:55 edsonjava 閱讀(597) | 評論 (0)編輯 收藏
           
          1.用keytool生成server.keystore文件:
          C:\Documents and Settings\new>keytool -genkey -alias tc-ssl -keyalg RSA -keystor
          e c:\server.keystore -validity 3650

          生成完后放入C:\jboss-3.2.6\server\default\conf中。

          2。配置server.xml文件
          <!-- SSL/TLS Connector configuration using the admin devl guide keystore-->
          ??????<Connector port="8443" address="${jboss.bind.address}"
          ?????????? maxThreads="100" minSpareThreads="5" maxSpareThreads="15"
          ?????????? scheme="https" secure="true" clientAuth="false"
          ?????????? keystoreFile="${jboss.server.home.dir}/conf/server.keystore"
          ?????????? keystorePass="111111" sslProtocol = "TLS" />
          3。訪問https://localhost:8443/jmx-console/index.jsp,可以了。
          同時(shí)http://localhost:8080/jmx-console/index.jsp也可以訪問,
          如果將http轉(zhuǎn)向到https: 修改WEB應(yīng)用的web.xml
          =========web.xml==================
          <security-constraint>
          ???? <web-resource-collection>
          ?????? <web-resource-name>HtmlAdaptor</web-resource-name>
          ?????? <description>An example security config that only allows users with the
          ???????? role JBossAdmin to access the HTML JMX console web application
          ?????? </description>
          ?????? <url-pattern>/</url-pattern>
          ?????? <!-- <http-method>GET</http-method>
          ?????? <http-method>POST</http-method> -->
          ???? </web-resource-collection>
          ???? <!--<auth-constraint>
          ?????? <role-name>JBossAdmin</role-name>
          ???? </auth-constraint> -->
          ???? <user-data-constraint>
          ????????????<description>Protection should be CONFIDENTIAL</description>
          ????????????<transport-guarantee>CONFIDENTIAL</transport-guarantee>
          ????????</user-data-constraint>
          ?? </security-constraint>
          posted @ 2006-07-20 23:15 edsonjava 閱讀(868) | 評論 (0)編輯 收藏
           
               摘要: 這些天稍微玩了一下 Axis ,以前做 WebServices 都使用 JBuilder ,感覺做 WebServices 如此簡單,現(xiàn)在自己手動做,原來也是如此簡單。高興之余寫一個(gè)簡單的初學(xué)手冊,就算是學(xué)習(xí)成果吧。當(dāng)然對 Axis ...  閱讀全文
          posted @ 2006-07-14 17:23 edsonjava 閱讀(256) | 評論 (0)編輯 收藏
          僅列出標(biāo)題
          共7頁: 上一頁 1 2 3 4 5 6 7 下一頁 
           
          主站蜘蛛池模板: 新化县| 东兴市| 高淳县| 濉溪县| 安阳县| 海宁市| 阳高县| 汉中市| 岱山县| 开化县| 南靖县| 象山县| 西乌珠穆沁旗| 三台县| 平远县| 渝中区| 甘洛县| 云梦县| 张家港市| 上蔡县| 麻阳| 枣庄市| 洪泽县| 周至县| 阿城市| 得荣县| 木兰县| 普格县| 宁安市| 浦北县| 商都县| 郑州市| 望谟县| 洛南县| 黄骅市| 乌兰察布市| 白玉县| 福贡县| 阿坝| 中超| 墨竹工卡县|