前言
不知大家在平時(shí)的開(kāi)發(fā)過(guò)程中有沒(méi)有遇到過(guò)跨域訪問(wèn)資源的問(wèn)題驳规,我不巧在上周就碰到一個(gè)這樣的問(wèn)題惑折,幸運(yùn)的是在公司前端同學(xué)的幫忙下解決了該問(wèn)題术裸。
什么是跨域問(wèn)題旭蠕?
- 只要協(xié)議停团、域名、端口有任何一個(gè)不同掏熬,都被當(dāng)作是不同的域
- 只要是在不同域中是無(wú)法進(jìn)行通信的佑稠。
基于以上的的出發(fā)點(diǎn),我們又有跨域共享資源的需求(譬如現(xiàn)在流行的前后端分離之后分別部署的情況
)孽江,本文所采用的解決辦法是JSONP
讶坯,說(shuō)到JSONP
就會(huì)首先想到JSON
。雖然只有一字之差但意義卻完全不一樣岗屏,首先科普一下JSON
辆琅。
JSON
其實(shí)現(xiàn)在
JSON
已經(jīng)是相當(dāng)流行了,只要涉及到前后端的數(shù)據(jù)交互大都都是采用的JSON(不管是web還是android和IOS)这刷,所以我這里就舉一個(gè)例子婉烟,就算是沒(méi)有用過(guò)的同學(xué)也能很快明白其中的意思。
PostMan
首先給大家安利一款后端開(kāi)發(fā)的利器PostMan
,可以用于模擬幾乎所有的HTTP
請(qǐng)求暇屋,在開(kāi)發(fā)階段調(diào)試后端接口非常有用似袁。
這是一個(gè)Chrome插件,可以直接在google商店搜索直接下載(當(dāng)然前提你懂得)。
之后界面就如下:
界面非常簡(jiǎn)潔扬霜,有點(diǎn)開(kāi)發(fā)經(jīng)驗(yàn)的童鞋應(yīng)該都會(huì)使用,不太會(huì)用的直接google下就可以了比較簡(jiǎn)單而涉。
接著我們就可以利用
PostMan
來(lái)發(fā)起一次請(qǐng)求獲取JSON
了著瓶。這里以我SSM
項(xiàng)目為例,也正好有暴露一個(gè)JSON的接口。地址如下:http://www.crossoverjie.top/SSM/content_load啼县。
直接在
POSTMAN
中的地址欄輸入該地址材原,采用GET
的方式請(qǐng)求,之后所返回的就是JSON格式的字符串季眷。由于
Javascript
原生的就支持JSON余蟹,所以解析起來(lái)非常方便。
JSONP
好了子刮,終于可以談?wù)?code>JSONP了威酒。之前說(shuō)道JSONP
是用來(lái)解決跨域問(wèn)題的,那么他是如何解決的呢话告。
經(jīng)過(guò)我們開(kāi)發(fā)界的前輩們發(fā)現(xiàn)兼搏,HTML中擁有SRC
屬性的標(biāo)簽都不受跨域的影響卵慰,比如:<script>沙郭、<img>、<iframe>
標(biāo)簽裳朋。
由于JS原生支持JSON的解析病线,于是我們采用<script>
的方式來(lái)處理跨域解析,代碼如下一看就明白鲤嫡。
web端:
<html lang="zh">
<head>
<script type="text/javascript">
$(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "http://www.crossoverjie.top/SSM/jsonpInfo?callback=getUser&userId=3",
dataType: "jsonp",
jsonp: "callback",//一般默認(rèn)為:callback
jsonpCallback:"getUser",//自定義的jsonp回調(diào)函數(shù)名稱送挑,默認(rèn)為jQuery自動(dòng)生成的隨機(jī)函數(shù)名,也可以寫"?"暖眼,jQuery會(huì)自動(dòng)為你處理數(shù)據(jù)
success: function(json){
/**
* 獲得服務(wù)器返回的信息惕耕。
* 可以做具體的業(yè)務(wù)處理。
*/
alert('用戶信息:ID: ' + json.userId + ' 诫肠,姓名: ' + json.username + '司澎。');
},
error: function(){
alert('fail');
}
});
});
</script>
</head>
<body oncontextmenu="return false">
</body>
</html>
其中我們采用了JQuery給我封裝好的函數(shù),這樣就可以自動(dòng)幫我們解析了栋豫。
首先我們來(lái)看下代碼中的http://www.crossoverjie.top/SSM/jsonpInfo?callback=getUser&userId=3這個(gè)地址返回的是什么內(nèi)容挤安,還是放到POSTMAN
中執(zhí)行如下:
可以看到我們所傳遞的
callback
參數(shù)帶著查詢的數(shù)據(jù)又原封不動(dòng)的返回給我們了丧鸯,這樣的話即使我們不使用JQuery
給我封裝好的函數(shù)蛤铜,我們自定義一個(gè)和callback
名稱一樣的函數(shù)一樣是可以解析其中的數(shù)據(jù)的,只是Jquery
幫我們做了而已。
前端沒(méi)問(wèn)題了围肥,那么后端又是如何實(shí)現(xiàn)的呢剿干?也很簡(jiǎn)單,如下:
@RequestMapping(value = "/jsonpInfo",method = { RequestMethod.GET })
@ResponseBody
public Object jsonpInfo(String callback,Integer userId) throws IOException {
User user = userService.getUserById(userId);
JSONPObject jsonpObject = new JSONPObject(callback,user) ;
return jsonpObject ;
}
后端采用了jackson
中的JSONPObject
這個(gè)類的一個(gè)構(gòu)造方法穆刻,只需要將callback
字段和需要轉(zhuǎn)成JSON
字符串的對(duì)象放進(jìn)去即可怨愤。
需要主要的是需要使用@ResponseBody
注解才能成功返回。
總結(jié)
其實(shí)網(wǎng)上還有其他的方法來(lái)處理跨域問(wèn)題蛹批,不過(guò)我覺(jué)得這樣的方式最為簡(jiǎn)單撰洗。同樣JSONP也是有缺點(diǎn)的,比如:只支持GET
方式的HTTP請(qǐng)求腐芍。
以上代碼依然在博主的SSM項(xiàng)目中差导,如有需要可以直接FORK
。
項(xiàng)目地址:https://github.com/crossoverJie/SSM.git
個(gè)人博客地址:http://crossoverjie.top猪勇。
GitHub地址:https://github.com/crossoverJie设褐。