先说说JSONP是怎么产生的1: 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,小可不才,试着用自己的方式来阐释一下这个问题,看看是否有帮助。
一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>
、<img>
、<iframe>
);于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。JSONP的客户端具体实现(jquery版):
使用jsonp来获取数据时,使用GET或者POST方法都是可以的,但是dataType必须要填写jsonp,并且需要填写jsonp和jsonpCallback两个属性,如:
$.ajax({ type: "POST", async: false, url: "http://www.someone.com/a/b", data:{ p: 1609 }, dataType: "jsonp", jsonp: "callback", jsonpCallback:"anyThing", success: function(data){ console.log(data.commonData); alert('票价: ' + data.jsonPData.PRice + ' 元,数量: ' + data.jsonPData.tickets + ' 个。'); }, error: function(){ alert('fail'); }});其中需要注意的是,jsonp属性在最后发出请求时会变成如下格式
http://www.someone.com/a/b?callback=anyThing&_=1486627742030所以java后端会取到callback的值,在返回时会拼装成如下格式数据返回,返回一个名为angThing的函数:
angThing({ "commonData": {...}, "jsonPData": { "price": 213.1, "tickets": 41 }})jquery会将方法中的数据剥离并返回到success回调方法中,供页面使用。
JSONP的服务端实现(struts2): 首先,在action中获取有客户端传来的数据,如data中的参数和callback的值
private String callback;public String find() { CommonData commonData = new CommonData(); JsonPTemp jsonPData = new JsonPTemp(new BigDecimal(213.1), new BigDecimal(41)); setJsonp(new JsonP(commonData, jsonPData)); return SUCCESS;}Struts2配置
<package name="a" namespace="/a" extends="default"><action name="b" class="com.someone.www.action.Action" method="find"> <result name="success" type="json"> <param name="callbackParameter">callback</param> <param name="root">jsonp</param> </result></action></package>注意:result中callbackParameter的值一定要与action中声明的变量名一致,否则的话请求会报错。
其实,struts2会把callback的值获取到,然后声明称一个方法供客户端使用,里面包裹的值是在下面时候填写进去的
setJsonp(new JsonP(commonData, jsonPData));struts2会把数据先转化为json,然后放入生成的方法中后,返回。
新闻热点
疑难解答