(URI參數傳遞)
概述
??WebSocket 是 HTML5 中實現實時通信的一種技術,它建立在 HTTP 協議上,但與傳統的 HTTP 請求不同,WebSocket 連接一旦建立,就可以在客戶端和服務器之間雙向傳遞數據,而不需要等待服務器的回應。在 Java 中,可以使用 Netty 這個開源框架來處理 WebSocket 請求。
??在使用Netty實現WebSocket通信時,客戶端可能會通過URI傳遞參數給服務器。然而,Netty的WebSocket URI參數傳遞方式與HTTP不同。HTTP的URI參數通常出現在查詢字符串中,而WebSocket的URI參數則以路徑參數的形式出現。這意味著,如果使用傳統的URI解析方式來解析WebSocket URI參數,可能會遇到問題。
起因
??在做websocket連接時驗證當前用戶是否需要接收異常數據提醒的功能的時候,發現傳了個參數,但是后臺接收不到這個參數,就開始研究怎么才能傳遞參數。
方法1
??直接把參數放到url后面 (new WebSocket("ws://127.0.0.1:12345/ws/?id=value")
)然后自己解析參數。(URI模板是一種通用的URI表示方式,可以包含占位符和查詢參數。查詢參數可以放在URI的查詢字符串中。在服務器端,可以解析URI模板并提取查詢參數。)
解析參數:
??取到uri再截取處理參數
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
System.out.println("觸發事件");
if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) {
WebSocketServerProtocolHandler.HandshakeComplete complete = (WebSocketServerProtocolHandler.HandshakeComplete) evt;
String uri = complete.requestUri();
System.out.println("uri: " + uri);
//輸出帶參數的uri , 然后截取參數
if (null != uri && uri.contains("/ws") && uri.contains("?")) {
String[] uriArray = uri.split("\?");
if (null != uriArray && uriArray.length > 1) {
String[] paramsArray = uriArray[1].split("=");
if (null != paramsArray && paramsArray.length > 1) {
//
String param= paramsArray[1];
}
System.out.println("握手成功");
}
}
}
}
??上面的方法加了參數之后沒有觸發userEventTriggered
方法 (不加參數的時候可以觸發,但是加了之后就不生效了),不知道怎么一回事。
??后面看源碼 發現 channelRead
里邊的msg有這個uri數據,就用這個獲取uri再去處理得到需要的參數。
上圖可以看出了 msg是HttpObjectAggregator$AggregatedFullHttpRequest里邊的 而message里邊有uri這個參數,message是屬于DefaultHttpRequest里邊的
一開始像下面這么寫的以為能直接用,結果報錯了
AggregatedFullHttpRequest
獲取不到,不能直接使用。
// String uri = ((DefaultHttpRequest) ((HttpObjectAggregator.AggregatedFullHttpRequest) msg).message).uri();
??再看看源碼,發現AggregatedFullHttpRequest
是繼承的HttpObjectAggregator.AggregatedFullHttpMessage
而這個是是在Netty框架內部的實現方式,是私有的,不公開的類,不能夠被直接訪問調用到、它不能直接訪問。就去找它的實現類,發現它是實現的FullHttpRequest
這個類,它是Netty提供的公共方法api,可以調用這個方法去獲取uri再進一步去獲取到我們需要的參數,于是就用這個去獲取。
最后實現方式代碼如下:
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println(msg);
String uri = ((FullHttpRequest) msg).uri();
// String uri = ((DefaultHttpRequest) ((HttpObjectAggregator.AggregatedFullHttpRequest) msg).message).uri();
System.out.println("uri: " + uri);
//輸出帶參數的uri , 然后截取出來需要的參數
if (null != uri && uri.contains("/ws") && uri.contains("?")) {
String[] uriArray = uri.split("\\?");
if (null != uriArray && uriArray.length > 1) {
String[] paramsArray = uriArray[1].split("=");
if (null != paramsArray && paramsArray.length > 1) {
// 參數獲取
String param= paramsArray[1];
}
System.out.println("握手成功");
}
}
}
方法2
??在客戶端設置連接成功回調 ,連接成功發送參數。
var socket = new WebSocket("ws://127.0.0.1:12345/ws");
// 發送參數
socket.onopen = function (event) {
socket1.send("value")
}
??前端發送的參數在channelRead0方法的textWebSocketFrame里可以直接獲取到。獲取到想要的參數后,就可以接著進行下面的邏輯處理了。
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {
// 傳的參數
String text = textWebSocketFrame.text();
// ... 拿到參數之后怎么處理的具體邏輯省略
}
pom
當然了,使用netty肯定不能忘了引入依賴
<!--netty-->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>