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