开发那点事系列五 - 发散思维&成就技术

       很多做技术的同学,初期都期盼着上面会下派很多任务。做的越多,收获也越多。诚然,自己也曾经历过这么一个阶段。在上研时,积极地帮着导师做了一坨事,有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/

你可能感兴趣的:(jsonp,maven,function,服务器,assembly,callback)