# websocket-study **Repository Path**: ChengSongyun/websocket-study ## Basic Information - **Project Name**: websocket-study - **Description**: 关于全双工WebSocket协议的学习 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-09-18 - **Last Updated**: 2025-09-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # WebSocket > websocket是一个全双工通讯协议,它只有一次握手,发送一个特殊的请求将http协议升级为Websocket协议 > > 全双工:就是客户端可以随时向服务端发送消息,服务端也可以随时向客户端发送消息 ## 一、引入依赖 > 在java中,我们想要使用websocket我们需要先引入两个依赖 ```xml jakarta.websocket jakarta.websocket-api 2.2.0 provided jakarta.websocket jakarta.websocket-client-api 2.2.0 ``` ## 二、WebSocket基本使用 ### 1、编写服务端 > 在服务端中,我们需要编写一个WebSocketServer类来实现Websocket的交互 ```java @ServerEndpoint public class WebSocketServer{ @Onopen public void onOpen(Session session){ System.out.println("客户端已连接"); } @OnMessage public void onMessage(String message,Session session){ System.out.println("接收到的消息:"+message); session.getBasicRemote().sendText("Hello client"); } @OnClose public void onClose(Session session){ System.out.println("连接断开"); } } ``` > 注解: > > @ServerEndpoint("/connection"):标注的类将成为WebSocket的端点,前端通过value值访问 > > @Onopen:该注解标注的方法将在连接建立成功时调用 > > @Message:该注解标注的方法将在客户端发送消息时调用 > > @Close:该注解标注的方法将在连接关闭时调用 > > @Error:该注解标注的方法将在连接错误时调用 > > 方法: > > session.getBasicRemote().sendText():该方法用于给客户端发送消息 ### 2、编写客户端 > 在客户端中也需要使用到WebSocket才能实现交互 #### 1.创建websocket对象 > 创建websocket对象用于发送请求和后续使用websocket的API方法 > > 发送的不再是http请求,而是ws请求 ```js const ws = new WebSocket("ws://localhost:8080/connection") ``` #### 2.api方法 > 使用websocket对象中的api方法发送消息给服务端 > > ws.onopen:连接成功时调用 > > ws.onmessage:服务端发送消息时调用 > > ws.onclose:连接关闭时调用 > > ws.send():给服务端发送消息 ```js ws.onopen = function(){ console.log('与服务器建立连接'); //发送消息 ws.send('Hello Server!'); } //onmessage方法,接收服务端发送的消息 ws.onmessage = function(event){ console.log(event.data); } //onclose方法 ws.onclose = function(){ console.log("与服务器断开连接") } ``` ## 三、WebSocket传参 > 在发送消息时,我们可以需要传递一些参数给服务端,让我们获取到一些信息(比如:谁发的,什么时候发的) > > > > 注意:关于WebSocket的更加深入的用法可以看work01项目下的案例 ### 1、引入servlet依赖 > 我们需要使用servlet来进行测试 ```xml jakarta.servlet jakarta.servlet-api 6.1.0 ``` ### 2、编写握手处理器 > 握手处理器用于在握手时获取servlet环境的对象信息 > > (如:HttpSession,HttpRequest等) > > 并将这些数据保存到websocket的session对象中 > > 需要继承Configurator并重写modifyHandshake()握手方法 ```java public class HandshakeHandler extends Configurator{ @Override public void modifyHandshake(ServerEndpointConfig sec,HandshakeRequest request,HandshakeResponse reponse){ //获取HttpSession对象 HttpSession httpSession = (HttpSession) request.getHttpSession(); //从HttpSession中获取登录的用户信息 String user = (String) httpSession.getAttribute("user"); //将用户信息保存到WebSocket的Session对象中 //每一个WebSocket的session都维护了一个map集合 //getUserProperties()得到session的map sec.getUserProperties.put("user",user); } } ``` ### 3、编写WebSocketServer > 在该类中我们需要一个存储Session的Map集合,并且还需要设置握手处理器,使握手处理器生效,还需要实现群发 > > Session:这是WebSocketSession,每个websocket连接都有一个session对象 ```java //必须在configurator属性中设置握手处理器,不然握手处理器不会生效 @ServerEndpoint(value = "/chat",configurator = HandshakeHandler.class) public class WebSocketServer{ /** * 使用map集合维护一个用户列表 * key是一个唯一的id * value是客户端session对象 */ private static final Map users = new HashMap<>(); /** * 每当有用户连接时,创建的session就保存到用户列表中 */ @OnOpen public void onopen(Session session) throw IOException{ //从WebSocket的session对象中获取到用户信息 String user = (String) session.getUserProperties().get("user"); users.put(user,session); } @OnMessage public void onMessage(Session session,String message){ String user = (String) session.getUserProperties().get("user"); } /** * 给所有客户端发送消息 * 群发 */ public void sendAllUser(String message){ users.forEach((id,session) -> { try { //注意:sendText()方法中的参数必须是String类型 session.getBasicRemote().sendText(message); } catch (IOException e) { throw new RuntimeException("发送失败:"+e); } }); } /** * 用户离线 * 每当用户离线后,就将该用户从用户列表中移除 * @param session * @throws IOException */ @OnClose public void onClose(Session session) throws IOException { String user = (String) session.getUserProperties().get("user"); sessionMap.remove(user); } } ``` ### 4、编写LoginServlet > 编写登录的Servlet用于测试 ```java @WebServlet(urlPatterns = "/login") public class LoginServlet extends HttpServlet { @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //从客户端中获取到name为user的表单的值 String user = req.getParameter("user"); //将用户保存到HttpSession,以便在握手处理器中使用 req.getSession().setAttribute("user", user); //转发到聊天页面 req.getRequestDispatcher("/WEB-INF/index.html").forward(req, resp); } } ``` ### 5、编写登录页面 > 编写登录页面用于传递用户信息 ```html Title

Login

``` ### 6、编写聊天页面 > 编写聊天页面用于渲染消息 ```html 聊天室

聊天室


```