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

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

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

    2006年10月10日

    原文來自: HttpClient POST 的 UTF-8 編碼問題

    Apache HttpClient ( http://jakarta.apache.org/commons/httpclient/ ) 是一個純 Java 的HTTP 協議的客戶端編程工具包, 對 HTTP 協議的支持相當全面, 更多細節也可以參考IBM 網站上的這篇文章 HttpClient入門 ( http://www-128.ibm.com/developerworks/cn/opensource/os-httpclient/ ).

    問題分析

    不過在實際使用中, 還是發現按照最基本的方式調用 HttpClient 時, 并不支持 UTF-8 編碼, 在網絡上找過一些文章, 也不得要領, 于是查看了 commons-httpclient-3.0.1 的一些代碼, 首先在 PostMethod 中找到了 generateRequestEntity() 方法:
    ????/**
    ?????*?Generates?a?request?entity?from?the?post?parameters,?if?present.??Calls
    ?????*?{@link?EntityEnclosingMethod#generateRequestBody()}?if?parameters?have?not?been?set.
    ?????*?
    ?????*?@since?3.0
    ?????*/
    ????protected?RequestEntity?generateRequestEntity()?{
    ????????if?(!this.params.isEmpty())?{
    ????????????//?Use?a?ByteArrayRequestEntity?instead?of?a?StringRequestEntity.
    ????????????//?This?is?to?avoid?potential?encoding?issues.??Form?url?encoded?strings
    ????????????//?are?ASCII?by?definition?but?the?content?type?may?not?be.??Treating?the?content
    ????????????//?as?bytes?allows?us?to?keep?the?current?charset?without?worrying?about?how
    ????????????//?this?charset?will?effect?the?encoding?of?the?form?url?encoded?string.
    ????????????String?content?=?EncodingUtil.formUrlEncode(getParameters(),?getRequestCharSet());
    ????????????ByteArrayRequestEntity?entity?=?new?ByteArrayRequestEntity(
    ????????????????EncodingUtil.getAsciiBytes(content),
    ????????????????FORM_URL_ENCODED_CONTENT_TYPE
    ????????????);
    ????????????return?entity;
    ????????}?else?{
    ????????????return?super.generateRequestEntity();
    ????????}
    ????}

    原來使用 NameValuePair 加入的 HTTP 請求的參數最終都會轉化為 RequestEntity 提交到 HTTP 服務器, 接著在 PostMethod 的父類 EntityEnclosingMethod 中找到了如下的代碼:
    ????/**
    ?????*?Returns?the?request's?charset.??The?charset?is?parsed?from?the?request?entity's?
    ?????*?content?type,?unless?the?content?type?header?has?been?set?manually.?
    ?????*?
    ?????*?@see?RequestEntity#getContentType()
    ?????*?
    ?????*?@since?3.0
    ?????*/
    ????public?String?getRequestCharSet()?{
    ????????if?(getRequestHeader("Content-Type")?==?null)?{
    ????????????//?check?the?content?type?from?request?entity
    ????????????//?We?can't?call?getRequestEntity()?since?it?will?probably?call
    ????????????//?this?method.
    ????????????if?(this.requestEntity?!=?null)?{
    ????????????????return?getContentCharSet(
    ????????????????????new?Header("Content-Type",?requestEntity.getContentType()));
    ????????????}?else?{
    ????????????????return?super.getRequestCharSet();
    ????????????}
    ????????}?else?{
    ????????????return?super.getRequestCharSet();
    ????????}
    ????}


    解決方案

    從上面兩段代碼可以看出是 HttpClient 是如何依據 "Content-Type" 獲得請求的編碼(字符集), 而這個編碼又是如何應用到提交內容的編碼過程中去的. 按照這個原來, 其實我們只需要重載 getRequestCharSet() 方法, 返回我們需要的編碼(字符集)名稱, 就可以解決 UTF-8 或者其它非默認編碼提交 POST 請求時的亂碼問題了.

    測試

    首先在 Tomcat 的 ROOT WebApp 下部署一個頁面 test.jsp, 作為測試頁面, 主要代碼片段如下:
    <%@?page?contentType="text/html;charset=UTF-8"%>
    <%@?page?session="false"?%>
    <%
    request.setCharacterEncoding("UTF-8");
    String?val?=?request.getParameter("TEXT");
    System.out.println(">>>>?The?result?is?"?+?val);
    %>


    接著寫一個測試類, 主要代碼如下:
    ????public?static?void?main(String[]?args)?throws?Exception,?IOException?{
    ????????String?url?=?"http://localhost:8080/test.jsp";
    ????????PostMethod?postMethod?=?new?UTF8PostMethod(url);
    ????????//填入各個表單域的值
    ????????NameValuePair[]?data?=?{
    ????????????????new?NameValuePair("TEXT",?"中文"),
    ????????};
    ????????//將表單的值放入postMethod中
    ????????postMethod.setRequestBody(data);
    ????????//執行postMethod
    ????????HttpClient?httpClient?=?new?HttpClient();
    ????????httpClient.executeMethod(postMethod);
    ????}
    ????
    ????//Inner?class?for?UTF-8?support
    ????public?static?class?UTF8PostMethod?extends?PostMethod{
    ????????public?UTF8PostMethod(String?url){
    ????????????super(url);
    ????????}
    ????????@Override
    ????????public?String?getRequestCharSet()?{
    ????????????//return?super.getRequestCharSet();
    ????????????return?"UTF-8";
    ????????}
    ????}


    運行這個測試程序, 在 Tomcat 的后臺輸出中可以正確打印出 ">>>> The result is 中文" .

    代碼下載

    本文所提到的所有代碼, 以及測試程序(可直接導入 eclipse)提供打包下載: att:HttpClient POST 的 UTF-8 編碼問題.httpClientUTF8.tar.bz2

    END


    posted @ 2006-10-31 23:00 thinkbase.net 閱讀(7707) | 評論 (8)編輯 收藏
     
    原文來自:? 使用 Apache 反向代理實現負載均衡及熱備


    初步設想

    • 早些時候在 JavaEye 上看到過一些使用 lighttpd 或者 apache 作前端, 通過負載均衡, 實現高性能的 Web 系統的討論, 于是留意了一下這方面的技術;
    • 考慮到對不同的 App Server 而言, 實現 Session 復制的配置各不相同(通常是需要配置集群), 因此從通用的角度, 覺得使用 session sticky 方式實現的負載均衡比較方便;
    • 由于沒有看到有資料說 lighttpd 能夠實現 session sticky, 所以決定先使用 Apache 試試.
    參考資料:

    環境準備

    • 下載安裝 Apache, 測試時使用的是 XAMPP ( http://www.apachefriends.org/en/xampp.html ) 的 Linux 版本 (xampp-linux-1.5.4.tar.gz), 按照安裝說明, 解壓到 /opt/lampp 目錄下就可以使用了;
      • 啟動 Apache: sudo /opt/lampp/lampp startapache
      • 重新加載 Apache: sudo /opt/lampp/lampp reloadapache (在 httpd.conf 文件被修改后可以不重啟, 而是直接 reload 就可以了)
      • 停止服務: sudo /opt/lampp/lampp stop
    • 準備兩個運行同樣程序的 Web 服務器, 這里使用的是 Tomcat 5.5, 并使用一個 jsp 文件作為測試文件(相關源代碼參見文章最后的附件);
      • 這兩個 Tomcat 服務器需要將 HTTP 服務配置在不同的端口上, 同時由于測試時運行在同一臺機器上, 其它端口也需要避免沖突;
    • 下載安裝 JMeter ( jakarta-jmeter-2.2), 用于壓力測試, 驗證負載均衡的效果;

    測試 jsp 文件的說明

    測試用的 jsp 文件 (test.jsp) 具有如下功能:
    • 顯示當前運行的服務器的 IP 地址及端口號, 這樣從返回的頁面就能夠知道是運行在哪一個 Web 服務器上的了;
    • 統計每個客戶端(不同的 session)向同一臺服務器發出請求的次數, 通過這個計數可以驗證是否實現了 session sticky;
    • 通過 clear 請求參數(即 .../test.jsp?clear=1)清除請求次數的計數結果, 以便進行下一次測試;
    • 模擬 JSESSIONID +jvmRoute 的機制, 自行實現了一個 STICK_PORT_TOKEN 的 Cookie, 直接使用不同服務器的 HTTP 端口號作為 route;
      • 說明1: 考慮到方案的通用性, 這里沒有直接使用 JSESSIONID +jvmRoute 的機制;
      • 說明2: 雖然作為一個例子, 相關代碼是寫死在 jsp 文件中的, 但是這個機制可以很方便的用一個 Filter 統一實現;

    Apache 的配置

    編輯 Apache 的 httpd.conf 文件(如果使用 xampp-linux 的話, 應該在 /opt/lampp/etc 目錄下), 在文件的最后加上如下內容:
    ###############################################################################
    # Reverse Proxy and Load Balance ##############################################
    ###############################################################################
    # 1)簡單的反向代理
    ProxyRequests Off
    <Proxy *>
    Order deny,allow
    Allow from all
    </Proxy>
    ProxyPass /1 http://localhost:8080/test
    #ProxyPassReverse /1 http://localhost:8080/test
    ProxyPass /2 http://localhost:18080/test
    #ProxyPassReverse /2 http://localhost:18080/test
    # 2)非 stickysession 的 balance
    ProxyPass /3 balancer://non-sticky-cluster nofailover=On
    <Proxy balancer://non-sticky-cluster>
    BalancerMember http://localhost:8080/test
    BalancerMember http://localhost:18080/test smax=10
    </Proxy>
    # 3)stickysession 的 balance
    ProxyPass /4 balancer://sticky-cluster stickysession=STICK_PORT_TOKEN nofailover=On
    <Proxy balancer://sticky-cluster>
    BalancerMember http://localhost:8080/test route=8080
    BalancerMember http://localhost:18080/test route=18080 loadfactor=2
    </Proxy>
    這個配置分為3個部分, 包括了 1)簡單的反向代理, 2)非 session sticky 的 load balance, 以及 3)session sticky 的 load balance 三種方式的配置(這里假設兩個 Tomcat 服務器的 HTTP 服務被配置在 8080 和 18080 端口), 其中第 2) 和 3) 的配置中 "nofailover=On" 適合于沒有 session 復制的情況下, 這種情況下, 如果其中一臺 HTTP 服務器出錯, 那么原來分配在這個出錯機器上的瀏覽器客戶端不會被自動轉移到另外的服務器上, 必須重新啟動瀏覽器才能將請求分配到另外一臺服務器上去.

    使用 JMeter 測試結果

    使用 JMeter 對 "3)session sticky 的 load balance" 的效果進行測試, 通過壓力測試的方式, 檢查兩臺 Tomcat 服務器被分配到的請求數量, 相關的測試腳本參見文章最后的附件.

    注意如果重復測試, 在下一次測試開始之前請對每個 Tomcat 服務器執行 .../test.jsp?clear=1 的請求, 清除上一次的計數結果.

    從下圖的測試結果可見: 50個線程中有21個被分配在 8080 端口的服務器上, 29個則被分配到 18080 端口的服務器; 另外, 所有的 session 請求次數都是 20 次, 說明 session sticky 達到了預期的效果.

    附件


    后記

    如何禁用 XAMPP 自帶的內容, 使之成為一個單純的轉發服務器:
    • 1)注釋掉 /opt/lampp/etc/httpd.conf 中 "Include etc/extra/httpd-xampp.conf" 這一行;
    • 2)刪除或者移走 /opt/lampp/htdocs 目錄下的內容(但是此目錄需要保留).
    posted @ 2006-10-10 13:12 thinkbase.net 閱讀(7051) | 評論 (7)編輯 收藏
     
    主站蜘蛛池模板: 久久精品免费全国观看国产| 免费在线观看的黄色网址| 亚洲欧美日韩一区二区三区在线| 国产成人高清精品免费软件| 色www永久免费网站| 亚洲欧洲日产专区| 免费一级毛片在播放视频| 免费成人高清在线视频| 亚洲乱码一区二区三区国产精品| jjzz亚洲亚洲女人| 最近的中文字幕大全免费8| 亚洲aⅴ无码专区在线观看春色 | 国产一级大片免费看| 免费看无码特级毛片| 亚洲一本到无码av中文字幕| 亚洲人成亚洲人成在线观看 | 亚洲一区免费观看| 久久亚洲色WWW成人欧美| 亚洲av无码潮喷在线观看| 永久免费无码网站在线观看| 七色永久性tv网站免费看| 美女啪啪网站又黄又免费| 亚洲精品高清国产麻豆专区| 亚洲精品国产成人影院| 亚洲成在人线aⅴ免费毛片| a毛片免费在线观看| 美美女高清毛片视频黄的一免费| 亚洲综合免费视频| 亚洲永久精品ww47| 国产v片免费播放| 国产香蕉九九久久精品免费| 久久aa毛片免费播放嗯啊| 特级毛片aaaa级毛片免费| 亚洲色大成网站www久久九| 久久久久亚洲AV无码麻豆| 黑人大战亚洲人精品一区| 国产精品极品美女免费观看| 国产精品久久久久久久久免费| 久久青青草原国产精品免费| 一级做a爰片久久免费| 亚洲AV性色在线观看|