最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

WebRTC實(shí)現(xiàn)雙端音視頻聊天功能(Vue3 + SpringBoot )

 更新時(shí)間:2025年05月15日 10:37:06   作者:m0_74823094  
這篇文章主要介紹了WebRTC實(shí)現(xiàn)雙端音視頻聊天功能(Vue3 + SpringBoot ),代碼分為前端部分和后端部分,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

概述

  • 文章描述使用WebRTC技術(shù)實(shí)現(xiàn)一對(duì)一音視頻通話。
  • 由于設(shè)備攝像頭限制(一臺(tái)電腦作測(cè)試無法在開啟的雙端同時(shí)獲取攝像頭數(shù)據(jù)流),導(dǎo)致一臺(tái)電腦無法同時(shí)測(cè)試雙端,因此文章使用mp4音視頻文件模擬攝像頭音視頻數(shù)據(jù)流輸入。
  • 使用技術(shù)
    • 前端:Vue3,WebRTC相關(guān)API,axios
    • 后端信令服務(wù)器實(shí)現(xiàn):SpringBoot,WebSocket

相關(guān)概念

  • Peer-to-Peer (P2P) 連接:WebRTC主要是基于 P2P 連接的,這意味著通信是直接在兩端的瀏覽器之間進(jìn)行的,而不需要經(jīng)過中介服務(wù)器(盡管可能會(huì)使用服務(wù)器來初始化和協(xié)調(diào)連接)。這種方式降低了延遲并節(jié)省了帶寬。
  • SDP**(Session Description Protocol)**:**描述媒體信息(如音頻、視頻編碼格式、傳輸協(xié)議等)**的協(xié)議。例如我們?cè)陔p方構(gòu)建連接時(shí),我們需要知道對(duì)方使用的音視頻編解碼格式,以確保雙方使用相同編解碼格式。編解碼格式就是定義在SDP信息中的其中之一的信息。
  • ICE Candidate:ICE 候選是 WebRTC 在 P2P 連接過程中為尋找最佳傳輸路徑(如 STUN 或 TURN 服務(wù)器)提供的一系列地址和端口。在雙方構(gòu)建連接時(shí)需要知道對(duì)方的公網(wǎng)IP****地址和端口,以實(shí)現(xiàn)P2P連接,Candidate信息中就包含自身的公網(wǎng)IP和端口。
  • STUN(Session Traversal Utilities for NAT**)服務(wù)器**:是 NAT 穿透的協(xié)議,用來獲取客戶端的公網(wǎng) IP 地址和端口。我們身處各種局域網(wǎng)中,對(duì)方如果想要和我們構(gòu)建P2P連接,就必然要知道我們的公網(wǎng)IP和端口才能和我們連接上,我們可以通過STUN服務(wù)器獲取我們的公網(wǎng)IP和端口
  • TURN(Traversal Using Relays around NAT**)服務(wù)器**:當(dāng) STUN 連接不可用時(shí),TURN 服務(wù)器作為中繼服務(wù)器轉(zhuǎn)發(fā)數(shù)據(jù)。當(dāng)STUN服務(wù)器無法幫助我們獲取公網(wǎng)IP和端口時(shí),我們就可以使用TURN服務(wù)器作為中轉(zhuǎn)站傳遞音視頻流數(shù)據(jù)。
  • 信令服務(wù)器:上面介紹了媒體信息SDP和網(wǎng)絡(luò)信息Candidate,這些實(shí)際上可以稱為"信令",我們?nèi)绻胍c對(duì)端連接,那么我們就需要知道對(duì)端的媒體信息和網(wǎng)絡(luò)信息來構(gòu)建連接,信令服務(wù)器就是幫助我們實(shí)現(xiàn)兩端的信息交換的。本文中信令服務(wù)器就是我們自己編寫的SpringBoot后端,來幫助兩端互傳連接信息。

雙端連接整體實(shí)現(xiàn)步驟概述

在大致知道了上面介紹的WebRTC基本概念之后,我們以雙端音視頻互聯(lián)的整體過程。

假設(shè)存在A端(發(fā)起端)B端(接收端)。

1. 創(chuàng)建RTC連接對(duì)象(new RTCPeerConnection),此對(duì)象存在構(gòu)建連接時(shí)所需的API。

2. A端和B端分別連接后端WebSocket(信令服務(wù)器),以為接下來信息互傳奠定基礎(chǔ)。

3. A端創(chuàng)建媒體信息SDP(createOffer)保存到本地(setLocalDescription),將A端SDP信息通過WebSocket發(fā)送給B端。

4. B端接收到A端的SDP信息,設(shè)置為遠(yuǎn)端媒體信息(setRemoteDescription),然后B端創(chuàng)建應(yīng)答媒體信息(實(shí)際上就是B端的媒體信息)SDP(createAnswer)保存到本地(setLocalDescription),并將B端創(chuàng)建的應(yīng)答媒體信息SDP通過WebSocket發(fā)送給A端。

5. A端收到B端發(fā)送的應(yīng)答媒體信息SDP后,保存為遠(yuǎn)端媒體信息(setRemoteDescription)。

6. 至此,A端和B端媒體信息SDP交換完畢。

7. 開始交換網(wǎng)絡(luò)信息Candidate,我們?cè)趧?chuàng)建RTC連接對(duì)象時(shí)(步驟1)監(jiān)聽網(wǎng)絡(luò)信息的獲?。╫nicecandidate),當(dāng)我們調(diào)用setRemoteDescription函數(shù)設(shè)置了遠(yuǎn)端媒體信息之后,會(huì)觸發(fā)onicecandidate并給予condidate網(wǎng)絡(luò)信息。

8. 我們將監(jiān)聽到的網(wǎng)絡(luò)信息candidate通過WebSocket發(fā)送給對(duì)端,對(duì)端收到后將對(duì)方的網(wǎng)絡(luò)信息配置上(addIceCandidate)以實(shí)現(xiàn)連接。

9. 當(dāng)媒體信息SDP和網(wǎng)絡(luò)信息Candidate互相交換并設(shè)置上之后,就可以開始音視頻流數(shù)據(jù)互傳顯示了。

10. 通過addTrack發(fā)送本地流數(shù)據(jù),通過ontrack監(jiān)聽對(duì)端音視頻流數(shù)據(jù)的發(fā)送,監(jiān)聽到就顯示對(duì)端音視頻。

媒體協(xié)商和網(wǎng)絡(luò)協(xié)商時(shí)序圖:

**總結(jié):**在視頻互傳之前重要的就是交換媒體SDP信息和網(wǎng)絡(luò)Candidate信息(媒體和網(wǎng)絡(luò)協(xié)商),當(dāng)雙方都獲取到對(duì)方的媒體和網(wǎng)絡(luò)信息之后。就能夠成功構(gòu)建連接并傳遞音視頻數(shù)據(jù)了。

文章代碼實(shí)現(xiàn)注意點(diǎn)

在最開始的概述中有提到,本文提供的1對(duì)1音視頻聊天代碼示例中沒有真實(shí)調(diào)用用戶攝像頭獲取音視頻流數(shù)據(jù),因?yàn)樽髡咧挥幸慌_(tái)電腦,為了可以更方便的在一臺(tái)電腦上開啟兩端并測(cè)試,因此使用了MP4音視頻作為音視頻流數(shù)據(jù)輸入作為測(cè)試。

這實(shí)際上并不會(huì)和真實(shí)開啟攝像頭獲取音視頻數(shù)據(jù)流有很大的區(qū)別。僅僅是獲取流數(shù)據(jù)的方式不同罷了。

在真實(shí)的場(chǎng)景下,可以使用API:getUserMedia去獲取攝像頭音視頻流數(shù)據(jù)即可。

const stream = await navigator.mediaDevices.getUserMedia({
	video: true,
	audio: true
});

STUN和TURN服務(wù)器的搭建

為了能夠獲取到我們本地的公網(wǎng)IP和端口去和對(duì)端創(chuàng)建連接,我們可以嘗試去搭建STUN服務(wù)器和TURN中繼服務(wù)器。

**注:**此步驟不是一定需要做,因?yàn)镚oogle給我們提供了一個(gè)免費(fèi)公用的STUN服務(wù)器地址:stun:stun.l.google.com:19302,如果你發(fā)現(xiàn)用不了,或需要搭建復(fù)雜的音視頻通話應(yīng)用,還是推薦自己搭建一下STUN/TURN服務(wù)器。

我們直接搭建開源的Coturn服務(wù)器即可,因?yàn)镃oturn 同時(shí)支持 TURN 和 STUN 協(xié)議。

下面會(huì)介紹在CentOS8中搭建Coturn服務(wù)器步驟:

1. 安裝所需依賴包

yum install -y make gcc cc gcc-c++ wget openssl-devel libevent libevent-devel openssl 

2. yum直接一鍵下載安裝

sudo yum install coturn
# (驗(yàn)證安裝)安裝程序結(jié)束后執(zhí)行如下命令查看是否正確輸出turnserver路徑
which turnserver

3. 配置Coturn相關(guān)屬性,找到配置文件路徑:

find / -name turnserver.conf

4. 獲取服務(wù)器內(nèi)網(wǎng)IP和公網(wǎng)IP

# 輸入命令查看Ip
ifconfig

找到自己?jiǎn)⒂玫木W(wǎng)絡(luò)下的內(nèi)網(wǎng)IP,公網(wǎng)IP就是你連接服務(wù)器的IP地址。

1fcc4a0de8b34d60aef3b3471bbb9efc.png

5. 使用openSSL生成cert和pkey配置的自簽名證書

openssl req -x509 -newkey rsa:2048 -keyout /turn_server_pkey.pem -out /turn_server_cert.pem -days 999 -nodes 

輸入上面命令后,填寫一下證書的一些信息(城市,地區(qū)等),隨便填一下回車回車!就行。

上面的/turn_server_pkey.pem和/turn_server_cert.pem 請(qǐng)自己設(shè)置好保存證書的路徑,上面默認(rèn)放到了根路徑下。

6. 編輯剛才找到的配置文件

將下面的配置部分修改后替換掉原配置文件的所有內(nèi)容。

# 網(wǎng)卡名
relay-device=eth0
#內(nèi)網(wǎng)IP
listening-ip=172.24.52.189 
listening-port=3478
#內(nèi)網(wǎng)IP,加密訪問配置
relay-ip=172.24.52.189
tls-listening-port=5349
# 外網(wǎng)IP
external-ip=自己的外網(wǎng)IP
relay-threads=500
#打開密碼驗(yàn)證
lt-cred-mech
cert=/turn_server_cert.pem
pkey=/turn_server_pkey.pem
min-port=40000
max-port=65535
#設(shè)置用戶名和密碼,創(chuàng)建IceServer時(shí)使用
user=user:123456
# 外網(wǎng)IP綁定的域名
realm=你自己IP綁定的域名
# 服務(wù)器名稱,用于OAuth認(rèn)證,默認(rèn)和realm相同,部分瀏覽器本段不設(shè)可能會(huì)引發(fā)cors錯(cuò)誤。
server-name=你自己IP綁定的域名
# 認(rèn)證密碼,和前面設(shè)置的密碼保持一致
cli-password=123456

7. 開啟端口訪問

7.1 開啟云服務(wù)器安全組端口

開啟4000-65535端口的原因:外部客戶端與 TURN 服務(wù)器的通信使用動(dòng)態(tài)端口。通常,操作系統(tǒng)會(huì)為每個(gè)連接分配一個(gè)臨時(shí)端口(通常是大于 1024 的端口),而 40000 到 65535 端口 作為 高端端口,是常用的臨時(shí)端口范圍。因此,為了確保 TURN 服務(wù)器能夠處理大量的并發(fā)連接,并為每個(gè)連接分配一個(gè)端口,需要確保 TURN 服務(wù)器的端口范圍足夠大。

7.2開啟本地防火墻端口

#開放端口
firewall-cmd --zone=public --add-port=3478/udp --permanent
firewall-cmd --zone=public --add-port=3478/tcp --permanent
#重啟防火墻
firewall-cmd --reload

8. 啟動(dòng)Coturn服務(wù)器

turnserver -o -a -f

9. 測(cè)試啟動(dòng)狀態(tài)

訪問測(cè)試網(wǎng)站:Trickle ICE

開發(fā)過程描述

如下僅展示關(guān)鍵性代碼解釋說明,具體代碼請(qǐng)到文章最后獲取Gitee源碼地址。

后端開發(fā)流程

  • websocket連接成功后維護(hù)用戶連接信息并廣播join消息。數(shù)據(jù)攜帶用戶ID列表。

// 后端維護(hù)Session連接的數(shù)據(jù)結(jié)構(gòu)

private final HashMap<String, WebSocketSession> userMap = new HashMap<>();

  • 編寫接收信息通用接口,dto對(duì)象包含userID,type,data(JSON序列化字符串),接口根據(jù)傳入userId取出session,給session發(fā)送消息對(duì)象。

前端開發(fā)流程

  • 日志系統(tǒng),監(jiān)聽ice狀態(tài)及日志打印。
  • 創(chuàng)建隨機(jī)ID,連接ws。
  • 協(xié)商函數(shù):協(xié)商前創(chuàng)建peerConnection對(duì)象并監(jiān)聽candidate,當(dāng)雙方都連接成功后調(diào)用,判斷本地offerFlag狀態(tài),如果為true,創(chuàng)建offer設(shè)置本地并發(fā)送消息給對(duì)端。
// STUN 服務(wù)器
const iceServers = [
{
urls: “stun:stun.l.google.com:19302” // Google公開的STUN 服務(wù)器
},
{
urls: “stun:自己的STUN服務(wù)器IP:3478” // 自己的Stun服務(wù)器
},
{
urls: “turn:自己的TRUN服務(wù)器IP:3478”, // 自己的TURN服務(wù)器
username: “userName”,
credential: “Password”
}
];
// 創(chuàng)建RTC連接對(duì)象并監(jiān)聽和獲取condidate信息
function createPeerConnection() {
wlog(“開始創(chuàng)建PC對(duì)象…”)
peerConnection = new RTCPeerConnection(iceServers);
wlog(“創(chuàng)建PC對(duì)象成功”)
// 創(chuàng)建RTC連接對(duì)象后連接websocket
initWebSocket();
// 監(jiān)聽網(wǎng)絡(luò)信息(ICE Candidate)
peerConnection.onicecandidate = (event) => {
if (event.candidate) {
candidateInfo = event.candidate;
wlog(“candidate信息變化…”);
// 將candidate信息發(fā)送給遠(yuǎn)端
setTimeout(()=>{
sendCandidate(event.candidate);
}, 150)
}
};
// 監(jiān)聽遠(yuǎn)端音視頻流
peerConnection.ontrack = (event) => {
nextTick(() => {
wlog(“> 收到遠(yuǎn)端數(shù)據(jù)流 <=”)
if (!remoteVideo.value.srcObject) {
remoteVideo.value.srcObject = event.streams[0];
remoteVideo.value.play(); // 強(qiáng)制播放
}
});
// remoteVideo.value.srcObject = event.streams[0];
};
// 監(jiān)聽ice連接狀態(tài)
peerConnection.oniceconnectionstatechange = () => {
wlog(RTC連接狀態(tài)改變:${peerConnection.iceConnectionState});
};
// 添加本地音視頻流到 PeerConnection
localStream.getTracks().forEach(track => {
peerConnection.addTrack(track, localStream);
});
}
  • candidate監(jiān)聽:當(dāng)監(jiān)聽到candidate后判斷雙方是否已連接,如果已連接,構(gòu)造并發(fā)送candidate給對(duì)端。
    • 解析消息處理器
    • 解析join:type為join取出userId列表,如果為一個(gè)代表僅自己在線,標(biāo)識(shí)為創(chuàng)建offer端,日志打印相關(guān)信息,如果有兩個(gè)者取出對(duì)方ID保存,代表雙方都上線成功,日志打印,調(diào)用協(xié)商函數(shù),開始媒體協(xié)商和網(wǎng)絡(luò)協(xié)商。
    • 解析offer:type為offer,說明收到發(fā)起端offer,將offer設(shè)置為遠(yuǎn)端信息,然后創(chuàng)建answer設(shè)置到本地,構(gòu)建answer消息發(fā)送給對(duì)端。
    • 解析answer:type為answer,說明收到接收端應(yīng)答,取出answer設(shè)置為遠(yuǎn)端消息。
    • 解析candidate:type為candidate,說明收到對(duì)端的網(wǎng)絡(luò)信息,取出設(shè)置到本地。
// 消息處理器 - 解析器
function handleSignalingMessage(message) {
wlog(“收到ws消息,開始解析…”)
wlog(message)
let parseMsg = JSON.parse(message);
wlog(解析結(jié)果:${parseMsg});
if (parseMsg.type == “join”) {
joinHandle(parseMsg.data);
} else if (parseMsg.type == “offer”) {
wlog(“收到發(fā)起端offer,開始解析…”);
offerHandle(parseMsg.data);
} else if (parseMsg.type == “answer”) {
wlog(“收到接收端的answer,開始解析…”);
answerHandle(parseMsg.data);
}else if(parseMsg.type == “candidate”){
wlog(“收到遠(yuǎn)端candidate,開始解析…”);
candidateHandle(parseMsg.data);
}
}
// 遠(yuǎn)端Candidate處理器
async function candidateHandle(candidate){
peerConnection.addIceCandidate(new RTCIceCandidate(JSON.parse(candidate)));
wlog(“+++++++ 本端candidate設(shè)置完畢 ++++++++”);
}
// 接收端的answer處理
async function answerHandle(answer) {
wlog(“將answer設(shè)置為遠(yuǎn)端信息”);
peerConnection.setRemoteDescription(new RTCSessionDescription(JSON.parse(answer))); // 設(shè)置遠(yuǎn)端SDP
}
// 發(fā)起端offer處理器
async function offerHandle(offer) {
wlog(“將發(fā)起端的offer設(shè)置為遠(yuǎn)端媒體信息”);
await peerConnection.setRemoteDescription(new RTCSessionDescription(JSON.parse(offer)));
wlog(“創(chuàng)建Answer 并設(shè)置到本地”);
let answer = await peerConnection.createAnswer()
await peerConnection.setLocalDescription(answer);
wlog(“發(fā)送answer給發(fā)起端”);
// 構(gòu)造answer消息發(fā)送給對(duì)端
let paramObj = {
userId: oppositeUserId,
type: “answer”,
data: JSON.stringify(answer)
}
// 執(zhí)行發(fā)送
const res = await axios.post(${BaseUrl}/rtcs/sendMessage, paramObj);
}
// 加入處理器
function joinHandle(userIds) {
// 判斷連接的用戶個(gè)數(shù)
if (userIds.length == 1 && userIds[0] == userId) {
wlog(“標(biāo)識(shí)為發(fā)起端,等待對(duì)方加入房間…”)
isRoomEmpty.value = true;
// 存在一個(gè)連接并且是自身,標(biāo)識(shí)我們是發(fā)起端
offerFlag = true;
} else if (userIds.length > 1) {
// 對(duì)方加入了
wlog(“對(duì)方已連接…”)
isRoomEmpty.value = false;
// 取出對(duì)方ID
for (let id of userIds) {
  if (id != userId) {
    oppositeUserId = id;
  }
}
wlog(`對(duì)端ID: ${oppositeUserId}`)
// 開始交換SDP和Candidate
swapVideoInfo()
}
}

效果演示

初始狀態(tài)

db67a4f2924c4cc59a68d4b3c69a1ffb.png

發(fā)起端加入房間

cab98851d7524f7caf1156c3b78788a4.png

接收端加入房間

Gitee源碼地址

源碼地址:點(diǎn)擊訪問Gitee項(xiàng)目源代碼。

到此這篇關(guān)于WebRTC實(shí)現(xiàn)雙端音視頻聊天(Vue3 + SpringBoot )的文章就介紹到這了,更多相關(guān)WebRTC雙端音視頻聊天內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • spring-data-redis 動(dòng)態(tài)切換數(shù)據(jù)源的方法

    spring-data-redis 動(dòng)態(tài)切換數(shù)據(jù)源的方法

    最近遇到了一個(gè)麻煩的需求,我們需要一個(gè)微服務(wù)應(yīng)用同時(shí)訪問兩個(gè)不同的 Redis 集群,一般情況下我們會(huì)怎么處理呢,下面通過場(chǎng)景分析給大家介紹spring-data-redis 動(dòng)態(tài)切換數(shù)據(jù)源的方法,感興趣的朋友一起看看吧
    2021-08-08
  • Java 基礎(chǔ):string中的compareTo方法

    Java 基礎(chǔ):string中的compareTo方法

    這篇文章主要介紹了Java 基礎(chǔ):string中的compareTo方法,文章圍繞string中的compareTo方法的相關(guān)資料展開文章詳細(xì)內(nèi)容,希望對(duì)待大家有所幫助
    2021-12-12
  • Java注解處理器實(shí)戰(zhàn)(附詳細(xì)示例代碼)

    Java注解處理器實(shí)戰(zhàn)(附詳細(xì)示例代碼)

    這篇文章主要介紹了Java注解處理器實(shí)戰(zhàn)的相關(guān)資料,通過編譯時(shí)APT生成代碼、運(yùn)行時(shí)反射實(shí)現(xiàn)視圖注入,同時(shí)指導(dǎo)如何開發(fā)自定義注解處理器,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-10-10
  • Springboot中如何通過yml為實(shí)體類注入屬性

    Springboot中如何通過yml為實(shí)體類注入屬性

    這篇文章主要介紹了Springboot中如何通過yml為實(shí)體類注入屬性,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Java SQL注入案例教程及html基礎(chǔ)入門

    Java SQL注入案例教程及html基礎(chǔ)入門

    這篇文章主要介紹了前端開發(fā)每天必學(xué)之SQL及HTML入門基礎(chǔ)知識(shí),介紹了學(xué)習(xí)web前端開發(fā)需要掌握的基礎(chǔ)技術(shù),感興趣的小伙伴們可以參考一下
    2021-07-07
  • Java代理模式之靜態(tài)代理與動(dòng)態(tài)代理的區(qū)別及優(yōu)缺點(diǎn)

    Java代理模式之靜態(tài)代理與動(dòng)態(tài)代理的區(qū)別及優(yōu)缺點(diǎn)

    代理模式是一種常用的設(shè)計(jì)模式,它允許通過引入一個(gè)代理對(duì)象來控制對(duì)目標(biāo)對(duì)象的訪問,在Java中,代理模式被廣泛應(yīng)用,它可以提供額外的功能,如權(quán)限檢查、緩存、日志記錄等,本文將介紹靜態(tài)代理與動(dòng)態(tài)代理的區(qū)別及優(yōu)缺點(diǎn),需要的朋友可以參考下
    2023-06-06
  • Jenkins?Pipline實(shí)現(xiàn)及原理示例解析

    Jenkins?Pipline實(shí)現(xiàn)及原理示例解析

    這篇文章主要為大家介紹了Jenkins?Pipline實(shí)現(xiàn)及原理示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • Java輕松使用工具類實(shí)現(xiàn)獲取MP3音頻時(shí)長(zhǎng)

    Java輕松使用工具類實(shí)現(xiàn)獲取MP3音頻時(shí)長(zhǎng)

    在Java中,工具類定義了一組公共方法,這篇文章將介紹Java中使用工具類來獲取一個(gè)MP3音頻文件的時(shí)間長(zhǎng)度,感興趣的同學(xué)繼續(xù)往下閱讀吧
    2021-10-10
  • Maven多模塊項(xiàng)目調(diào)試與問題排查的完整指南

    Maven多模塊項(xiàng)目調(diào)試與問題排查的完整指南

    在現(xiàn)代企業(yè)級(jí)Java開發(fā)中,Maven多模塊項(xiàng)目因其清晰的代碼組織,依賴管理和高效的構(gòu)建流程已成為主流架構(gòu)模式,本文深入剖析多模塊項(xiàng)目的四大核心痛點(diǎn)解決方案,感興趣的小伙伴可以跟隨小編一起了解下
    2025-06-06
  • 深度解析Spring Security 中的 SecurityFilterChain核心功能

    深度解析Spring Security 中的 SecurityFilterChain核心功

    SecurityFilterChain通過組件化配置、類型安全路徑匹配、多鏈協(xié)同三大特性,重構(gòu)了Spring Security的配置范式,接下來通過本文給大家介紹Spring Security中的SecurityFilterChain核心功能,感興趣的朋友一起看看吧
    2025-08-08

最新評(píng)論

磐石市| 大方县| 冷水江市| 资兴市| 辉县市| 武功县| 中牟县| 竹山县| 灵宝市| 柘城县| 安远县| 黄浦区| 和平区| 墨竹工卡县| 正阳县| 仙游县| 抚松县| 和田县| 阳东县| 文水县| 萨嘎县| 桂林市| 南城县| 右玉县| 梓潼县| 襄汾县| 巴里| 宣化县| 苍溪县| 乌兰察布市| 信阳市| 柏乡县| 开平市| 焉耆| 疏勒县| 济阳县| 富民县| 蒙城县| 保山市| 敖汉旗| 庆云县|