生活随笔
收集整理的這篇文章主要介紹了
AJAX跨域访问(不同域之间相互访问)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
- 一、跨域:
- 二、同源策略:
- 三、解決Ajax跨域問題的方案:
- 方案一:設置響應頭
- 方案二:jsonp
- 方案三:jQuery封裝jsonp
- 方案四:代理機制(httpclient)
- 方案五:nginx反向代理
一、跨域:
- 跨域是指從一個域名的網頁去請求另一個域名的資源。比如從百度(https://baidu.com)頁面去請求京東(https://www.jd.com)的資源。
- 通過超鏈接或者form表單提交或者超鏈接的方式進行跨域是不存在問題的。但在一個域名的網頁中的一段js代碼發送ajax請求去訪問另一個域名中的資源,由于同源策略的存在導致無法跨域訪問,那么ajax就存在這種跨域問題。
- 有一些情況下,我們是需要使用ajax進行跨域訪問的。比如某公司的A頁面(8080:a.bjpowernode.com)有可能需要獲取B頁面(8081:b.bjpowernode.com)。
二、同源策略:
- 同源策略是指一段腳本只能讀取來自同一來源的窗口和文檔的屬性,同源就是協議(http)、域名(localhost)和端口(8080)都相同。
- Ajax無法跨域:http://localhost:8080/這個域名中的文件不能訪問http://localhost:8081/這個域名中的內容。但是form表單和超鏈接可以。
- 同源策略有什么用?如果你剛剛在網銀輸入賬號密碼,查看了自己還有1萬塊錢,緊接著訪問一些非法的網站,這個網站可以訪問剛剛的網銀站點,并且獲取賬號密碼,那后果可想而知。所以,從安全的角度來講,同源策略是有利于保護網站信息的。
三、解決Ajax跨域問題的方案:
方案一:設置響應頭
在被訪問的servlet中加入下述代碼表示允許該域名訪問我(該servlet)。
response
.setHeader("Access-Control-Allow-Origin", "http://localhost:8080"); response
.setHeader("Access-Control-Allow-Origin", "*");
方案二:jsonp
- jsonp:json with padding(帶填充的json)
- jsonp不是ajax請求,但是可以完成局部刷新的效果,并且可以解決跨域問題。
- 注意:jsonp解決跨域的時候,只支持GET請求。不支持post請求。
- 原理:script標簽的src屬性值可以是URL,作用是訪問某個servlet,后端servlet響應該請求并返回一個字符串到標簽中,瀏覽器接收到這個字符串后,會自動將字符串當做JS代碼執行。
如果后端響應的字符串是一段JS代碼的字符串,那么就能實現JS的一系列操作,例如使用innerHTML方法動態生成標簽的值、調用前端創建的函數等,類似ajax異步刷新。 - 例子:用戶點擊按鈕后從后端接收數據展示到前端。這里后端接收的數據是一個前端早已寫好的函數。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>jsonp跨域問題
</title>
</head>
<body><script type="text/javascript">function dosome(myjson){document.getElementById("mydiv").innerHTML = myjson.name;}window.onload =() => {document.getElementById("btn").onclick = () =>{var myscript = document.createElement("script");myscript.type = "text/javascript";myscript.src = "http://localhost:8081/a/servlet01?fun=dosome";document.getElementsByTagName("body")[0].appendChild(myscript);}}</script><button id="btn">解決ajax跨域問題
</button><div id="mydiv"></div>
</body>
</html>
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
@WebServlet("/servlet01")
public class Servlets extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request
, HttpServletResponse response
) throws ServletException, IOException {response
.setContentType("text/html");String fun
= request
.getParameter("fun");response
.getWriter().print(fun
+"({\"name\":\"zhangsan\"})");}
}
方案三:jQuery封裝jsonp
- jQuery中的jsonp其實就是我們方案2的高度封裝,底層原理完全相同。
- 核心代碼:$.ajax({type : "GET",url : "跨域的url",dataType : "jsonp", jsonp : "fun", jsonpCallback : "sayHello" })
方案四:代理機制(httpclient)
- 我們知道1號服務器不能使用異步ajax直接訪問二號服務器,所以我們可以1號服務器訪問本服務器的servlet,然后本服務器的servlet去訪問2號服務器的servlet。
- 使用Java程序怎么去發送get/post請求呢?【GET和POST請求就是HTTP請求。】
- 第一種方案:使用JDK內置的API(java.net.URL…),這些API是可以發送HTTP請求的。
- 第二種方案:使用第三方的開源組件,比如:apache的httpclient組件。(httpclient組件是開源免費的,可以直接用)
- 在java程序中,使用httpclient組件可以發送http請求。
- 對于httpclient組件的代碼,大家目前可以不進行深入的研究,可以從網上直接搜。然后粘貼過來,改一改,看看能不能完成發送get和post請求。
- 使用httpclient組件,需要先將這個組件相關的jar包引入到項目當中。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>代理跨域問題
</title>
</head>
<body>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">$(function () {$("#btn").click(function () {$.ajax({type : "get",url : "/b/zhuan",async : true,dataType:"json",success : function(json) {$("#mydiv").html(json.name);}})})})
</script>
<button id="btn">解決ajax跨域問題
</button>
<div id="mydiv"></div>
</body>
</html>
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@WebServlet("/zhuan")
public class Zhongzhuan extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request
, HttpServletResponse response
) throws ServletException, IOException {String url
= "http://localhost:8081/a/servlet02";HttpGet httpGet
= new HttpGet(url
);httpGet
.setHeader("Content-Type", "application/x-www-form-urlencoded");CloseableHttpClient httpClient
= HttpClients.createDefault();HttpResponse response1
= httpClient
.execute(httpGet
);HttpEntity entity
= response1
.getEntity();BufferedReader reader
= new BufferedReader(new InputStreamReader(entity
.getContent(), "UTF-8"));String line
= null;StringBuffer responseSB
= new StringBuffer();while ((line
= reader
.readLine()) != null) {responseSB
.append(line
);}response
.getWriter().print(responseSB
);reader
.close();httpClient
.close();}
}
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
@WebServlet("/servlet02")
public class Servlet2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request
, HttpServletResponse response
) throws ServletException, IOException {response
.setContentType("text/html");response
.getWriter().print("{\"name\":\"zhangsan\"}");}
}
方案五:nginx反向代理
- nginx反向代理中也是使用了這種代理機制來完成AJAX的跨域,實現起來非常簡單,只要修改一個nginx的配置即可。具體細節老師沒講。
總結
以上是生活随笔為你收集整理的AJAX跨域访问(不同域之间相互访问)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。