区别:我认为的websocket和轮询的区别
轮询是客户端定期向服务端发送请求,目的是获取的信息
websocket则是服务端直接向客户端发送想要获取的信息
配置jdk17 idea 2022
代码
pom
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.5</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>wsocket</artifactId><version>0.0.1-SNAPSHOT</version><name>wsocket</name><description>wsocket</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.32</version></dependency><!-- websocket消息推送 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework</groupId>-->
<!-- <artifactId>spring-websocket</artifactId>-->
<!-- <version>6.0.9</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.tomcat.embed</groupId>-->
<!-- <artifactId>tomcat-embed-websocket</artifactId>-->
<!-- <version>10.1.20</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.apache.tomcat.embed</groupId>-->
<!-- <artifactId>tomcat-embed-websocket</artifactId>-->
<!-- <version>9.0.78</version>-->
<!-- </dependency>--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.9</version></dependency><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-websocket</artifactId><version>10.1.20</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
配置类
package com.example.wsocket.spring;import com.example.wsocket.java.WebSocketConfig;
import jakarta.annotation.Resource;
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;/***/
@Configuration
@EnableWebSocket
public class MyWsConfig implements WebSocketConfigurer {@ResourceMyWsHandler myWsHandler;@ResourceMyWsInterceptor myWsInterceptor;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(myWsHandler,"/myWs1").addInterceptors(myWsInterceptor).setAllowedOrigins("*");}//访问的位置,设置拦截器,设置拦截范围
}
websocket周期设置
package com.example.wsocket.spring;import cn.hutool.core.text.StrBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.server.Session;
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;/**物理程序*/
@Component
@Slf4j
public class MyWsHandler extends AbstractWebSocketHandler {private static Map<String,SessionBean> sessionBeanMap;private static AtomicInteger clientIdMaker;private static StringBuffer stringBuffer;//初始化static {sessionBeanMap = new ConcurrentHashMap<>();clientIdMaker = new AtomicInteger(0);stringBuffer = new StringBuffer();}@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {super.afterConnectionEstablished(session);SessionBean sessionBean = new SessionBean(session, clientIdMaker.getAndIncrement());sessionBeanMap.put(session.getId(),sessionBean);log.info(sessionBeanMap.get(session.getId()).getClientId()+"建立连接");stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+"进入了群聊<br/>");sendMessage(sessionBeanMap);}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {super.handleTextMessage(session, message);log.info(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload());stringBuffer.append(sessionBeanMap.get(session.getId()).getClientId()+":"+message.getPayload()+"<br/>");sendMessage(sessionBeanMap);}//异常时@Overridepublic void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {super.handleTransportError(session, exception);if (session.isOpen()){session.close();}sessionBeanMap.remove(session.getId());}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {super.afterConnectionClosed(session, status);int clientId = sessionBeanMap.get(session.getId()).getClientId();sessionBeanMap.remove(session);log.info(clientId+"关闭了连接");stringBuffer.append(clientId+"退出了群聊<br/>");sendMessage(sessionBeanMap);}public void sendMessage(Map<String,SessionBean> sessionBeanMap){for(String key:sessionBeanMap.keySet()){{try {sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(stringBuffer.toString()));} catch (IOException e) {log.info("出错啦");}}}}// //定时任务
// @Scheduled(fixedDelay = 2000)//多少秒执行1次
// public void sendMessage() throws IOException {
// for (String key:sessionBeanMap.keySet()){
// sessionBeanMap.get(key).getWebSocketSession().sendMessage(new TextMessage(":心跳"));
// }
// }
}
拦截器
package com.example.wsocket.spring;import lombok.extern.slf4j.Slf4j;
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;/*** @authorGH* @company www.1248163489.com*/
@Component
@Slf4j
public class MyWsInterceptor extends HttpSessionHandshakeInterceptor {@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {return super.beforeHandshake(request, response, wsHandler, attributes);}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception ex) {super.afterHandshake(request, response, wsHandler, ex);}
}
sessionBean
import jakarta.websocket.Session;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.web.server.WebSession;
import org.springframework.web.socket.WebSocketSession;/*** @authorGH* @company www.1248163489.com*/
@Data
@AllArgsConstructorpublic class SessionBean {/****@param*/private WebSocketSession webSocketSession;private Integer clientId;
}
前端页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<p style="border: 1px solid black;width: 400px;height: 600px" id="talkMsg"></p>
<input id="message" />
<button id="sendBtn" onclick="sendMsg()">发送</button>
</body>
<script>let ws = new WebSocket("ws://localhost:8080/myWs1")ws.onopen=function (){}ws.onmessage=function (message) {document.getElementById("talkMsg").innerHTML = message.data}function sendMsg() {ws.send(document.getElementById("message").value)document.getElementById("message").value=""}
</script>
</html>