<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小菜毛毛技術分享

    與大家共同成長

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      164 Posts :: 141 Stories :: 94 Comments :: 0 Trackbacks

    #

    前不久做的一個筆記本BIOS相關的項目,操作對BOIS文件里面的內容時進行較多的位運算,于是順手整理了一份位運算相關的內容。
       Java 定義的位運算(bitwise operators )直接對整數類型的位進行操作,這些整數類型包括long,int,short,char,and byte 。
       所有的整數類型(除了char 類型之外)都是有符號的整數。這意味著他們既能表示正數,又能表示負數。Java 使用采用補碼來表示負數。
       為什么采用補碼嗎?這是考慮到零的交叉(zero crossing )問題。
       原碼:
       將最高位作為符號位(以0代表正,1代表負),其余各位代表數值本身的絕對值(以二進制表示)。這個時候有一個問題:表示0的時候正0和負0表示并不一 樣,所以在計算機中沒有采用原碼的表示形式。
       反碼:
       一個數如果為正,則它的反碼與原碼相同;一個數如果為負,則符號位為1,其余各位是對原碼取反。問題和上面一樣的。所以,計算機中也沒有采用反碼來表示數 字。
       補碼:
       一個數如果為正,則它的原碼、反碼、補碼相同;一個數如果為負,則符號位為1,其余各位是對原碼取反,然后再加1。也就是通過將與其對應的正數的二進制代 碼取反(即將1變成0,將0變成1),然后對其結果加1。例如,-42就是通過將42的二進制代碼的各個位取反,即對00101010 取反得到11010101 ,然后再加1,得到11010110 ,即-42 。要對一個負數解碼,首先對其所有的位取反,然后加1。例如-42,或11010110 取反后為00101001 ,或41,然后加1,這樣就得到了42。
       在計算機中,如果我們用1個字節表示一個數,一個字節有8位,超過8位就進1,在內存中情況為:1 00000000。進位1被丟棄。這種情況,我們叫溢出。在計算機中,假定byte 類型的值零為0000 0000,反碼為1111 1111 補碼為1 0000 0000,在計算-0的補碼的時候因為溢出,導致-0和+0是一樣的表示,所以計算機中采用補碼的形式表示數字。
    數的最大值和最小值:由于最高位為符號位,所以最大值和最小值時要去掉最高位。如一個byte為8位.最大值為0111 1111 ,即 (2的7次方) -1 = 127.最小值為1000 0000,即-( 2的7次方) =-128。char為無符號數,沒有符號位,所以最小值為0,最大值為1111 1111 1111 1111 ,即(2的16次方) -1。

    移位運算符
    包括:
    “>> 右移,高位補符號位”;
    “>>> 無符號右移,高位補0”;
    “<< 左移”;

    例子:
    -5>>3=-1
    1111 1111 1111 1111 1111 1111 1111 1011
    1111 1111 1111 1111 1111 1111 1111 1111
    其結果與 Math.floor((double)-5/(2*2*2)) 完全相同。

    -5<<3=-40
    1111 1111 1111 1111 1111 1111 1111 1011
    1111 1111 1111 1111 1111 1111 1101 1000
    其結果與 -5*2*2*2 完全相同。

    5>>3=0
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0000 0000
    其結果與 5/(2*2*2) 完全相同。

    5<<3=40
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0010 1000
    其結果與 5*2*2*2 完全相同。

    -5>>>3=536870911
    1111 1111 1111 1111 1111 1111 1111 1011
    0001 1111 1111 1111 1111 1111 1111 1111

    無論正數、負數,它們的右移、左移、無符號右移 32 位都是其本身,比如 -5<<32=-5、-5>>32=-5、-5>>>32=-5。
    一個有趣的現象是,把 1 左移 31 位再右移 31 位,其結果為 -1。
    0000 0000 0000 0000 0000 0000 0000 0001
    1000 0000 0000 0000 0000 0000 0000 0000
    1111 1111 1111 1111 1111 1111 1111 1111

    位邏輯運算符
    包括:
    & 與;
    | 或;
    ~ 非(也叫做求反);
    ^ 異或

    “& 與”、“| 或”、“~ 非”是基本邏輯運算,由此可以演變出“與非”、“或非”、“與或非”復合邏輯運算。“^ 異或”是一種特殊的邏輯運算,對它求反可以得到“同或”,所以“同或”邏輯也叫“異或非”邏輯。

    例子:
    5&3=1
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0000 0011
    0000 0000 0000 0000 0000 0000 0000 0001

    -5&3=1
    1111 1111 1111 1111 1111 1111 1111 1011
    0000 0000 0000 0000 0000 0000 0000 0011
    0000 0000 0000 0000 0000 0000 0000 0011

    5|3=7
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0000 0011
    0000 0000 0000 0000 0000 0000 0000 0111

    -5|3=-5
    1111 1111 1111 1111 1111 1111 1111 1011
    0000 0000 0000 0000 0000 0000 0000 0011
    1111 1111 1111 1111 1111 1111 1111 1011

    ~5=-6
    0000 0000 0000 0000 0000 0000 0000 0101
    1111 1111 1111 1111 1111 1111 1111 1010

    ~-5=4
    1111 1111 1111 1111 1111 1111 1111 1011
    0000 0000 0000 0000 0000 0000 0000 0100

    5^3=6
    0000 0000 0000 0000 0000 0000 0000 0101
    0000 0000 0000 0000 0000 0000 0000 0011
    0000 0000 0000 0000 0000 0000 0000 0110

    -5^3=-8
    1111 1111 1111 1111 1111 1111 1111 1011
    0000 0000 0000 0000 0000 0000 0000 0011
    1111 1111 1111 1111 1111 1111 1111 1000

    參考:
    http://blog.csdn.net/zdmilan/archive/2005/10/30/519634.aspx
    posted @ 2010-05-18 12:02 小菜毛毛 閱讀(360) | 評論 (0)編輯 收藏

    應用程序服務器通過各種協議,可以包括HTTP,把商業邏輯暴露給客戶端應用程序。Web服務器主要是處理向瀏覽器發送HTML以供瀏覽,而應用程序服務 器提供訪問商業邏輯的途徑以供客戶端應用程序使用。應用程序使用此商業邏輯就象你調用對象的一個方法一樣。
    通俗的講,Web服務器傳送(serves)頁面使瀏覽器可以瀏覽,然而應用程序服務器提供的是客戶端應用程序可以調用(call)的方法 (methods)。確切一點,你可以說:Web服務器專門處理HTTP請求(request),但是應用程序服務器是通過很多協議來為應用程序提供 (serves)商業邏輯(business logic)。

    下面讓我們來細細道來:

    Web服務器 (Web Server)

    Web服務器可以解析(handles)HTTP協議。當Web服務器接收到一個HTTP請求(request),會返回一個HTTP響應 (response),例如送回一個HTML頁面。為了處理一個請求(request),Web服務器可以響應(response)一個靜態頁面或圖片, 進行頁面跳轉(redirect),或者把動態響應(dynamic response)的產生委托(delegate)給一些其它的程序例如CGI腳本,JSP(JavaServer Pages)腳本,servlets,ASP(Active Server Pages)腳本,服務器端(server-side)JavaScript,或者一些其它的服務器端(server-side)技術。無論它們(譯者 注:腳本)的目的如何,這些服務器端(server-side)的程序通常產生一個HTML的響應(response)來讓瀏覽器可以瀏覽。

    要知道,Web服務器的代理模型(delegation model)非常簡單。當一個請求(request)被送到Web服務器里來時,它只單純的把請求(request)傳遞給可以很好的處理請求 (request)的程序(譯者注:服務器端腳本)。Web服務器僅僅提供一個可以執行服務器端(server-side)程序和返回(程序所產生的)響 應(response)的環境,而不會超出職能范圍。服務器端(server-side)程序通常具有事務處理(transaction processing),數據庫連接(database connectivity)和消息(messaging)等功能。

    雖然 Web服務器不支持事務處理或數據庫連接池,但它可以配置(employ)各種策略(strategies)來實現容錯性(fault tolerance)和可擴展性(scalability),例如負載平衡(load balancing),緩沖(caching)。集群特征(clustering—features)經常被誤認為僅僅是應用程序服務器專有的特征。

    應用程序服務器(The Application Server)
    根據我們的定義,作為應用程序服務器, 它通過各種協議,可以包括HTTP,把商業邏輯暴露給(expose)客戶端應用程序。Web服務器主要是處理向瀏覽器發送HTML以供瀏覽,而應用程序 服務器提供訪問商業邏輯的途徑以供客戶端應用程序使用。應用程序使用此商業邏輯就象你調用對象的一個方法(或過程語言中的一個函數)一樣。

    應用程序服務器的客戶端(包含有圖形用戶界面(GUI)的)可能會運行在一臺PC、一個Web服務器或者甚至是其它的應用程序服務器上。在應用程序服務 器與其客戶端之間來回穿梭(traveling)的信息不僅僅局限于簡單的顯示標記。相反,這種信息就是程序邏輯(program logic)。 正是由于這種邏輯取得了(takes)數據和方法調用(calls)的形式而不是靜態HTML,所以客戶端才可以隨心所欲的使用這種被暴露的商業邏輯。

    在大多數情形下,應用程序服務器是通過組件(component)的應用程序接口(API)把商業邏輯暴露(expose)(給客戶端應用程序)的,例 如基于J2EE(Java 2 Platform, Enterprise Edition)應用程序服務器的EJB(Enterprise JavaBean)組件模型。此外,應用程序服務器可以管理自己的資源,例如看大門的工作(gate-keeping duties)包括安全(security),事務處理(transaction processing),資源池(resource pooling), 和消息(messaging)。就象Web服務器一樣,應用程序服務器配置了多種可擴展(scalability)和容錯(fault tolerance)技術。

    一個例子
    例如,設想一個在線商店(網站)提供實時定價(real-time pricing)和有效性(availability)信息。這個站點(site)很可能會提供一個表單(form)讓你來選擇產品。當你提交查詢 (query)后,網站會進行查找(lookup)并把結果內嵌在HTML頁面中返回。網站可以有很多種方式來實現這種功能。我要介紹一個不使用應用程序 服務器的情景和一個使用應用程序服務器的情景。觀察一下這兩中情景的不同會有助于你了解應用程序服務器的功能。

    情景 1:不帶應用程序服務器的Web服務器

    在此種情景下,一個Web服務器獨立提供在線商店的功能。Web服務器獲 得你的請求(request),然后發送給服務器端(server-side)可以處理請求(request)的程序。此程序從數據庫或文本文件 (flat file,譯者注:flat file是指沒有特殊格式的非二進制的文件,如properties和XML文件等)中查找定價信息。一旦找到,服務器端(server-side)程序 把結果信息表示成(formulate)HTML形式,最后Web服務器把會它發送到你的Web瀏覽器。

    簡而言之,Web服務器只是簡 單的通過響應(response)HTML頁面來處理HTTP請求(request)。

    情景2:帶應用程序服務器的 Web服務器

    情景2和情景1相同的是Web服務器還是把響應(response)的產生委托 (delegates)給腳本(譯者注:服務器端(server-side)程序)。然而,你可以把查找定價的商業邏輯(business logic)放到應用程序服務器上。由于這種變化,此腳本只是簡單的調用應用程序服務器的查找服務(lookup service),而不是已經知道如何查找數據然后表示為(formulate)一個響應(response)。 這時當該腳本程序產生HTML響應(response)時就可以使用該服務的返回結果了。

    在此情景中,應用程序服務器提供 (serves)了用于查詢產品的定價信息的商業邏輯。(服務器的)這種功能(functionality)沒有指出有關顯示和客戶端如何使用此信息的細 節,相反客戶端和應用程序服務器只是來回傳送數據。當有客戶端調用應用程序服務器的查找服務(lookup service)時,此服務只是簡單的查找并返回結果給客戶端。

    通過從響應產生(response-generating)HTML的 代碼中分離出來,在應用程序之中該定價(查找)邏輯的可重用性更強了。其他的客戶端,例如收款機,也可以調用同樣的服務(service)來作為一個店員 給客戶結帳。相反,在情景1中的定價查找服務是不可重用的因為信息內嵌在HTML頁中了。

    總而言之,在情景2的模型中,在Web服務器 通過回應HTML頁面來處理HTTP請求(request),而應用程序服務器則是通過處理定價和有效性(availability)請求 (request)來提供應用程序邏輯的。

    警告(Caveats)
    現在,XML Web Services已經使應用程序服務器和Web服務器的界線混淆了。通過傳送一個XML有效載荷(payload)給服務器,Web服務器現在可以處理數 據和響應(response)的能力與以前的應用程序服務器同樣多了。

    另外,現在大多數應用程序服務器也包含了Web服務器,這就意味 著可以把Web服務器當作是應用程序服務器的一個子集(subset)。雖然應用程序服務器包含了Web服務器的功能,但是開發者很少把應用程序服務器部 署(deploy)成這種功能(capacity)(譯者注:這種功能是指既有應用程序服務器的功能又有Web服務器的功能)。相反,如果需要,他們通常 會把Web服務器獨立配置,和應用程序服務器一前一后。這種功能的分離有助于提高性能(簡單的Web請求(request)就不會影響應用程序服務器 了),分開配置(專門的Web服務器,集群(clustering)等等),而且給最佳產品的選取留有余地。


    posted @ 2010-05-14 10:19 小菜毛毛 閱讀(225) | 評論 (0)編輯 收藏

    HTTPS(Secure Hypertext Transfer Protocol)安全超文本傳輸協議
    它是一個安全通信通道,它基于HTTP開發,用于在客戶計算機和服務器之間交換信息。它使用安全套接字層(SSL)進行信息交換,簡單來說它是HTTP的 安全版。
    它是由Netscape開發并內置于其瀏覽器中,用于對數據進行壓縮和解壓操作,并返回網絡上傳送回的結果。HTTPS實際上應用了Netscape的安 全全套接字層(SSL)作為HTTP應用層的子層。(HTTPS使用端口443,而不是象HTTP那樣使用端口80來和TCP/IP進行通信。)SSL使 用40 位關鍵字作為RC4流加密算法,這對于商業信息的加密是合適的。HTTPS和SSL支持使用X.509數字認證,如果需要的話用戶可以確認發送者是誰。
    HTTPS和HTTP的區別:
    https協議需要到ca申請證書,一般免費證書很少,需要交費。
    http是超文本傳輸協議,信息是明文傳輸,https 則是具有安全性的ssl加密傳輸協議
    http和https使用的是完全不同的連接方式用的端口也不一樣,前者是80,后者是443。
    http的連接很簡單,是無狀態的
    HTTPS協議是由SSL+HTTP協議構建的可進行加密傳輸、身份認證的網絡協議 要比http協議安全
    HTTPS解決的問題:
    1 . 信任主機的問題. 采用https 的server 必須從CA 申請一個用于證明服務器用途類型的證書. 改證書只有用于對應的server 的時候,客戶度才信任次主機. 所以目前所有的銀行系統網站,關鍵部分應用都是https 的. 客戶通過信任該證書,從而信任了該主機. 其實這樣做效率很低,但是銀行更側重安全. 這一點對我們沒有任何意義,我們的server ,采用的證書不管自己issue 還是從公眾的地方issue, 客戶端都是自己人,所以我們也就肯定信任該server.
    2 . 通訊過程中的數據的泄密和被竄改
    1. 一般意義上的https, 就是 server 有一個證書.
    a) 主要目的是保證server 就是他聲稱的server. 這個跟第一點一樣.
    b) 服務端和客戶端之間的所有通訊,都是加密的.
    i. 具體講,是客戶端產生一個對稱的密鑰,通過server 的證書來交換密鑰. 一般意義上的握手過程.
    ii. 加下來所有的信息往來就都是加密的. 第三方即使截獲,也沒有任何意義.因為他沒有密鑰. 當然竄改也就沒有什么意義了.
    2. 少許對客戶端有要求的情況下,會要求客戶端也必須有一個證書.
    a) 這里客戶端證書,其實就類似表示個人信息的時候,除了用戶名/密碼, 還有一個CA 認證過的身份. 應為個人證書一般來說上別人無法模擬的,所有這樣能夠更深的確認自己的身份.
    b) 目前少數個人銀行的專業版是這種做法,具體證書可能是拿U盤作為一個備份的載體.
    HTTPS 一定是繁瑣的.
    a) 本來簡單的http協議,一個get一個response. 由于https 要還密鑰和確認加密算法的需要.單握手就需要6/7 個往返.
    i. 任何應用中,過多的round trip 肯定影響性能.
    b) 接下來才是具體的http協議,每一次響應或者請求, 都要求客戶端和服務端對會話的內容做加密/解密.
    i. 盡管對稱加密/解密效率比較高,可是仍然要消耗過多的CPU,為此有專門的SSL 芯片. 如果CPU 信能比較低的話,肯定會降低性能,從而不能serve 更多的請求.
    ii. 加密后數據量的影響. 所以,才會出現那么多的安全認證提示
    posted @ 2010-05-13 09:37 小菜毛毛 閱讀(286) | 評論 (0)編輯 收藏

    早早就聽說過開發方向的筆試面試都是以算法和數據結構這些基礎為主,我自恃著那么一丁點項目經驗,一直沒放在心上。

    連日下來的筆試徹底印證了師兄們的話,筆試基本不過。最可惜的是淘寶,筆試中發揮不錯終于能進一面,一開始聊家常聊框架聊開源技術還聊得不錯,突然 間,連續問了三個問題:

    1.多線程訪問hashtable和hashmap有什么不一樣?我只答出線程安全不一樣,具體怎么不一樣就有一句每一句了(回來google一 下,這種java基礎還真TM簡單,枉稱精通java了)

    2.平衡二叉樹查找算法的復雜度?再次雷響,隨便蒙了個歸并排序的復雜度給他。

    3.對于100W條數據的排序和查找有什么效率高的方式?完了,結結巴巴的說一通,最后自認不會……

    原本以為技術面會比筆試好過的,回學校的路上我淚流滿面啊我。這些都不是RP問題了,鐵了心惡補數據結構……

    Java線 程安全同步解決方案 

    1、 問題描述:

      如果一個資源或對象可能被多個線程同時訪問,它就是一個共享資源;例如 類的成員變量,包括類變量和實例變量,再比如對一個文件進行寫操作等。一般情況下,對共享資源的訪問需要考慮線程安全的問題。

      如果一個對象的完整生命周期只在一個線程內,則不需要考慮線程安全,例 如一個局部變量。下面為一個示例代碼:

    1. public class C1 {
    2. public static java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
    3. //其他代碼
    4. }

      假如在一個JSP中這樣的去調用:

    1. <a.jsp>:
    2. <%
    3. Java.util.Date date = C1.sdf.parse(“2003-4-15”);
    4. %>

      則這樣的代碼不是線程安全的。因為java.text.SimpleDateFormat 不是線程安全的,a.jsp中的代碼將會有若干個線程同時執行,而都訪問的是同一個線程不安全的對象,這樣就不是一個線程安全的代碼。正確的寫法應該如 下:

    1. <a.jsp>:
    2. <%
    3. java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
    4. Java.util.Date date = sdf.parse(“2003-4-15”);
    5. %>

    2、 原因分析:

      此時,sdf對象從創建到銷毀都位于一個方法中,相當于一個局部變量,不是一個共享資源,因此則沒有線程不安全的問題。

    3、 解決方法或過程:

    1) 如果對象是immutable,則是線程安全的,例如:String,可以放心使用。
    2) 如果對象是線程安全的,則放心使用
    3) 有 條件線程安全,對于Vector和Hashtable一般情況下是線程安全的,但是對于某些特殊情況,需要通過額外的synchronized保證線程安 全。
    4) 使用synchronized關鍵字;

      對于上例中可以改寫jsp代碼,在sdf上進行同步,而不需要每次創建一個新的對象來保證線程安全,代碼如下:

    1. <%
    2. synchronized(C1.sdf){
    3. Java.util.Date date = C1.sdf.parse(“2003-4-15”);
    4. }
    5. %>

      這種寫法是在一個對象級別上進行同步,也就是說任何時候,對于這個對象,最多只能有一個線程在執行同步方法。

      另外一種寫法是在Class級別上進行同步,寫法如下:

    1. public class C1 {
    2. public static java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
    3. public void method(){
    4. synchronized(C1.class){
    5. //synchronized code
    6. }
    7. }
    8. }

      這種寫法表示無論C1有多少個實例,在任何一個時間點,最多只能有一個線程和一個實例進入同步塊中。這種同步會比較大的影響性能。

      5) 有些對象不能在多線程間共享,則只能在方法內部使用,或者只在一個線程內部使用。

    synchronized詳解

    Java對多線程的支持與同步機制深受大家的喜愛,似乎看起來使用了synchronized關鍵字就可以輕松地解決多線程共享數據同步問題。到底如何?――還得對synchronized關鍵字的作用進行深入了解才可定論。

    總的說來,synchronized關鍵字可以作為函數的修飾符,也可作為函數內的語句,也就是平時說的同步方法和同步語句塊。如果再細的分類,synchronized可作用于instance變量、object reference(對象引用)、static函數和class literals(類名稱字面常量)身上。

    在進一步闡述之前,我們需要明確幾點:

    A.無論synchronized關鍵字加在方法上還是對象上,它取得的鎖都是對象,而不是把一段代碼或函數當作鎖――而且同步方法很可能還會被其他線程的對象訪問。

    B.每個對象只有一個鎖(lock)與之相關聯。

    C.實現同步是要很大的系統開銷作為代價的,甚至可能 造成死鎖,所以盡量避免無謂的同步控制。

    接著來討論synchronized

    用到不同地方對代碼產生的影響:

    假設P1P2是同一個類的不同對象,這個類中定義了以下幾種情況的同步塊或同步方法,P1P2就都可以調用它們。

    1. synchronized當作函數修飾符時,示例代碼如下:

    Public synchronized void methodAAA()

    {

    //….

    }

    這也就是同步方法,那這時synchronized鎖定的是哪個對象呢?它鎖定的是調用這個同步方法對象。也就是說,當一個對象P1在不 同的線程中執行這個同步方法時,它們之間會形成互斥,達到同步的效果。但是這個對象所屬的Class所 產生的另一對象P2卻可以任意調用這個被加了synchronized關鍵字的方法。

    上邊的示例代碼等同于如下代碼:

    public void methodAAA()

    {

    synchronized (this)      // (1)

    {

           //…..

    }

    }

     (1)處 的this指的是什么呢?它指的就是調用這個方法的對象,如P1。可見 同步方法實質是將synchronized作用于object reference。――那個拿到了P1對象 鎖的線程,才可以調用P1的同步方法,而對P2而 言,P1這個鎖與它毫不相干,程序也可能在這種情形下擺脫同步機制的控制,造成數據混亂:(

    2.同步塊,示例代碼如下:

               public void method3(SomeObject so)

                  {

                         synchronized(so)

    {

           //…..

    }

    }

    這時,鎖就是so這個對象,誰拿到這個鎖誰就可以運行它所控制的那段代碼。當有一個明確的對象作為鎖時,就可以這樣寫程序,但當沒有明確的對象作為 鎖,只是想讓一段代碼同步時,可以創建一個特殊的instance變量(它得是一個對象)來充當鎖:

    class Foo implements Runnable

    {

           private byte[] lock = new byte[0]; // 特殊的instance變量

        Public void methodA()

    {

           synchronized(lock) { //… }

    }

    //…..

    }

    注:零長度的byte數 組對象創建起來將比任何對象都經濟――查看編譯后的字節碼:生成零長度的byte[]對 象只需3條操作碼,而Object lock = new Object()則 需要7行操作碼。

    3.將synchronized作用于static 函數,示例代碼如下:

          Class Foo

    {

    public synchronized static void methodAAA()   // 同步的static 函數

    {

    //….

    }

    public void methodBBB()

    {

           synchronized(Foo.class)   // class literal(類名稱字面常量)

    }

           }

       代碼中的methodBBB()方法是把class literal作為鎖的情況,它和同步的static函 數產生的效果是一樣的,取得的鎖很特別,是當前調用這個方法的對象所屬的類(Class, 而不再是由這個Class產生的某個具體對象了)。

    記得在《Effective Java》一書中看到過將 Foo.class P1.getClass()用于作同步鎖還不一樣,不能用P1.getClass()來達到鎖這個Class的目的。P1指的是由Foo類產生的對象。

    可以推斷:如果一個類中定義了一個synchronizedstatic函數A,也定 義了一個synchronized instance函數B,那么這個類的同一對象Obj在多線程中分別訪問AB兩個方法時,不會構成同步,因為它們的鎖都不一樣。A方法的鎖 是Obj這個對象,而B的鎖是Obj所屬的那個Class

    小結如下:

    搞清楚synchronized鎖定的是哪個對象,就能幫助我們設計更安全的多線程程序。

    還有一些技巧可以讓我們對共享資源的同步訪問更加安全:

    1. 定義private instance變量+它的 get方法,而不要定義public/protectedinstance變量。如果將變量定義為public,對象在外界可以繞過同步方法的控制而 直接取得它,并改動它。這也是JavaBean的標準實現方式之一。

    2. 如果instance變量是一個對象,如數組或ArrayList什么的,那上述方法仍然不安全, 因為當外界對象通過get方法拿到這個instance對象的引用后,又將其指向另一個對象,那么這個private變量也就變了,豈不是很危險。這個時候就需要將get方法 也加上synchronized同步,并且,只返回這個private對象的clone()――這樣,調用端得到的就是對象副本的引用了。



    posted @ 2010-05-11 09:49 小菜毛毛 閱讀(915) | 評論 (0)編輯 收藏

    字符,字節和編碼

    轉載自:http://www.regexlab.com/zh/encoding.htm

    級別:中級

    摘要:本文介紹了字符與編碼的發展過程,相關概念的正確理解。舉例說明了一些實際應用中,編碼的實現方法。然后,本文 講述了通常對字符與編碼的幾種誤解,由于這些誤解而導致亂碼產生的原因,以及消除亂碼的辦法。本文的內容涵蓋了“中文問題”,“亂碼問題”。

    掌握編碼問題的關鍵是正確地理解相關概念,編碼所涉及的技術其實是很簡單的。因此,閱讀本文時需要慢讀多想,多思考。

    引言

    “字符與編碼”是一個被經常討論的話題。即使這樣,時常出現的亂碼仍然困擾著大家。雖然我們有很多的辦法可以用來消除亂 碼,但我們并不一定理解這些辦法的內在原理。而有的亂碼產生的原因,實際上由于底層代碼本身有問題所導致的。因此,不僅是初學者會對字符編碼感到模糊,有 的底層開發人員同樣對字符編碼缺乏準確的理解。

    回頁首

    1. 編碼問題的由來,相關概念的理解

    1.1 字符與編碼的發展

    從計算機對多國語言的支持角度看,大致可以分為三個階段:

    系統內碼 說明 系統
    階段一 ASCII 計算機剛開始只支持英語,其它語言不能夠在計算機上存儲和顯示。 英文 DOS
    階段二 ANSI編碼
    (本地化)
    為使計算機支持更多語言,通常使用 0x80~0xFF 范圍的 2 個字節來表示 1 個字符。比如:漢字 '中' 在中文操作系統中,使用 [0xD6,0xD0] 這兩個字節存儲。

    不同的國家和地區制定了不同的標準,由此產生了 GB2312, BIG5, JIS 等各自的編碼標準。這些使用 2 個字節來代表一個字符的各種漢字延伸編碼方式,稱為 ANSI 編碼。在簡體中文系統下,ANSI 編碼代表 GB2312 編碼,在日文操作系統下,ANSI 編碼代表 JIS 編碼。

    不同 ANSI 編碼之間互不兼容,當信息在國際間交流時,無法將屬于兩種語言的文字,存儲在同一段 ANSI 編碼的文本中。
    中文 DOS,中文 Windows 95/98,日文 Windows 95/98
    階段三 UNICODE
    (國際化)
    為了使國際間信息交流更加方便,國際組織制定了 UNICODE 字符集, 為各種語言中的每一個字符設定了統一并且唯一的數字編號,以滿足跨語言、跨平臺進行文本轉換、處理的要求。 Windows NT/2000/XP,Linux,Java

    字符串在內存中的存放方法:

    在 ASCII 階段,單字節字符串使用一個字節存放一個字符(SBCS)。比如,"Bob123" 在內存中為:

    42 6F 62 31 32 33 00
    B o b 1 2 3 "0

    在使用 ANSI 編碼支持多種語言階段,每個字符使用一個字節或多個字節來表示(MBCS),因此,這種方式存放的字符也被稱作多字節字符。比如,"中文 123" 在中文 Windows 95 內存中為7個字節,每個漢字占2個字節,每個英文和數字字符占1個字節:

    D6 D0 CE C4 31 32 33 00
    1 2 3 "0

    在 UNICODE 被采用之后,計算機存放字符串時,改為存放每個字符在 UNICODE 字符集中的序號。目前計算機一般使用 2 個字節(16 位)來存放一個序號(DBCS),因此,這種方式存放的字符也被稱作寬字節字符。 比如,字符串 "中文123" 在 Windows 2000 下,內存中實際存放的是 5 個序號:

    2D 4E 87 65 31 00 32 00 33 00 00 00      ← 在 x86 CPU 中,低字節在前
    1 2 3 "0

    一共占 10 個字節。

    回頁首

    1.2 字符,字節,字符串

    理解編碼的關鍵,是要把字符的概念和字節的概念理解準確。這兩個概念容易混淆,我們在此做一下區分:

    概念描述 舉例
    字符 人們使用的記號,抽象意義上的一個符號。 '1', '中', 'a', '$', '¥', ……
    字節 計算機中存儲數據的單元,一個8位的二進制數,是一個很具體的存儲空間。 0x01, 0x45, 0xFA, ……
    ANSI
    字符串
    在內存中,如果“字符”是以 ANSI 編碼形式存在的,一個字符 可能使用一個字節或多個字節來表示,那么我們稱這種字符串為 ANSI 字符串或者多字節字符串 "中文123"
    (占7字節)
    UNICODE
    字符串
    在內存中,如果“字符”是以在 UNICODE 中的序號存在的,那么我們稱這種字符串為 UNICODE 字符串或者寬字節字符串 L"中文123"
    (占10字節)

    由于不同 ANSI 編碼所規定的標準是不相同的,因此,對于一個給定的多字節字符串,我們必須知道它采用 的是哪一種編碼規則,才能夠知道它包含了哪些“字符”。而對于 UNICODE 字符串來說,不管在什么環境下,它所代表的“字符”內容總 是不變的。

    回頁首

    1.3 字符集與編碼

    各個國家和地區所制定的不同 ANSI 編碼標準中,都只規定了各自語言所需的“字符”。比如:漢字標準(GB2312)中沒有規定韓國語字符怎樣存儲。這些 ANSI 編碼標準所規定的內容包含兩層含義:

    1. 使用哪些字符。也就是說哪些漢字,字母和符號會被收入標準中。所包含“字符”的集合就叫做“字符集”。
    2. 規定每個“字符”分別用一個字節還是多個字節存儲,用哪些字節來存儲,這個規定就叫做“編碼”。

    各個國家和地區在制定編碼標準的時候,“字符的集合”和“編碼”一般都是同時制定的。因此,平常我們所說的“字符集”,比 如:GB2312, GBK, JIS 等,除了有“字符的集合”這層含義外,同時也包含了“編碼”的含義。

    UNICODE 字符集”包含了各種語言中使用到的所有“字符”。用來給 UNICODE 字符集編碼的標準有很多種,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等。

    回頁首

    1.4 常用的編碼簡介

    簡單介紹一下常用的編碼規則,為后邊的章節做一個準備。在這里,我們根據編碼規則的特點,把所有的編碼分成三類:

    分類 編碼標準 說明
    單字節字符編碼 ISO-8859-1 最簡單的編碼規則,每一個字節直接作為一個 UNICODE 字符。比如,[0xD6, 0xD0] 這兩個字節,通過 iso-8859-1 轉化為字符串時,將直接得到 [0x00D6, 0x00D0] 兩個 UNICODE 字符,即 "ÖÐ"。

    反之,將 UNICODE 字符串通過 iso-8859-1 轉化為字節串時,只能正常轉化 0~255 范圍的字符。
    ANSI 編碼 GB2312,
    BIG5,
    Shift_JIS,
    ISO-8859-2 ……
    把 UNICODE 字符串通過 ANSI 編碼轉化為“字節串”時,根據各自編碼的規定,一個 UNICODE 字符可能轉化成一個字節或多個字節。

    反之,將字節串轉化成字符串時,也可能多個字節轉化成一個字符。比如,[0xD6, 0xD0] 這兩個字節,通過 GB2312 轉化為字符串時,將得到 [0x4E2D] 一個字符,即 '中' 字。

    “ANSI 編碼”的特點:
    1. 這些“ANSI 編碼標準”都只能處理各自語言范圍之內的 UNICODE 字符。
    2. “UNICODE 字符”與“轉換出來的字節”之間的關系是人為規定的。
    UNICODE 編碼 UTF-8,
    UTF-16, UnicodeBig ……
    與“ANSI 編碼”類似的,把字符串通過 UNICODE 編碼轉化成“字節串”時,一個 UNICODE 字符可能轉化成一個字節或多個字節。

    與“ANSI 編碼”不同的是:
    1. 這些“UNICODE 編碼”能夠處理所有的 UNICODE 字符。
    2. “UNICODE 字符”與“轉換出來的字節”之間是可以通過計算得到的。

    我們實際上沒有必要去深究每一種編碼具體把某一個字符編碼成了哪幾個字節,我們只需要知道“編碼”的概念就是把“字符”轉 化成“字節”就可以了。對于“UNICODE 編碼”,由于它們是可以通過計算得到的,因此,在特殊的場合,我們可以去了解某一種“UNICODE 編碼”是怎樣的規則。

    回頁首

    2. 字符與編碼在程序中的實現

    2.1 程序中的字符與字節

    在 C++ 和 Java 中,用來代表“字符”和“字節”的數據類型,以及進行編碼的方法:

    類型或操作 C++ Java
    字符 wchar_t char
    字節 char byte
    ANSI 字符串 char[] byte[]
    UNICODE 字符串 wchar_t[] String
    字節串→字符串 mbstowcs(), MultiByteToWideChar() string = new String(bytes, "encoding")
    字符串→字節串 wcstombs(), WideCharToMultiByte() bytes = string.getBytes("encoding")

    以上需要注意幾點:

    1. Java 中的 char 代表一個“UNICODE 字符(寬字節字符)”,而 C++ 中的 char 代表一個字節。
    2. MultiByteToWideChar() 和 WideCharToMultiByte() 是 Windows API 函數。

    回頁首

    2.2 C++ 中相關實現方法

    聲明一段字符串常量:

    // ANSI 字符串,內容長度 7 字節
    char
         sz[20] = "中文123";

    // UNICODE 字符串,內容長度 5 個 wchar_t(10 字節)
    wchar_t wsz[20] = L""x4E2D"x6587"x0031"x0032"x0033";

    UNICODE 字符串的 I/O 操作,字符與字節的轉換操作:

    // 運行時設定當前 ANSI 編碼,VC 格式
    setlocale(LC_ALL, ".936");

    // GCC 中格式
    setlocale(LC_ALL, "zh_CN.GBK");

    // Visual C++ 中使用小寫 %s,按照 setlocale 指定編碼輸出到文件
    // GCC 中使用大寫 %S

    fwprintf(fp, L"%s"n", wsz);

    // 把 UNICODE 字符串按照 setlocale 指定的編碼轉換成字節
    wcstombs(sz, wsz, 20);
    // 把字節串按照 setlocale 指定的編碼轉換成 UNICODE 字符串
    mbstowcs(wsz, sz, 20);

    在 Visual C++ 中,UNICODE 字符串常量有更簡單的表示方法。如果源程序的編碼與當前默認 ANSI 編碼不符,則需要使用 #pragma setlocale,告訴編譯器源程序使用的編碼:

    // 如果源程序的編碼與當前默認 ANSI 編碼不一致,
    // 則需要此行,編譯時用來指明當前源程序使用的編碼

    #pragma setlocale
    (".936")

    // UNICODE 字符串常量,內容長度 10 字節
    wchar_t wsz[20] = L"中文123";

    以上需要注意 #pragma setlocale 與 setlocale(LC_ALL, "") 的作用是不同的,#pragma setlocale 在編譯時起作用,setlocale() 在運行時起作用。

    回頁首

    2.3 Java 中相關實現方法

    字符串類 String 中的內容是 UNICODE 字符串:

    // Java 代碼,直接寫中文
    String
    string = "中文123";

    // 得到長度為 5,因為是 5 個字符
    System.out.println(string.length());

    字符串 I/O 操作,字符與字節轉換操作。在 Java 包 java.io.* 中,以“Stream”結尾的類一般是用來操作“字節串”的類,以“Reader”,“Writer”結尾的類一般是用來操作“字符串”的類。

    // 字符串與字節串間相互轉化

    // 按照 GB2312 得到字節(得到多字節字符串)

    byte
    [] bytes = string.getBytes("GB2312");

    // 從字節按照 GB2312 得到 UNICODE 字符串
    string = new String(bytes, "GB2312");

    // 要將 String 按照某種編碼寫入文本文件,有兩種方法:

    // 第一種辦法:用 Stream 類寫入已經按照指定編碼轉化好的字節串

    OutputStream os = new FileOutputStream("1.txt");
    os.write(bytes);
    os.close();

    // 第二種辦法:構造指定編碼的 Writer 來寫入字符串
    Writer ow = new OutputStreamWriter(new FileOutputStream("2.txt"), "GB2312");
    ow.write(string);
    ow.close();

    /* 最后得到的 1.txt 和 2.txt 都是 7 個字節 */

    如果 java 的源程序編碼與當前默認 ANSI 編碼不符,則在編譯的時候,需要指明一下源程序的編碼。比如:

    E:">javac -encoding BIG5 Hello.java

    以上需要注意區分源程序的編碼與 I/O 操作的編碼,前者是在編譯時起作用,后者是在運行時起作用。

    回頁首

    3. 幾種誤解,以及亂碼產生的原因和解決辦法

    3.1 容易產生的誤解
    對編碼的誤解
    誤解一 在將“字節串”轉化成“UNICODE 字符串”時,比如在讀取文本文件時,或者通過網絡傳輸文本時,容易將“字節串”簡單地作為單字節字符串,采用每“一個字節”就是“一個字 符”的方法進行轉化。

    而實際上,在非英文的環境中,應該將“字節串”作為 ANSI 字符串,采用適當的編碼來得到 UNICODE 字符串,有可能“多個字節”才能得到“一個字符”。

    通常,一直在英文環境下做開發的程序員們,容易有這種誤解。
    誤解二 在 DOS,Windows 98 等非 UNICODE 環境下,字符串都是以 ANSI 編碼的字節形式存在的。這種以字節形式存在的字符串,必須知道是哪種編碼才能被正確地使用。這使我們形成了一個慣性思維:“字符串的編碼”。

    當 UNICODE 被支持后,Java 中的 String 是以字符的“序號”來存儲的,不是以“某種編碼的字節”來存儲的,因此已經不存在“字符串的編碼”這個概念了。只有在“字符串”與“字節串”轉化時,或 者,將一個“字節串”當成一個 ANSI 字符串時,才有編碼的概念。

    不少的人都有這個誤解。

    第一種誤解,往往是導致亂碼產生的原因。第二種誤解,往往導致本來容易糾正的亂碼問題變得更復雜。

    在這里,我們可以看到,其中所講的“誤解一”,即采用每“一個字節”就是“一個字符”的轉化方法,實際上也就等同于采用 iso-8859-1 進行轉化。因此,我們常常使用 bytes = string.getBytes("iso-8859-1") 來進行逆向操作,得到原始的“字節串”。然后再使用正確的 ANSI 編碼,比如 string = new String(bytes, "GB2312"),來得到正確的“UNICODE 字符串”。

    回頁首

    3.2 非 UNICODE 程序在不同語言環境間移植時的亂碼

    非 UNICODE 程序中的字符串,都是以某種 ANSI 編碼形式存在的。如果程序運行時的語言環境與開發時的語言環境不同,將會導致 ANSI 字符串的顯示失敗。

    比如,在日文環境下開發的非 UNICODE 的日文程序界面,拿到中文環境下運行時,界面上將顯示亂碼。如果這個日文程序界面改為采用 UNICODE 來記錄字符串,那么當在中文環境下運行時,界面上將可以顯示正常的日文。

    由于客觀原因,有時候我們必須在中文操作系統下運行非 UNICODE 的日文軟件,這時我們可以采用一些工具,比如,南極星,AppLocale 等,暫時的模擬不同的語言環境。

    回頁首

    3.3 網頁提交字符串

    當頁面中的表單提交字符串時,首先把字符串按照當前頁面的編碼,轉化成字節串。然后再將每個字節轉化成 "%XX" 的格式提交到 Web 服務器。比如,一個編碼為 GB2312 的頁面,提交 "中" 這個字符串時,提交給服務器的內容為 "%D6%D0"。

    在服務器端,Web 服務器把收到的 "%D6%D0" 轉化成 [0xD6, 0xD0] 兩個字節,然后再根據 GB2312 編碼規則得到 "中" 字。

    在 Tomcat 服務器中,request.getParameter() 得到亂碼時,常常是因為前面提到的“誤解一”造成的。默認情況下,當提交 "%D6%D0" 給 Tomcat 服務器時,request.getParameter() 將返回 [0x00D6, 0x00D0] 兩個 UNICODE 字符,而不是返回一個 "中" 字符。因此,我們需要使用 bytes = string.getBytes("iso-8859-1") 得到原始的字節串,再用 string = new String(bytes, "GB2312") 重新得到正確的字符串 "中"。

    回頁首

    3.4 從數據庫讀取字符串

    通過數據庫客戶端(比如 ODBC 或 JDBC)從數據庫服務器中讀取字符串時,客戶端需要從服務器獲知所使用的 ANSI 編碼。當數據庫服務器發送字節流給客戶端時,客戶端負責將字節流按照正確的編碼轉化成 UNICODE 字符串。

    如果從數據庫讀取字符串時得到亂碼,而數據庫中存放的數據又是正確的,那么往往還是因為前面提到的“誤解一”造成的。解決 的辦法還是通過 string = new String( string.getBytes("iso-8859-1"), "GB2312") 的方法,重新得到原始的字節串,再重新使用正確的編碼轉化成字符串。

    回頁首

    3.5 電子郵件中的字符串

    當一段 Text 或者 HTML 通過電子郵件傳送時,發送的內容首先通過一種指定的字符編碼轉化成“字 節串”,然后再把“字節串”通過一種指定的傳輸編碼(Content-Transfer-Encoding)進行轉化得到另一串“字節 串”。比如,打開一封電子郵件源代碼,可以看到類似的內容:

    Content-Type: text/plain;
            charset="gb2312"
    Content-Transfer-Encoding: base64

    sbG+qcrQuqO17cf4yee74bGjz9W7+b3wudzA7dbQ0MQNCg0KvPKzxqO6uqO17cnnsaPW0NDEDQoNCg==

    最常用的 Content-Transfer-Encoding 有 Base64 和 Quoted-Printable 兩種。在對二進制文件或者中文文本進行轉化時,Base64 得到的“字節串”比 Quoted-Printable 更短。在對英文文本進行轉化時,Quoted-Printable 得到的“字節串”比 Base64 更短。

    郵件的標題,用了一種更簡短的格式來標注“字符編碼”和“傳輸編碼”。比如,標題內容為 "中",則在郵件源代碼中表示為:

    // 正確的標題格式
    Subject: =?GB2312?B?1tA=?=

    其中,

    • 第一個“=?”與“?”中間的部分指定了字符編碼,在這個例子中指定的是 GB2312。
    • “?”與“?”中間的“B”代表 Base64。如果是“Q”則代表 Quoted-Printable。
    • 最后“?”與“?=”之間的部分,就是經過 GB2312 轉化成字節串,再經過 Base64 轉化后的標題內容。

    如果“傳輸編碼”改為 Quoted-Printable,同樣,如果標題內容為 "中":

    // 正確的標題格式
    Subject: =?GB2312?Q?=D6=D0?=

    如果閱讀郵件時出現亂碼,一般是因為“字符編碼”或“傳輸編碼”指定有誤,或者是沒有指定。比如,有的發郵件組件在發送郵 件時,標題 "中":

    // 錯誤的標題格式
    Subject: =?ISO-8859-1?Q?=D6=D0?=

    這樣的表示,實際上是明確指明了標題為 [0x00D6, 0x00D0],即 "ÖÐ",而不是 "中"。

    回頁首

    4. 幾種錯誤理解的糾正

    誤解:“ISO-8859-1 是國際編碼?”

    非也。iso-8859-1 只是單字節字符集中最簡單的一種,也就是“字節編號”與“UNICODE 字符編號”一致的那種編碼規則。當我們要把一個“字節串”轉化成“字符串”,而又不知道它是哪一種 ANSI 編碼時,先暫時地把“每一個字節”作為“一個字符”進行轉化,不會造成信息丟失。然后再使用 bytes = string.getBytes("iso-8859-1") 的方法可恢復到原始的字節串。

    誤解:“Java 中,怎樣知道某個字符串的內碼?”

    Java 中,字符串類 java.lang.String 處理的是 UNICODE 字符串,不是 ANSI 字符串。我們只需要把字符串作為“抽象的符號的串”來看待。因此不存在字符串的內碼的問題。

    posted @ 2010-04-30 11:15 小菜毛毛 閱讀(365) | 評論 (0)編輯 收藏

    想寫個struts 2.0+tiles模版玩玩,沒有想到找資料還麻煩,于是自己把通宵弄好的過程記下來,以供大家有急需,不足的地方歡迎交流。

    1.在WEB-INF/lib下加入所需的jar包 

        commons-digester-1.6.jar,

        tiles-core-2.0-20070207.130156-4.jar,
        tiles-api-2.0-20070207.130156-4.jar,
        struts2-tiles-plugin-2.0.6.jar,
    struts2-core-2.0.6.jar
    xwork-2.0.1.jar,
    2. 以下內容添加到web.xml
     <context-param>
           <param-name>org.apache.tiles.CONTAINER_FACTORY</param-name>
           <param-value>
               org.apache.struts2.tiles.StrutsTilesContainerFactory
           </param-value>
        </context-param>
       
        <context-param>
           <param-name>   org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG
           </param-name>
           <param-value>/WEB-INF/tiles.xml</param-value>
        </context-param>
     
        <listener>
           <listener-class>
               org.apache.struts2.tiles.StrutsTilesListener
           </listener-class>
        </listener>
    3.在WEB-INF下添加和tiles.tld和tiles.xml文件,其中tiles.tld內容為tiles-core- 2.0-20070207.130156-4.jar包中META_INF/tiles-core.tld的內容。
    tiles.xml內容:
    <?xml version="1.0" encoding="GB2312" ?>
    <!DOCTYPE tiles-definitions PUBLIC
           "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
           "http://jakarta.apache.org/struts/dtds/tiles-config.dtd">
    <tiles-definitions>
        <definition name="myapp.homepage" template="layout.jsp">
           <put name="title" value="Tiles tutorial homepage" />
           <put name="header" value="/tiles/header.jsp" />
           <put name="menu" value="/tiles/menu.jsp" />
           <put name="body" value="/tiles/cBody.jsp" />
           <put name="footer" value="/tiles/footer.jsp" />
        </definition>
    </tiles-definitions>
       
    4.struts.xml 為:
    <!DOCTYPE struts PUBLIC  
            "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
            "http://struts.apache.org/dtds/struts-2.0.dtd">
    <struts>
        <package name="default" extends="tiles-default">
           <action name="go" class="com.action.MyAction">
               <!--result name="success">/next.jsp</result-->
               <result name="success" type="tiles">myapp.homepage</result>
           </action>
           </package>
    </struts>
    紅色部分根據自己項目 定。注意extends="tiles-default"
    5創建layout.jsp
    <%@ page contentType="text/html; charset=UTF-8"%>
    <%@ taglib uri="WEB-INF/tiles.tld " prefix="tiles"%>
    <html>
        <head>
           <title></title>
        </head>
        <body>
           <table width="768px" height="800px" border="2" align="center">
          
               <tr>
                  <td colspan="2" align="center" valign="top" width="768px" height="100px" bgcolor="#80ff80">
                      <tiles:insertAttribute name="header" />
                  </td>
               </tr>
               <tr>
                  <td align="center" width="150px" height="800px" bgcolor="#00ff00">
                      <tiles:insertAttribute name="menu" />
                  </td>
                  <td align="right" width="618px" height="800px" bgcolor="#ff80c0">
                      <tiles:insertAttribute name="body" />
                  </td>
               </tr>
               <tr>
                  <td colspan="2" bgcolor="#00ff40" height="100px">
                      <tiles:insertAttribute name="footer" />
                  </td>
               </tr>
           </table>
        </body>
    </html>
     
    6.根據
    <put name="title" value="Tiles tutorial homepage" />
           <put name="header" value="/tiles/header.jsp" />
           <put name="menu" value="/tiles/menu.jsp" />
           <put name="body" value="/tiles/cBody.jsp" />
           <put name="footer" value="/tiles/footer.jsp" />
    WebRoot下創 建tiles目錄和相應jsp文件
    7.OK了!下載源代碼到我的CSDN資源http://download.csdn.net/user/haoxing272
    null
    posted @ 2010-04-26 15:12 小菜毛毛 閱讀(4707) | 評論 (1)編輯 收藏

    獲取 MIME:HttpContext.Current.Request.Files[fileKey].ContentLength

    MIME類型就是設定某種擴展名 的文件用一種應用程序來打開的方式類型,當該擴展名文件被訪問的時候,瀏覽器會自動使用指定應用程序來打開。多用于指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。

    下面列出常用的文件對應的MIME類型:

    Mime- Types(mime類型) Dateiendung(擴 展名) Bedeutung
    application/msexcel *.xls *.xla Microsoft Excel Dateien
    application/mshelp *.hlp *.chm Microsoft Windows Hilfe Dateien
    application/mspowerpoint *.ppt *.ppz *.pps *.pot Microsoft Powerpoint Dateien
    application/msword *.doc *.dot Microsoft Word Dateien

    application/octet-stream

    *.exe exe
    application/pdf *.pdf Adobe PDF-Dateien
    application/post****** *.ai *.eps *.ps Adobe Post******-Dateien
    application/rtf *.rtf Microsoft RTF-Dateien
    application/x-httpd-php *.php *.phtml PHP-Dateien
         
    application/x-java****** *.js serverseitige Java******-Dateien
    application/x-shockwave-flash *.swf *.cab Flash Shockwave-Dateien
    application/zip *.zip ZIP-Archivdateien
    audio/basic *.au *.snd Sound-Dateien
    audio/mpeg *.mp3 MPEG-Dateien
    audio/x-midi *.mid *.midi MIDI-Dateien
    audio/x-mpeg *.mp2 MPEG-Dateien
    audio/x-wav *.wav Wav-Dateien
    image/gif *.gif GIF-Dateien
    image/jpeg *.jpeg *.jpg *.jpe JPEG-Dateien
    image/x-windowdump *.xwd X-Windows Dump
    text/css *.css CSS Stylesheet-Dateien
    text/html *.htm *.html *.shtml -Dateien
    text/java****** *.js Java******-Dateien
    text/plain *.txt reine Textdateien
    video/mpeg *.mpeg *.mpg *.mpe MPEG-Dateien
    video/vnd.rn-realvideo *.rmvb realplay-Dateien
    video/quicktime *.qt *.mov Quicktime-Dateien
    video/vnd.vivo *viv *.vivo Vivo-Dateien

    更多....查找請用ctrl+F

    MIME類型大全
    application/vnd.lotus-1-2-3
    3gp video/3gpp
    aab application/x-authoware-bin
    aam application/x-authoware-map
    aas application/x-authoware-seg
    ai application/post******
    aif audio/x-aiff
    aifc audio/x-aiff
    aiff audio/x-aiff
    als audio/X-Alpha5
    amc application/x-mpeg
    ani application/octet-stream
    asc text/plain
    asd application/astound
    asf video/x-ms-asf
    asn application/astound
    asp application/x-asap
    asx video/x-ms-asf
    au audio/basic
    avb application/octet-stream
    avi video/x-msvideo
    awb audio/amr-wb
    bcpio application/x-bcpio
    bin application/octet-stream
    bld application/bld
    bld2 application/bld2
    bmp application/x-MS-bmp
    bpk application/octet-stream
    bz2 application/x-bzip2
    cal image/x-cals
    ccn application/x-cnc
    cco application/x-cocoa
    cdf application/x-netcdf
    cgi magnus-internal/cgi
    chat application/x-chat
    class application/octet-stream
    clp application/x-msclip
    cmx application/x-cmx
    co application/x-cult3d-object
    cod image/cis-cod
    cpio application/x-cpio
    cpt application/mac-compactpro
    crd application/x-mscardfile
    csh application/x-csh
    csm chemical/x-csml
    csml chemical/x-csml
    css text/css
    cur application/octet-stream
    dcm x-lml/x-evm
    dcr application/x-director
    dcx image/x-dcx
    dhtml text/html
    dir application/x-director
    dll application/octet-stream
    dmg application/octet-stream
    dms application/octet-stream
    doc application/msword
    dot application/x-dot
    dvi application/x-dvi
    dwf drawing/x-dwf
    dwg application/x-autocad
    dxf application/x-autocad
    dxr application/x-director
    ebk application/x-expandedbook
    emb chemical/x-embl-dl-nucleotide
    embl chemical/x-embl-dl-nucleotide
    eps application/post******
    eri image/x-eri
    es audio/echospeech
    esl audio/echospeech
    etc application/x-earthtime
    etx text/x-setext
    evm x-lml/x-evm
    evy application/x-envoy
    exe application/octet-stream
    fh4 image/x-freehand
    fh5 image/x-freehand
    fhc image/x-freehand
    fif image/fif
    fm application/x-maker
    fpx image/x-fpx
    fvi video/isivideo
    gau chemical/x-gaussian-input
    gca application/x-gca-compressed
    gdb x-lml/x-gdb
    gif image/gif
    gps application/x-gps
    gtar application/x-gtar
    gz application/x-gzip
    hdf application/x-hdf
    hdm text/x-hdml
    hdml text/x-hdml
    hlp application/winhlp
    hqx application/mac-binhex40
    htm text/html
    html text/html
    hts text/html
    ice x-conference/x-cooltalk
    ico application/octet-stream
    ief image/ief
    ifm image/gif
    ifs image/ifs
    imy audio/melody
    ins application/x-NET-Install
    ips application/x-ip******
    ipx application/x-ipix
    it audio/x-mod
    itz audio/x-mod
    ivr i-world/i-vrml
    j2k image/j2k
    jad text/vnd.sun.j2me.app-de******or
    jam application/x-jam
    jar application/java-archive
    jnlp application/x-java-jnlp-file
    jpe image/jpeg
    jpeg image/jpeg
    jpg image/jpeg
    jpz image/jpeg
    js application/x-java******
    jwc application/jwc
    kjx application/x-kjx
    lak x-lml/x-lak
    latex application/x-latex
    lcc application/fastman
    lcl application/x-digitalloca
    lcr application/x-digitalloca
    lgh application/lgh
    lha application/octet-stream
    lml x-lml/x-lml
    lmlpack x-lml/x-lmlpack
    lsf video/x-ms-asf
    lsx video/x-ms-asf
    lzh application/x-lzh
    m13 application/x-msmediaview
    m14 application/x-msmediaview
    m15 audio/x-mod
    m3u audio/x-mpegurl
    m3url audio/x-mpegurl
    ma1 audio/ma1
    ma2 audio/ma2
    ma3 audio/ma3
    ma5 audio/ma5
    man application/x-troff-man
    map magnus-internal/imagemap
    mbd application/mbedlet
    mct application/x-mascot
    mdb application/x-msaccess
    mdz audio/x-mod
    me application/x-troff-me
    mel text/x-vmel
    mi application/x-mif
    mid audio/midi
    midi audio/midi
    mif application/x-mif
    mil image/x-cals
    mio audio/x-mio
    mmf application/x-skt-lbs
    mng video/x-mng
    mny application/x-msmoney
    moc application/x-mocha
    mocha application/x-mocha
    mod audio/x-mod
    mof application/x-yumekara
    mol chemical/x-mdl-molfile
    mop chemical/x-mopac-input
    mov video/quicktime
    movie video/x-sgi-movie
    mp2 audio/x-mpeg
    mp3 audio/x-mpeg
    mp4 video/mp4
    mpc application/vnd.mpohun.certificate
    mpe video/mpeg
    mpeg video/mpeg
    mpg video/mpeg
    mpg4 video/mp4
    mpga audio/mpeg
    mpn application/vnd.mophun.application
    mpp application/vnd.ms-project
    mps application/x-mapserver
    mrl text/x-mrml
    mrm application/x-mrm
    ms application/x-troff-ms
    mts application/metastream
    mtx application/metastream
    mtz application/metastream
    mzv application/metastream
    nar application/zip
    nbmp image/nbmp
    nc application/x-netcdf
    ndb x-lml/x-ndb
    ndwn application/ndwn
    nif application/x-nif
    nmz application/x-scream
    nokia-op-logo image/vnd.nok-oplogo-color
    npx application/x-netfpx
    nsnd audio/nsnd
    nva application/x-neva1
    oda application/oda
    oom application/x-AtlasMate-Plugin
    pac audio/x-pac
    pae audio/x-epac
    pan application/x-pan
    pbm image/x-portable-bitmap
    pcx image/x-pcx
    pda image/x-pda
    pdb chemical/x-pdb
    pdf application/pdf
    pfr application/font-tdpfr
    pgm image/x-portable-graymap
    pict image/x-pict
    pm application/x-perl
    pmd application/x-pmd
    png image/png
    pnm image/x-portable-anymap
    pnz image/png
    pot application/vnd.ms-powerpoint
    ppm image/x-portable-pixmap
    pps application/vnd.ms-powerpoint
    ppt application/vnd.ms-powerpoint
    pqf application/x-cprplayer
    pqi application/cprplayer
    prc application/x-prc
    proxy application/x-ns-proxy-autoconfig
    ps application/post******
    ptlk application/listenup
    pub application/x-mspublisher
    pvx video/x-pv-pvx
    qcp audio/vnd.qcelp
    qt video/quicktime
    qti image/x-quicktime
    qtif image/x-quicktime
    r3t text/vnd.rn-realtext3d
    ra audio/x-pn-realaudio
    ram audio/x-pn-realaudio
    rar application/x-rar-compressed
    ras image/x-cmu-raster
    rdf application/rdf+xml
    rf image/vnd.rn-realflash
    rgb image/x-rgb
    rlf application/x-richlink
    rm audio/x-pn-realaudio
    rmf audio/x-rmf
    rmm audio/x-pn-realaudio
    rmvb audio/x-pn-realaudio
    rnx application/vnd.rn-realplayer
    roff application/x-troff
    rp image/vnd.rn-realpix
    rpm audio/x-pn-realaudio-plugin
    rt text/vnd.rn-realtext
    rte x-lml/x-gps
    rtf application/rtf
    rtg application/metastream
    rtx text/richtext
    rv video/vnd.rn-realvideo
    rwc application/x-rogerwilco
    s3m audio/x-mod
    s3z audio/x-mod
    sca application/x-supercard
    scd application/x-msschedule
    sdf application/e-score
    sea application/x-stuffit
    sgm text/x-sgml
    sgml text/x-sgml
    sh application/x-sh
    shar application/x-shar
    shtml magnus-internal/parsed-html
    shw application/presentations
    si6 image/si6
    si7 image/vnd.stiwap.sis
    si9 image/vnd.lgtwap.sis
    sis application/vnd.symbian.install
    sit application/x-stuffit
    skd application/x-Koan
    skm application/x-Koan
    skp application/x-Koan
    skt application/x-Koan
    slc application/x-salsa
    smd audio/x-smd
    smi application/smil
    smil application/smil
    smp application/studiom
    smz audio/x-smd
    snd audio/basic
    spc text/x-speech
    spl application/futuresplash
    spr application/x-sprite
    sprite application/x-sprite
    spt application/x-spt
    src application/x-wais-source
    stk application/hyperstudio
    stm audio/x-mod
    sv4cpio application/x-sv4cpio
    sv4crc application/x-sv4crc
    svf image/vnd
    svg image/svg-xml
    svh image/svh
    svr x-world/x-svr
    swf application/x-shockwave-flash
    swfl application/x-shockwave-flash
    t application/x-troff
    tad application/octet-stream
    talk text/x-speech
    tar application/x-tar
    taz application/x-tar
    tbp application/x-timbuktu
    tbt application/x-timbuktu
    tcl application/x-tcl
    tex application/x-tex
    texi application/x-texinfo
    texinfo application/x-texinfo
    tgz application/x-tar
    thm application/vnd.eri.thm
    tif image/tiff
    tiff image/tiff
    tki application/x-tkined
    tkined application/x-tkined
    toc application/toc
    toy image/toy
    tr application/x-troff
    trk x-lml/x-gps
    trm application/x-msterminal
    tsi audio/tsplayer
    tsp application/dsptype
    tsv text/tab-separated-values
    tsv text/tab-separated-values
    ttf application/octet-stream
    ttz application/t-time
    txt text/plain
    ult audio/x-mod
    ustar application/x-ustar
    uu application/x-uuencode
    uue application/x-uuencode
    vcd application/x-cdlink
    vcf text/x-vcard
    vdo video/vdo
    vib audio/vib
    viv video/vivo
    vivo video/vivo
    vmd application/vocaltec-media-desc
    vmf application/vocaltec-media-file
    vmi application/x-dreamcast-vms-info
    vms application/x-dreamcast-vms
    vox audio/voxware
    vqe audio/x-twinvq-plugin
    vqf audio/x-twinvq
    vql audio/x-twinvq
    vre x-world/x-vream
    vrml x-world/x-vrml
    vrt x-world/x-vrt
    vrw x-world/x-vream
    vts workbook/formulaone
    wav audio/x-wav
    wax audio/x-ms-wax
    wbmp image/vnd.wap.wbmp
    web application/vnd.xara
    wi image/wavelet
    wis application/x-InstallShield
    wm video/x-ms-wm
    wma audio/x-ms-wma
    wmd application/x-ms-wmd
    wmf application/x-msmetafile
    wml text/vnd.wap.wml
    wmlc application/vnd.wap.wmlc
    wmls text/vnd.wap.wml******
    wmlsc application/vnd.wap.wml******c
    wml****** text/vnd.wap.wml******
    wmv audio/x-ms-wmv
    wmx video/x-ms-wmx
    wmz application/x-ms-wmz
    wpng image/x-up-wpng
    wpt x-lml/x-gps
    wri application/x-mswrite
    wrl x-world/x-vrml
    wrz x-world/x-vrml
    ws text/vnd.wap.wml******
    wsc application/vnd.wap.wml******c
    wv video/wavelet
    wvx video/x-ms-wvx
    wxl application/x-wxl
    x-gzip application/x-gzip
    xar application/vnd.xara
    xbm image/x-xbitmap
    xdm application/x-xdma
    xdma application/x-xdma
    xdw application/vnd.fujixerox.docuworks
    xht application/xhtml+xml
    xhtm application/xhtml+xml
    xhtml application/xhtml+xml
    xla application/vnd.ms-excel
    xlc application/vnd.ms-excel
    xll application/x-excel
    xlm application/vnd.ms-excel
    xls application/vnd.ms-excel
    xlt application/vnd.ms-excel
    xlw application/vnd.ms-excel
    xm audio/x-mod
    xml text/xml
    xmz audio/x-mod
    xpi application/x-xpinstall
    xpm image/x-xpixmap
    xsit text/xml
    xsl text/xml
    xul text/xul
    xwd image/x-xwindowdump
    xyz chemical/x-pdb
    yz1 application/x-yz1
    z application/x-compress
    zac application/x-zaurus-zac
    zip application/zip

    posted @ 2010-04-15 10:59 小菜毛毛 閱讀(288) | 評論 (0)編輯 收藏

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

    HttpClient簡介

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





    回頁首


    HttpClient 功能介紹

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

    • 實現了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
    • 支持自動轉向
    • 支持 HTTPS 協議
    • 支持代理服務器等

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





    回頁首


    HttpClient 基本功能的使用

    GET 方法

    使用 HttpClient 需要以下 6 個步驟:

    1. 創建 HttpClient 的實例

    2. 創建某種連接方法的實例,在這里是 GetMethod。在 GetMethod 的構造函數中傳入待連接的地址

    3. 調用第一步中創建好的實例的 execute 方法來執行第二步中創建好的 method 實例

    4. 讀 response

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

    6. 對得到后的內容進行處理

    根據以上步驟,我們來編寫用GET方法來取得某網頁內容的代碼。

    • 大部分情況下 HttpClient 默認的構造函數已經足夠使用。
      HttpClient httpClient = new HttpClient();


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


    • 調用實例httpClient的executeMethod方法來執行getMethod。由于是執行在網絡上的程序,在運行 executeMethod方法的時候,需要處理兩個異常,分別是HttpException和IOException。引起第一種異常的原因主要可能是 在構造getMethod的時候傳入的協議不對,比如不小心將"http"寫成"htp",或者服務器端返回的內容不正常等,并且該異常發生是不可恢復 的;第二種異常一般是由于網絡原因引起的異常,對于這種異常 (IOException),HttpClient會根據你指定的恢復策略自動試著重新執行executeMethod方法。HttpClient的恢復 策略可以自定義(通過實現接口HttpMethodRetryHandler來實現)。通過httpClient的方法setParameter設置你實 現的恢復策略,本文中使用的是系統提供的默認恢復策略,該策略在碰到第二類異常的時候將自動重試3次。executeMethod返回值是一個整數,表示 了執行該方法后服務器返回的狀態碼,該狀態碼能表示出該方法執行是否成功、需要認證或者頁面發生了跳轉(默認狀態下GetMethod的實例是自動處理跳 轉的)等。
      //設置成了默認的恢復策略,在發生異常時候將自動重試3次,在這里你也可以設置成自定義的恢復策略

      getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,

      new DefaultHttpMethodRetryHandler());

      //執行getMethod

      int statusCode = client.executeMethod(getMethod);

      if (statusCode != HttpStatus.SC_OK) {

      System.err.println("Method failed: " + getMethod.getStatusLine());

      }


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


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


    • 處理內容。在這一步中根據你的需要處理內容,在例子中只是簡單的將內容打印到控制臺。
      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) {

    //構造HttpClient的實例

    HttpClient httpClient = new HttpClient();

    //創建GET方法的實例

    GetMethod getMethod = new GetMethod("http://www.ibm.com");

    //使用系統提供的默認的恢復策略

    getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,

    new DefaultHttpMethodRetryHandler());

    try {

    //執行getMethod

    int statusCode = httpClient.executeMethod(getMethod);

    if (statusCode != HttpStatus.SC_OK) {

    System.err.println("Method failed: "

    + getMethod.getStatusLine());

    }

    //讀取內容

    byte[] responseBody = getMethod.getResponseBody();

    //處理內容

    System.out.println(new String(responseBody));

    } catch (HttpException e) {

    //發生致命的異常,可能是協議不對或者返回的內容有問題

    System.out.println("Please check your provided http address!");

    e.printStackTrace();

    } catch (IOException e) {

    //發生網絡異常

    e.printStackTrace();

    } finally {

    //釋放連接

    getMethod.releaseConnection();

    }

    }

    }


    POST方法

    根據RFC2616,對POST的解釋如下:POST方法用來向目的服務器發出請求,要求它接受被附在請求后的實體,并把它當作請求隊列 (Request-Line)中請求URI所指定資源的附加新子項。POST被設計成用統一的方法實現下列功能:

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

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

    • 構造PostMethod之前的步驟都相同,與GetMethod一樣,構造PostMethod也需要一個URI參數,在本例中,登錄 的地址是http://www.newsmth.net/bbslogin2.php。在創建了PostMethod的實例之后,需要給method實例 填充表單的值,在BBS的登錄表單中需要有兩個域,第一個是用戶名(域名叫id),第二個是密碼(域名叫passwd)。表單中的域用類 NameValuePair來表示,該類的構造函數第一個參數是域名,第二參數是該域的值;將表單所有的值設置到PostMethod中用方法 setRequestBody。另外由于BBS登錄成功后會轉向另外一個頁面,但是HttpClient對于要求接受后繼服務的請求,比如POST和 PUT,不支持自動轉發,因此需要自己對頁面轉向做處理。具體的頁面轉向處理請參見下面的"自動轉向"部分。代碼如下:
      String url = "http://www.newsmth.net/bbslogin2.php";

      PostMethod postMethod = new PostMethod(url);

      // 填入各個表單域的值

      NameValuePair[] data = { new NameValuePair("id", "youUserName"),

      new NameValuePair("passwd", "yourPwd") };

      // 將表單的值放入postMethod中

      postMethod.setRequestBody(data);

      // 執行postMethod

      int statusCode = httpClient.executeMethod(postMethod);

      // HttpClient對于要求接受后繼服務的請求,象POST和PUT等不能自動處理轉發

      // 301或者302

      if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY ||

      statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {

      // 從頭中取出轉向的地址

      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過程中常見的一些問題。

    字符編碼

    某目標頁的編碼可能出現在兩個地方,第一個地方是服務器返回的http頭中,另外一個地方是得到的html/xml頁面中。

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

    自動轉向

    根據RFC2616中對自動轉向的定義,主要有兩種:301和302。301表示永久的移走(Moved Permanently),當返回的是301,則表示請求的資源已經被移到一個固定的新地方,任何向該地址發起請求都會被轉到新的地址上。302表示暫時 的轉向,比如在服務器端的servlet程序調用了sendRedirect方法,則在客戶端就會得到一個302的代碼,這時服務器返回的頭信息中 location的值就是sendRedirect轉向的目標地址。

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

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

    處理HTTPS協議

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

    方法1,取得證書,并導入本地的keystore:

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

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



      2. 單擊"View Certificate",在彈出的對話框中選擇"Details",然后再單擊"Copy to File",根據提供的向導生成待訪問網頁的證書文件



      3. 向導第一步,歡迎界面,直接單擊"Next",



      4. 向導第二步,選擇導出的文件格式,默認,單擊"Next",



      5. 向導第三步,輸入導出的文件名,輸入后,單擊"Next",



      6. 向導第四步,單擊"Finish",完成向導



      7. 最后彈出一個對話框,顯示導出成功



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

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


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

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


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


      運行該程序可能出現的問題:

      1. 拋出異常java.net.SocketException: Algorithm SSL not available。出現這個異常可能是因為沒有加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。出現這個異常可能是你沒有把ibmjsse.jar拷貝到<java-home>"lib"ext"目錄下。

      3. 拋出異常javax.net.ssl.SSLHandshakeException: unknown certificate。出現這個異常表明你的JSSE應該已經安裝正確,但是可能因為你沒有把證書導入到當前運行JRE的keystore中,請按照前 面介紹的步驟來導入你的證書。

    方法2,擴展HttpClient類實現自動接受證書

    因為這種方法自動接收所有證書,因此存在一定的安全問題,所以在使用這種方法前請仔細考慮您的系統的安全需求。具體的步驟如下:

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


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


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

    處理代理服務器

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


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






    回頁首


    結論

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



    參考資料

    • Commons logging包含了各種各樣的日志API的實現,讀者可以通過站點http://jakarta.apache.org/commons /logging/得到詳細的內容

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

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

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

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

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

    • HTTPClient的主頁是http://jakarta.apache.org /commons/httpclient/,你可以在這里得到關于HttpClient更加詳細的信息
    posted @ 2010-04-09 14:38 小菜毛毛 閱讀(828) | 評論 (0)編輯 收藏

    http://update1.aptana.org/studio/3.2/024747/index.html
    在以上網址中可以下載插件或者在線安裝插件:

    End of Life Aptana Studio 1.2

    This update site is for Aptana Studio 1.2 users. There is already a newer version of Aptana Studio available. Please check it out at http://aptana.org/studio/download

    Aptana Studio 3.2 and 3.3 Update Site

    This site is designed to be used inside Eclipse 3.2 or manually update an old version of Aptana Studio. If you have Aptana Studio installed, it is recommended you use the internal update mechanism available via the Help menu => Check for Aptana Updates...

    Install Aptana Studio as a Plugin

    For Eclipse 3.2 or Eclipse 3.3

    If you're already familiar with installing plugins from Eclipse, you can use this URL for the update site:
    http://update.aptana.com/update/studio/3.2
    For detailed instructions click here.

    For Eclipse 3.4

    For Eclipse 3.4 installation instructions click here

    From a Local File

    1. Save the above file to an easy to find location.
    2. Open Eclipse, and go to Help > Software Updates > Find and Install
    3. Search for new features to install, then click "Next" then choose "New Archived Site". Choose the file you saved in step 1.
    4. Select the appropriate plugins to install, then click "Next", accept the license agreements, and click "Next" again.
    5. Click "Change location". If no appropriate location is already available, click "Add Location" and choose something like "D:"dev"extensions"pluginname" or "extesnions"aptana".
    6. Click "Finish".

    Update Aptana Studio Standalone from a Local File

    1. Save the above file to an easy-to-find location, preferably in the root of your drive.
    2. Unzip the file into a folder.
    3. Make sure fix_policy.sh (OS X and Linux) or fix_policy.vbs (Windows) is executable
    4. Run fix_policy.sh (OS X and Linux) or fix_policy.vbs (Windows)
    5. Open policy_url.txt and copy the URL into your clipboard.
    6. Open Aptana Studio, and go to Window > Preferences > Install/Update
    7. Paste the URL from policy_url.txt (something similar to file:///path/to/policy.xml) into the Policy URL field
    8. Click "OK".
    9. Go to Help > Check for Aptana Studio Updates now...
    10. In the "Updates" window, check the box next to the name of the plug-in, and click the "Next" button.
    11. Choose the option to accept the terms of the license agreement, and click the "Next" button.
    12. Click the "Finish" button.
    13. Click the "Install All" button.
    如果按照以上方法安裝有沖突,即可將其下載的插件解壓(比如我解壓到D:/myeclipse6.0.1/eclipse/aptana_update_3.3),并把對應的文件復制features和plugins,并在D:/myeclipse6.0.1/eclipse/links目錄下新建aptana.link文件,并編輯:path=D:\\myeclipse6.0.1\\eclipse\\aptana_update_3.3
    解決開啟后報錯java.lang.NullPointerException的問題
          開啟后彈出對話框報錯java.lang.NullPointerException,點擊details,他報錯:

    java.lang.NullPointerException
    at com.aptana.ide.xul.FirefoxBrowser.createControl(FirefoxBrowser.java:314)
    at com.aptana.ide.server.portal.ui.MyAptanaEditor.createPartControl(MyAptanaEditor.java:261)
    at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:596)
    ........... 省略.............

          這時,雖我已經安裝了firefox,但還是要選擇windows->Preferences->My Aptana/Message Center-> "Use Firefox as the Aptana Home Page Browser",去掉勾子就解決了,My Aptana的廬山真面目就欣賞到了

    posted @ 2010-04-08 10:40 小菜毛毛 閱讀(2800) | 評論 (0)編輯 收藏

       * struts1.2和webwork的區別
        * hibernate和ibatis的區別
        * spring工作機制,IOC容器
        * servlet的一些相關問題
        * webservice相關
        * java基礎:jvm,HashSet等等
        * 考察學習新技術的能力
    posted @ 2010-04-08 09:37 小菜毛毛 閱讀(617) | 評論 (0)編輯 收藏

    僅列出標題
    共17頁: First 上一頁 3 4 5 6 7 8 9 10 11 下一頁 Last 
    主站蜘蛛池模板: 国产亚洲成归v人片在线观看| 亚洲精品无码国产| 亚洲另类古典武侠| 天天影视色香欲综合免费| 亚洲国产成人一区二区三区| 免费在线观影网站| 亚洲成av人片天堂网| 久久黄色免费网站| 久久亚洲精品无码VA大香大香| 无码国产精品一区二区免费16| 老司机亚洲精品影院无码| 精品一区二区三区无码免费视频| 亚洲精品免费在线| 成人看的午夜免费毛片| 色吊丝免费观看网站| 亚洲欧洲日产国码无码网站 | 天天拍拍天天爽免费视频| 亚洲精品永久在线观看| 免费在线精品视频| 久久久久久久国产免费看| 亚洲AV无码一区二区三区系列| 久久国产精品成人片免费| 中文字幕精品三区无码亚洲 | 精品亚洲一区二区三区在线观看| 13小箩利洗澡无码视频网站免费| 亚洲成年轻人电影网站www | 青草青草视频2免费观看| 亚洲理论电影在线观看| 100部毛片免费全部播放完整| 亚洲色欲啪啪久久WWW综合网| 四虎影视免费永久在线观看| baoyu777永久免费视频| 亚洲人成免费网站| 久久久久一级精品亚洲国产成人综合AV区 | 午夜免费福利在线| 国产免费福利体检区久久| 亚洲高清在线mv| 亚洲成A人片在线观看无码3D| 国产精品免费观看调教网| 亚洲人成网站18禁止| 国产亚洲婷婷香蕉久久精品 |