網站首頁 編程語言 正文
1.前言
跨域簡單的說,就是從一個域名的網頁去訪問另一個域名網頁的資源。
通過超鏈接或者form表單提交或者window.location.href的方式進行跨域是不存在問題的。但在一個域名的網頁中的一段js代碼發送ajax請求去訪問另一個域名中的資源,由于同源策略的存在導致無法跨域訪問,那么ajax就存在這種跨域問題。
關于同源問題,我們判斷同源從三個要素著手:協議、域名、端口號。
如果協議一致,域名一致,端口號一致,三個要素都一致,才是同源,其它一律都是不同源
接下來我們來談談ajax中存在的跨域問題如何解決。
2.解決方案
下面例子都是部署在兩個服務器上,html代碼是a服務器上的內容,servlet是b服務器上的內容。
2.1 設置響應頭
這個比較簡單,只需要在跨域訪問資源的Servlet中添加代碼:
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080"); // 允許某個
response.setHeader("Access-Control-Allow-Origin", "*"); // 允許所有
2.2 jsonp
jsonp是一種類AJAX的請求機制,同樣可以完成局部刷新的效果。但是jsonp只支持GET請求方式。
2.2.1 前端代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jsonp跨域</title>
</head>
<body>
<!-- 下面一行的代碼效果是和下面22-28行的代碼一樣的 -->
<!--<script type="text/javascript" src="http://localhost:8081/b/jsonp2?fun=sayHello"></script>-->
<script type="text/javascript">
// data是一個json:{"username" : "lucy"}
function sayHello(data){
document.getElementById("mydiv").innerHTML = data.username
}
window.onload = () => {
document.getElementById("btn").onclick = () => {
// 加載script元素
// 創建script元素對象
const htmlScriptElement = document.createElement("script");
// 設置script的type屬性
htmlScriptElement.type = "text/javascript"
// 設置script的src屬性
htmlScriptElement.src = "http://localhost:8081/b/jsonp2?fun=sayHello"
// 將script對象添加到body標簽中(這一步就是加載script)
document.getElementsByTagName("body")[0].appendChild(htmlScriptElement)
}
}
</script>
<button id="btn">jsonp解決跨域問題,達到ajax局部刷新的效果</button>
<div id="mydiv"></div>
</body>
</html>
2.2.2 后端代碼
package com.bjpowernode.b.web.servlet;
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("/jsonp2")
public class JSONPServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 獲取函數名
String fun = request.getParameter("fun");
// 響應一段js代碼
response.getWriter().print(fun + "({\"username\" : \"lucy\"})");
}
}
2.3 使用jQuery封裝的jsonp
jQuery中的jsonp其實就是我們上面代碼的高度封裝,底層原理完全相同。
核心代碼:
$.ajax({
type : "GET",
url : "跨域的url",
dataType : "jsonp", // 指定數據類型
jsonp : "fun", // 指定參數名(不設置的時候,默認是:"callback")
jsonpCallback : "sayHello" // 指定回調函數的名字
// (不設置的時候,jQuery會自動生成一個隨機的回調函數,
//并且這個回調函數還會自動調用success的回調函數。)
})
后端代碼同上。
2.4 代理機制(httpclient)
使用Java程序發送get/post請求這里有兩種方案:
- 第一種方案:使用JDK內置的API(java.net.URL…),這些API是可以發送HTTP請求的。
- 第二種方案:使用第三方的開源組件,比如:apache的httpclient組件。(httpclient組件是開源免費的,可以直接用)
這里我們說第二種方案。
2.4.1 前端代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用代理機制完成ajax跨域訪問</title>
</head>
<body>
<script type="text/javascript">
// ES6當中的有一個新語法:箭頭函數。
window.onload = () => {
document.getElementById("btn").onclick = () => {
// 發送ajax請求
// 1.創建核心對象
const xmlHttpRequest = new XMLHttpRequest(); // const可以聲明變量。(可以自己研究一下:var let const聲明變量時有什么區別)
// 2.注冊回調函數
xmlHttpRequest.onreadystatechange = () => {
if (xmlHttpRequest.readyState == 4) {
// 這里也可以使用區間的方式,因為狀態碼是200~299都是正常響應結束。
if (xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) {
document.getElementById("mydiv").innerHTML = xmlHttpRequest.responseText
}
}
}
// 3.開啟通道
xmlHttpRequest.open("GET", "/a/proxy", true)
// 4.發送請求
xmlHttpRequest.send()
}
}
</script>
<button id="btn">使用代理機制解決ajax跨域訪問</button>
<div id="mydiv"></div>
</body>
</html>
2.4.2 代理Servlet代碼
這一部分的代碼基本上都是模板套用,改改具體參數就好了。
package com.bjpowernode.javaweb.servlet;
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.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@WebServlet("/proxy")
public class ProxyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 通過httpclient組件,發送HTTP GET請求,訪問 TargetServlet
HttpGet httpGet = new HttpGet("http://localhost:8081/b/target");
httpGet.setHeader("Content-Type", "application/x-www-form-urlencoded");
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpResponse resp = httpClient.execute(httpGet);
HttpEntity entity = resp.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);
}
reader.close();
httpClient.close();
// b站點響應回來的數據
response.getWriter().print(responseSB);
}
}
2.4.3 目標Servlet代碼
package com.bjpowernode.b.web.servlet;
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("/target")
public class TargetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 響應一個json字符串。
response.getWriter().print("{\"username\":\"jackson\"}");
}
}
2.4.4 圖示
2.5 nginx反向代理
nginx反向代理中也是使用了這種代理機制來完成AJAX的跨域,實現起來非常簡單,只要修改一個nginx的配置即可。這個再說。
原文鏈接:https://blog.csdn.net/qq_52002412/article/details/126461138
相關推薦
- 2022-12-29 react如何將字符串轉義成html語句_React
- 2022-07-30 RocketMQ消息過濾是如何實現的?
- 2022-09-23 win11下FTP服務器搭建圖文教程_FTP服務器
- 2024-03-04 echarts 柱狀圖,單獨一根柱子根據條件改變顏色
- 2022-07-15 Android?Flutter繪制扇形圖詳解_Android
- 2022-05-06 詳析Python面向對象中的繼承_python
- 2022-04-08 swift表格控件使用方法詳解(UITableview)_Swift
- 2022-02-17 URLError和HTTPError基礎用法
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支