開發那點事系列五 - 發散思維&成就技術

       很多做技術的同學,初期都期盼着上面會下派很多任務。做的越多,收穫也越多。誠然,自己也曾經歷過這麼一個階段。在上研時,積極地幫着導師做了一坨事,有Jos相關的,有C++相關的。不積硅步無以至千里嘛,正所謂。除了做事,往往我還會階段性的做一些項目總結,並召集組員討論。無論是技術上,還是非技術上(有些需求是自己去談的,系統是需要自己去上的,當然關於使用方的反饋意見也是記憶最深刻的)。今天藉着工作中一個非常細的點,和大家分享一下,發散思維與技術視野的拓寬多麼密不可分~

        早先寫過一篇跨域問題的文章,詳見: http://fengjia10.iteye.com/blog/481213。今天分享的主題也和跨域有關(之前不是寫過一篇嗎,怎麼又來一篇?其主要動機是我最近比較“懶”,不希望用node.js,也不希望服務器端寫個servlet,就想瀏覽器裏搗鼓一下,就能搞定跨域)。瞭解跨域,首先要了解同源策略。瞭解了它,那麼我想說,其實最省事的方案是在web server(apache.nginx,lighttpd)提供Cross-OriginResource Sharing (CORS)配置。如apache配置中可以添加如下頭部:

        Header add Access-Control-Allow-Origin "*".

        服務器端開放同源訪問策略,雖然省事,但也是風險最大的。倘若我們對服務器端無能爲力,那接下來我們又有何招呢?這裏,我再介紹兩種狠招:

        方案一,借用YQL,代碼如下:

       

// Accepts a url and a callback function to run.
function requestCrossDomain(site, callback) {
 
    // If no url was passed, exit.
    if (!site) {
        alert('No site was passed.');
        return false;
    }
 
    // Take the provided url, and add it to a YQL query. Make sure you encode it!
    var yql = 'http://query.yahooapis.com/v1/public/yql?q=' + encodeURIComponent('select * from xml where url="' + site + '"') + '&format=xml&callback=?';
 
    // Request that YSQL string, and run a callback function.
    // Pass a defined function to prevent cache-busting.
    $.getJSON(yql, cbFunc);
 
    function cbFunc(data) {
        // If we have something to work with...
        if (data.results[0]) {
            if (typeof callback === 'function') {
                callback(data);
            }
        }
        // Else, Maybe we requested a site that doesn't exist, and nothing returned.
        else throw new Error('Nothing returned from getJSON.');
    }
}

        

        關於YQL的詳細介紹,大家可以看這裏, http://developer.yahoo.com/yql/

        其實這招就是Yahoo代爲你請求目標url。注:這裏的format,如果是json的話,它會幫你搞成jsonp的形式返回(即便目標服務器只支持xml返回,YQL也可以jsonp形式返回)。

        方案二,jsonp模式.。讓Yahoo作爲我們的代理,總覺得不靠譜吧?大家都是在天朝做事,天朝上國啊,怎麼甘心使用西方蠻夷的東東呢?那自己搞吧,這裏需要服務器端做點手腳了,返回格式不再是json,而要搞成jsonp了。剩下的就是瀏覽器端的ajax調用,實例代碼如下:

$.ajax({url:finalUrl, type:"GET", crossDomain:true, dataType:"jsonp", timeout:5000, success:function (data, textStatus, jqXHR) {
                if (jqXHR.status == 200 && data.data.userUrl != "") {
                    var userUrl = data.data.userUrl;
                    var waterDetails = userUrl.concat("1/details/");
                    var waterDetailsCached = userUrl.concat("1/details/cached/");
                    var breakDownValue = userUrl.concat("1/breakdown/");
                    var breakDownValueCached = userUrl.concat("1/breakdown/cached/");
                    var domainValue = userUrl.concat("1/domains/");
                    var domainValueCached = userUrl.concat("1/domains/cached/");

                    watUrl[0] = waterDetails, watUrl[1] = waterDetailsCached, brkUrl[0] = breakDownValue, brkUrl[1] = breakDownValueCached, dbkUrl[0] = domainValue, dbkUrl[1] = domainValueCached;

                    $("<div class=\"datagrid-mask\"></div>").css({display:"block", width:"100%", height:$(window).height()}).appendTo("body");
                    $("<div class=\"datagrid-mask-msg\"></div>").html("正在處理,請稍候。。。").appendTo("body").css({display:"block", left:($(document.body).outerWidth(true) - 190) / 2, top:($(window).height() - 45) / 2});

                    setTimeout(show, 120000);
                }
            }});

         注意,jsonp的原理其實蠻簡單的:動態生成一段javascript塊(含有script標籤),然後服務器端返回的是data作爲參數的回調函數,剩下的執行流程就很清晰了。請注意,這裏所有請求都是get請求,這也是爲什麼jquery框架中,即便你設置type爲post,你也無法真正post request,爲什麼會這樣?打開firebug,看看我們的js、img、css的外鏈請求方式吧。

        到目前爲止,我介紹了三種方案,這三種方案的共同之處就是服務器端無需任何編碼(這也是寫這篇博文的初衷,換種思路解決跨域問題嘛)。除此之外,如果我們用applet,iframe,flash,它們也有自己的跨域策略。感興趣的同學可以繼續探索,因爲平時這些偏方用的不多,這裏也就不贅述了。

        到此爲止,看看我們學到了什麼?CORS、同源策略、JSONP原理、JQUERY ajax API、YQL API等等等等。。。。。。

        臨淵慕魚,不如退而結網。嘗試使用發散思路解決問題,你的技術不可能沒有提高的,不是嗎?

        對了,就在發文期間,又幫朋友解決了一個maven依賴的問題。同樣本着發散思路,和大家簡單分享一下吧。主要場景:實現打包的時候將非本方應用(應用所依賴的包)包單獨維護打包,並形成一定的包規格。比方說apache的包,我們統一搞成apache-artifactId-version,如何做呢?這裏給兩種思路:分別基於maven的assembly和dependency插件。爲什麼我會想到這兩個呢?如果你熟悉maven的基礎架構(不熟悉也沒關係,可以拍着大腿想一下,生命週期哪個階段會做這些事情?),maven內置提供給我們dependency插件就有這個功能。爲什麼還有assembly?其實該組件是用來讓我們進行個性化打包的。ok ,細節我省略了。。。。。。

        Maven是一個博大精深的開源產品,掌握好它着實不易,尤其是默認契約(可以參看我前面的maven優化篇)。好了,今天先到這裏吧。。。。。。


參考文獻:

1.      http://usejquery.com/posts/the-jquery-cross-domain-ajax-guide

2.      http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

3.      http://maven.apache.org/plugins/maven-dependency-plugin/

4.      http://maven.apache.org/plugins/maven-assembly-plugin/

發佈了69 篇原創文章 · 獲贊 127 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章