瀏覽器基於同源策略限制:協議、域名、端口三者必須完全相同,才允許 JavaScript 操作目標頁面的 DOM 或發起 AJAX 請求。否則視為跨域,請求會被瀏覽器攔截。
xxx.aaa.com vs yyy.aaa.comaaa.com:8000 vs aaa.com:80https://aaa.com vs https://aaa.com僅適用於主域相同、子域不同場景。在兩個頁面中均設置:
document.domain = 'aaa.com';
即可互相訪問 DOM/JS 變量。注意:無法解決端口/協議不同導致的跨域。
利用 <script> 標籤不受同源策略限制的特性,動態創建腳本標籤請求數據,服務端返回可執行的 JavaScript 函數調用,客戶端預定義回調函數處理數據。
success_jsonpCallback(data)。jsoncallback=success_jsonpCallback。success_jsonpCallback({"name":"張三","age":28})。Content-Type: text/plain;charset=UTF-8,瀏覽器執行腳本,觸發回調。$.ajax({
type: "get",
async: false,
url: "https://api.example.com/data",
dataType: "jsonp",
jsonp: "jsoncallback", // 傳遞回調函數名的參數名
jsonpCallback: "successCallback", // 自定義回調函數名
success: function(json) {
console.log("跨域數據:", json);
}
});
$.getJSON("https://api.example.com/data?jsoncallback=?", function(data) {
console.log("數據:", data);
});
注意:? 會被 jQuery 替換為隨機生成的回調函數名。不支持 POST,URL 長度有限制,不適合大數據量。
public void jsonpTest(HttpServletRequest request, HttpServletResponse response) throws IOException {
String callbackName = request.getParameter("jsoncallback"); // 獲取回調函數名
String jsonStr = "{\"name\":\"張三\",\"age\":28}"; // 業務數據 JSON
String renderStr = callbackName + "(" + jsonStr + ")"; // 拼裝可執行 JS
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().write(renderStr);
}
Access-Control-Allow-Origin 響應頭即可,支持所有 HTTP 方法、請求頭、憑證攜帶,配置更靈活安全。JSONP 是歷史產物,解決老瀏覽器跨域的權宜之計。新項目請優先使用 CORS 或 Nginx 反向代理(同源部署),架構更清晰、安全可控。