跨域訪問一直是困擾很多開發(fā)者的問題之一。因為涉及到安全性問題,所以跨域訪問默認是不可以進行的,否則假設(shè)我寫了一段js去更改google的圖標,明天他寫了一段代碼去吧google首頁的文字全部變成梵文,那還得了?
首先,講下什么是相同的域。域是這樣定義的,協(xié)議名+host名+端口號,只有這3個都一樣,才能說是同樣的域,同樣的域里面的訪問不受到同源策略限制,你可以用你的js代碼任意的去操作資源,但是不同域你不能這樣做了。
解決跨域訪問有很多方法,常見的一種“單向”跨域訪問方式是用JSONP(Json with Padding),它解決思路是如果域A (充當客戶端)上的js 要操作域B(充當服務(wù)器端)上的資源,那么只要吧域A上的js函數(shù)名傳遞給域B,然后在域B進行封裝,它解析來自域A的函數(shù)名,并且將域B上的資源轉(zhuǎn)為json對象,并且兩者進行組合,組合后的字符串是 域A函數(shù)名(域B json對象) 這種函數(shù)調(diào)用的形式,然后當域A上用script src='#'" >域A函數(shù)名(域B json對象)的形式,于是達到了域A函數(shù)處理域B資源的效果。
為了更有說服力,我們這里做一個非常簡單的實驗,假定域A(客戶端)有個應(yīng)用部署在http://localhost:8180上,域B(服務(wù)器端)有個應(yīng)用部署在http://localhost:8080上,顯然這2個域由于端口不同,所以域A如果要訪問域B必定是跨域訪問的。域A 有一段js函數(shù),域B提供了一個json對象,我們想要域A的js函數(shù)操作域B的json對象。會怎樣呢?
服務(wù)端(我們部署在http://localhost:8080上):
先貼上域B(服務(wù)器端的代碼),它用一個java servlet,負責接收來自客戶端的帶回調(diào)函數(shù)名參數(shù)的請求,并且與自己端提供的json對象包裝,包裝為一個jsonp后然后放入響應(yīng)輸出流。
package com.charles.jsonp;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.simple.JSONObject;
/**
* Servlet implementation class JSONPServlet
*/
public class JSONPServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public JSONPServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//get the callback function which comes from client
String callbackFuncFromClient= request.getParameter("callbackFunc");
//create a json object
JSONObject jsonInfo = new JSONObject();
jsonInfo.put("name","charles");
jsonInfo.put("title", "technical lead");
jsonInfo.put("info","talent man");
//create a string which stands for a javascript with the format func(jsonobject)
StringBuffer jsonpString = new StringBuffer();
jsonpString.append(callbackFuncFromClient).append("(").append(jsonInfo.toJSONString()).append(")");
//construct the output jsonp and output to the client
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
out.println(jsonpString);
out.flush();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}