熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

MIDP 1.0 HttpConnection類的robust封裝

2013-11-23 19:19:28  來源: Java核心技術 
NetConnection簡介

轉述Matrix上zhengyun_ustc所述你的HttpConnection是否封裝的足夠健壯呢?遇到各種情況你是否有信心應對呢?譬如說你要請求的Response包實在太大以至於運營商給你掐了告訴你說超時譬如說你是不是總要自己寫一個線程來專門作http連接?譬如說有一些移動運營商設置了caching proxy servers妨礙了你的測試

為了解決這個問題一位日本程序員JAYF針對MIDP提供了一種robust的NetConnection封裝這個HttpConnnection類負責管理連接並易於使用

NetConnection特性

跨過Proxyserver阻礙

一些移動網絡放置了代理服務器用來提高訪問速度但是它的cache也成為了開發人員測試/調試程序的一大障礙NetConnection類使用一個簡單的http request屬性將server上的代理功能關閉掉

使用線程分離的連接模式

本類可以使用單線程多線程兩種模式運行只要設置一個簡單的標志即可

支持Http request range

由於服務商在其網絡上可能存在一些針對回應數據最大長度的限制所以NetConnection類提供了構造request URL的功能使回應數據分為多個數據包從而去除了前面的限制

netConnection是如何實現的?

netConnection類結構分析

此類實現了Runnable接口其運行模式支持多線程模式當前只能由一個線程使用資源其它線程wait

此類使用了一些靜態成員變量

  //當前只能由一個線程使用singleton
        private static NetConnection singleton = new NetConnection();

        private static HttpConnection httpConn;

        private static String url;

        private static String method;

        private static byte[] data;
                

        private static String contentType;
        

        private static long lowRange;
        

        private static long highRange;
        

        private static boolean disableProxy;
        

        private static boolean detached;
        
        private static byte[] response;



類方法

  //線程run方法
public void run()

//當前運行的線程執行完畢後通報給其它的由於等待資源而wait狀態的線程
private synchronized void forceNotify()

//當資源正在被其它線程使用時當前線程進入wait狀態
private synchronized void forceWait()

//關閉http連接
private static void severConnection()



由於使用了這些static成員變量所以一些操作方法需要同步(synchronized)

netConnection核心代碼解析

netConnection類的實現思想很簡單就是設置一些request屬性和對於GET方法構造一個特殊的URL更重要的是其作者對http協議的深入理解嚴謹的代碼風格值得吾輩學習研究這也是本人分析其核心代碼的一大原因

  /**
* 實現了連接邏輯
* 調用者可以在分離的線程中使用netConnection類的靜態連接
* @throws IllegalStateException 如果此方法直接其它類調用則拋出該異常
*/
public void run() {
        
        if (url == null) {
                throw new IllegalStateException(Cannot invoke this method!);
        }

        
        DataOutputStream dos = null;
        DataInputStream dis = null;
        StringBuffer buffer = null;

        try {

                int permissions = ;
                
                //根據method值設置Connector的權限(READ/READ_WRITE)
                if (HttpConnectionGETequals(method)) {
                        permissions = ConnectorREAD;
                } else if (HttpConnectionPOSTequals(method)) {
                        permissions = ConnectorREAD_WRITE;
                }
                
                //如果關閉server代理功能則構造noProxyUrl
                //原理使用timestamp作為該URL中noproxy參數值
                //        致使server視其為client發來的新請求
                if (disableProxy) {
                        
                        boolean hasQueryParams = false;
                        
                        char[] ca = urltoCharArray();
                        //判斷原URL中是否含有參數
                        for (int loop = ; loop < urllength(); loop++) {
                                
                                if (ca[loop] == ?) {
                                        hasQueryParams = true;
                                        break;
                                }
                        }
                        
                        //由於需要多次字符串拼接所以使用可提供效率的StringBuffer類
                        StringBuffer noProxyUrl = new StringBuffer();

                        //將原URL內容復制到noProxyUrl
                        noProxyUrlappend(url);

                        //如果原URL中含有參數
                        //  則需要在noProxyUrl中增加&
                        //  否則直接在noProxyUrl中增加?
                        //  這樣做為了後面增加noproxy參數做准備
                        if (hasQueryParams) {
                                noProxyUrlappend(&);
                        } else {
                                noProxyUrlappend(?);
                        }

                        //增加noproxy參數
                        noProxyUrlappend(noproxy=);
                noProxyUrlappend(SystemcurrentTimeMillis()); // timestamp
                        
                        //將構造好的noProxyUrl復制到原URL
                        url = noProxyUrltoString();
                }
                
                

                // 打開Http 連接
          httpConn = (HttpConnection) Connectoropen(url permissions true);
                //設置request方法
                (method);

                //如果request權限為READ(即request方法為GET)
                //則需要設置http request屬性的Range
                //原理設置http request屬性的Range後的
                //        server接收到該request後將把response數據分成小部分發回
                //        從而避免了部分運營商對http response size的限制
                if (permissions == ConnectorREAD) {        
                        if (lowRange > && lowRange < highRange) {
                                StringBuffer range = new StringBuffer();
                                
                                rangeappend(bytes=);
                                rangeappend(lowRange);
                                rangeappend();
                                rangeappend(highRange);
                                
                        (Range rangetoString());
                        }
                //否則request權限為READ_WRITE(即request方法為POST)
                //那麼設置request的ContentType屬性
                } else if (permissions == ConnectorREAD_WRITE) {
                        // POST request
                        (ContentType contentType);
                        dos = ();
                        doswrite(data);
                }
        
        } catch (Exception e) {
        
                exceptionPipe = e;
                //如果程序運行在多線程模式則在異常發生後需要喚醒其它睡眠的線程繼續run
                if (detached) {
                        forceNotify();
                }
                
                return;
                
        } finally {

                try {
                        try {
                                if (dos != null) {
                                        // 關閉dos
                                        dosclose();
                                }
                        } catch (Exception e) {
                  // 如果程序運行在多線程模式則在異常發生後需要喚醒其它睡眠的線程繼續run
                                if (exceptionPipe == null) {
                                        exceptionPipe = e;
                                        
                                        if (detached) {
                                                forceNotify();
                                        }
                                        return;
                                }
                        } finally {
                                dos = null;
                        }
                        
                        // 讀取http連接的回應代碼
                        int responseCode = ();
                        
       //當request方法為GET並設置了request range時接收到的回應代碼為HTTP_PARTIAL
       //當request方法為POST接收到的回應代碼為HTTP_OK
       //如果上述兩種回應代碼均沒有收到則表明連接失敗或者出問題
                     if (responseCode != HttpConnectionHTTP_OK
                          && responseCode != HttpConnectionHTTP_PARTIAL) {

                           if (exceptionPipe == null) {
                                 StringBuffer errorCode = new StringBuffer();
                                 errorCodeappend(Response code from server: );
                                 errorCodeappend(responseCode);
                                 errorCodeappend(\nMessage: [);
                                 errorCodeappend(());
                                 errorCodeappend(]);
                                        
                        exceptionPipe = new IOException(errorCodetoString());
                                        
                                        if (detached) {
                                                forceNotify();
                                        }
                                        return;
                                }
                        }

                  //如果收到了上述的兩種回應代碼之一則可以繼續讀取server的response數據
                        dis = ();

                        //循環讀取repsonse數據
                        int ch;
                        buffer = new StringBuffer();
                while ((ch = disread()) != ) {
                        bufferappend((char) ch);
                }

                //將response數據進行必要的編碼轉換                
                        response = buffertoString()getBytes(ISO_);
                        //接收到回應後表明整個http會話過程結束線程將結束
                        //如果程序運行在多線程模式則此時需要喚醒其它睡眠的線程繼續run
                        if (detached) {
                                forceNotify();
                        }
                        
                        return;

                } catch (Exception e) {
                        
                        if (exceptionPipe == null) {
                                exceptionPipe = e;
                                
                                if (detached) {
                                        forceNotify();
                                }
                                
                                return;
                        }
                } finally {
                    
                        try {
                                if (dis != null) {
                                        // 關閉dis
                                        disclose();
                                }
                        } catch (Exception e) {
                                // 若關閉dis時發生異常則進行異常處理
                                if (exceptionPipe == null) {
                                        exceptionPipe = e;
                                        
                                        if (detached) {
                                                forceNotify();
                                        }
                                        return;
                                }
                        } finally {
                                dis = null;
                        }
                        
                        try {
                                if (httpConn != null) {
                                        //關閉http連接
                                        ();

                                        httpConn = null;
                                }
                        } catch (Exception e) {

                                if (exceptionPipe == null) {
                                        exceptionPipe = e;
                                        
                                        if (detached) {
                                                forceNotify();
                                        }
                                        return;
                                }
                        }
                }
        }
}


From:http://tw.wingwit.com/Article/program/Java/hx/201311/26660.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.