java注解實現(xiàn)websocket服務(wù)的兩種方式
1.基于java注解實現(xiàn)websocket服務(wù)器端
1.1需要的類
1.1.1服務(wù)終端類
用java注解來監(jiān)聽連接@ServerEndpoint、連接成功@OnOpen、連接失敗@OnClose、收到消息等狀態(tài)@OnMessage
1.1.2配置類
把spring中的ServerEndpointExporter對象注入進來
2.1代碼示例
2.1.1 maven配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.heima</groupId>
<artifactId>ws-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.22</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.7.14</version>
</dependency>
</dependencies>
</project>2.1.2 WsServerEndpoint類
package com.heima;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/***
* 監(jiān)聽websocket地址 /myWs
*/
@ServerEndpoint("/myWs")
@Component
@Slf4j
@EnableScheduling
public class WsServerEndpoint {
static Map<String,Session> map = new ConcurrentHashMap<String,Session>();
/***
* 連接建立時執(zhí)行的操作
* @param session
*/
@OnOpen
public void onOpen(Session session)
{
map.put(session.getId(),session);
log.info("websocket is open");
}
/***
* 收到客戶端消息執(zhí)行的操作
* @param text
*/
@OnMessage
public String OnMessage(String text)
{
log.info("收到了一條信息"+text);
return "已收到你的信息" ;
}
/***
* 連接關(guān)閉時執(zhí)行的操作
* @param session
*/
@OnClose
public void OnClose(Session session)
{
map.remove(session.getId());
log.info("連接關(guān)閉時執(zhí)行的操作");
}
/***
* 向客戶端發(fā)送信息
*/
@Scheduled(fixedRate = 2000)
public void sendMsg() throws IOException {
for (String key : map.keySet())
{
map.get(key).getBasicRemote().sendText("你好,你好");
}
}
}
2.1.3 WebSocketConfig
package com.heima;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter()
{
return new ServerEndpointExporter();
}
}
2.1.3 前端測試代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>wsClient</title>
</head>
<body>
<script>
// 創(chuàng)建websocket
let ws = new WebSocket("ws://localhost:8080/myWs")
//向服務(wù)器發(fā)送hello
ws.onopen=function (){
ws.send("hello")
}
//監(jiān)聽數(shù)據(jù)ws://localhost:8080/myWs
ws.onmessage=function (message){
console.log(message.data)
}
</script>
</body>
</html>2.1.4測試結(jié)果
2.1.4.1 當(dāng)打開瀏覽器時

2.1.4.2 當(dāng)關(guān)閉瀏覽器時

2.1.4.3 當(dāng)刷新瀏覽器的時候



2.基于spring提供的類和接口刷新websocket服務(wù)器端
2.1:HttpSessionHandShakeInter 握手?jǐn)r截器
package com.spring;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import java.util.Map;
/***
* 握手?jǐn)r截器
*/
@Component
@Slf4j
public class MyWsInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
log.info(request.getRemoteAddress().toString()+"開始握手");
return super.beforeHandshake(request, response, wsHandler, attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {
log.info(request.getRemoteAddress().toString()+"完成握手");
super.afterHandshake(request, response, wsHandler, ex);
}
}
2.2 MyWsHandler 主處理程序
sessionbean封裝類
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.web.socket.WebSocketSession;
@Data
@AllArgsConstructor
public class SessionBean {
private WebSocketSession webSocketSession;
private Integer clientId;
}
主處理程序
package com.spring;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.server.Session;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/***
* webSocket 主處理程序
*/
@Component
@Slf4j
@EnableScheduling
public class MyWsHandler extends AbstractWebSocketHandler {
//map有并發(fā)線程問題 所以用ConcurrentHashMap
private static Map<String, SessionBean> map ;
//id有并發(fā)問題 所以用Integer的安全類型
private static AtomicInteger clientIdMaker;
static {
map = new ConcurrentHashMap<>();
clientIdMaker=new AtomicInteger(0);
}
//連接建立
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
super.afterConnectionEstablished(session);
//將session 進一步封裝 id采用的是自增
SessionBean sessionBean = new SessionBean(session, clientIdMaker.getAndIncrement());
map.put(session.getId(),sessionBean);
log.info(map.get(session.getId()).getClientId()+"建立了連接");
}
//收到消息
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
super.handleTextMessage(session, message);
log.info(map.get(session.getId()).getClientId()+":"+message.getPayload());
}
//傳輸異常
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
super.handleTransportError(session, exception);
if (session.isOpen())
{
session.close();
}
map.remove(session.getId());
}
//連接關(guān)閉
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
super.afterConnectionClosed(session, status);
log.info(map.get(session.getId()).getClientId()+"關(guān)閉連接");
}
/***
* 向客戶端發(fā)送信息
*/
@Scheduled(fixedRate = 2000)
public void sendMsg() throws IOException {
for (String key : map.keySet())
{
map.get(key).getWebSocketSession().sendMessage(new TextMessage("hello," +
"spring socket"));
}
}
}
2.3 WebSocketConfigurer 注冊攔截器和主處理程序以及監(jiān)聽路徑
package com.spring;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import javax.annotation.Resource;
@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {
@Resource
private MyWsHandler wsHandler;
@Resource
private MyWsInterceptor wsInterceptor;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(wsHandler,"/myWs1").addInterceptors(wsInterceptor).setAllowedOriginPatterns("*");
}
}
2.4 前端測試
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>wsClient</title>
</head>
<body>
<script>
// 創(chuàng)建websocket
let ws = new WebSocket("ws://localhost:8080/myWs1")
//向服務(wù)器發(fā)送hello
ws.onopen=function (){
ws.send("hello")
}
//監(jiān)聽數(shù)據(jù)ws://localhost:8080/myWs
ws.onmessage=function (message){
console.log(message.data)
}
</script>
</body>
</html>總結(jié)
到此這篇關(guān)于java注解實現(xiàn)websocket服務(wù)兩種方式的文章就介紹到這了,更多相關(guān)java websocket服務(wù)實現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IntelliJ?IDEA教程之clean或者install?Maven項目的操作方法
這篇文章主要介紹了IntelliJ?IDEA教程之clean或者install?Maven項目的操作方法,本文分步驟給大家介紹兩種方式講解如何調(diào)試出窗口,需要的朋友可以參考下2023-04-04
Java日期格式化的實現(xiàn)(@JsonFormat和@JSONField)
本文主要介紹了Java日期格式化的實現(xiàn),主要介紹了@JsonFormat和@JSONField兩種方式,具有一定的參考價值,感興趣的可以了解一下2024-05-05
Java?3年面試經(jīng)驗告訴你Mybatis是如何進行分頁的
這篇文章主要介紹了Java?3年面試經(jīng)驗告訴你Mybatis是如何進行分頁的,對于任何ORM框架,分頁的實現(xiàn)邏輯無外乎兩種,不管怎么包裝,最終給到開發(fā)者的,只是使用上的差異而已,本文給大家講解的很明白,感興趣的朋友一起看看吧2022-09-09
Java設(shè)置Excel行列自適應(yīng)詳細(xì)操作步驟和代碼示例(告別手動調(diào)整的繁瑣)
在excel中,可通過設(shè)置自適應(yīng)行高或列寬自動排版,是一種比較常用的快速調(diào)整表格整體布局的方法,這篇文章主要介紹了Java設(shè)置Excel行列自適應(yīng)詳細(xì)操作步驟和代碼示例的相關(guān)資料,需要的朋友可以參考下2026-01-01
SpringBoot整合Redis及Redis工具類撰寫實例
這篇文章主要介紹了SpringBoot整合Redis及Redis工具類撰寫實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01

