WebSocket实践

1.创建项目

Sevlet多的情况推荐还是要web.xml管理Servlet,方便维护和管理。

如果Sevlet少,就使用@WebServle注解方式管理。

2.创建登陆的Servlet [可以直接访问]

HttpServlet依赖于Tomcat。

2.1 添加tomcat依赖

package controller;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @Program: nettyDemo
 * @Description: controller.LoginServlet
 * @Author: BitterGourd
 * @Date: 2020-03-07 00:08
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doPost(req, resp);
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        String userName = req.getParameter("username");
        String passWord = req.getParameter("password");
        System.out.println("username: "+userName+",password: "+passWord);

        HttpSession session = req.getSession();
        String id = session.getId();
        System.out.println("wssessionid:"+id);

        req.getRequestDispatcher("/WEB-INF/jsp/WebSocketChat.jsp").forward(req,resp);
        // WebSocketChat.jsp不允许直接访问放在WEB-INF下 转发进去
        
    }
}

3.创建WebSocket

@ServerEndpoint("/url")是创建WebSocket的Server类需要的注解 用法同 @WebServlet("/url"),url是前端建立连接时需要的地址

  • 一般情况下加入tomcat依赖时不会引入websocket的jar包

package controller;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Program: nettyDemo
 * @Description: WSServer
 * @Author: BitterGourd
 * @Date: 2020-03-08 01:59
 */
@ServerEndpoint("/chatRoom")
public class WSServer {
    private static final Set<WSServer> connections =
            new CopyOnWriteArraySet<>();   // 连接的数量
    private static final String GUEST_PREFIX = "Guest";
    private static final AtomicInteger connectionIds = new AtomicInteger(0);
    private Session session;  // 保存的客户端的session
    private final String nickname;

    public WSServer()  {
        nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
    }

    public void sendMsgToAll(String message) throws IOException {
        for (WSServer eve : connections){
            eve.session.getBasicRemote().sendText(message);
        }
    }

    @OnOpen
    public void start(Session session) throws IOException {  // webSocket包下的Session类
        System.out.println(new String("连接建立成功".getBytes(),"utf-8"));
        this.session = session;
        connections.add(this);
        String message = String.format("* %s %s", nickname, "加入了聊天室.");
        sendMsgToAll(message);
    }


    @OnClose
    public void end() throws IOException {
        System.out.println("连接关闭");
        connections.remove(this);
        String message = String.format("* %s %s", nickname, "离开了聊天室.");
        sendMsgToAll(message);
        connectionIds.getAndDecrement();
    }


    @OnMessage
    public void incoming(String message) throws IOException {  // 接收前台发送的消息
        System.out.println(nickname+"说: "+message);
        sendMsgToAll(message);
    }

    @OnError
    public void onError(Throwable t) throws Throwable{
        System.out.println("Chat Error: " + t.toString());
    }
}

4.Demo整体流程

4.0项目结构

4.1 先写index.jsp [登陆页面]

<%--
  Created by IntelliJ IDEA.
  User: lenovo
  Date: 2020/3/6
  Time: 23:16
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>登陆</title>
  </head>
  <body>
    <div>
      <form action="login">
        <table>
          <tr>
            <td>用户名: </td>
            <td><input type="text" id="username" name="username" placeholder="输入用户名..."></td>
          </tr>
          <tr>
            <td>密码: </td>
            <td><input type="password" id="password" name="password" placeholder="请输入密码..."></td>
          </tr>
          <tr>
            <td><button type="submit">登陆</button></td>
          </tr>
        </table>
      </form>
    </div>
  </body>
</html>

4.2 表单提交到LoginServlet

package controller;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @Program: nettyDemo
 * @Description: controller.LoginServlet
 * @Author: BitterGourd
 * @Date: 2020-03-07 00:08
 */
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doPost(req, resp);
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        String userName = req.getParameter("username");
        String passWord = req.getParameter("password");
        System.out.println("username: "+userName+",password: "+passWord);

        HttpSession session = req.getSession();
        String id = session.getId();
        System.out.println("wssessionid:"+id);

        req.getRequestDispatcher("/WEB-INF/jsp/WebSocketChat.jsp").forward(req,resp);
    }
}

4.3 WebSocket聊天室页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>ChatRoom</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        var ws;
        var ws_url = "ws://127.0.0.1:8080/WebSocket/chatRoom"

        $(function () {
            wsConnect();
            $("#send").click(function () {
                sendMessage();
            })
        })

        function wsConnect() {
            if ('WebSocket' in window) {
                ws = new WebSocket(ws_url); // 连接成功 回调函数生成一个ws对象(websocket连接)
            } else if ('MozWebSocket' in window) {
                ws = new MozWebSocket(ws_url);
            } else {
                console.log('Error: WebSocket is not supported by this browser.');
                return;
            }

            // 都是回调函数
            ws.onopen = function () {
                console.log('Info: WebSocket connection opened.');
            };

            ws.onclose = function () {
                console.log('Info: WebSocket closed.');
            };

            ws.onmessage = function (message) {  // message是从后台传过来的
                console.log(message.data);
                $("#chat_content").append("<p>"+message.data+"</p>");
            };
        }
        function sendMessage() {
            var sendMsg = $("#msg").val();
            ws.send(sendMsg);
            $("#msg").val("");
        }

    </script>
</head>
<body>
<div style="610px;border:1px solid #000">
    <h1 align="center">Welcome to ChatRoom</h1>
    <div id="chat_content" style="margin: 2px;  600px; height: 400px;border:1px solid #000;">
    </div>
    <input id="msg" placeholder="输入消息..." style="margin: 2px;  300px;"><button id="send">发送消息</button>
</div>
</body>
</html>

4.4 WSServer类

package controller;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Program: nettyDemo
 * @Description: WSServer
 * @Author: BitterGourd
 * @Date: 2020-03-08 01:59
 */
@ServerEndpoint("/chatRoom")
public class WSServer {
    private static final Set<WSServer> connections =
            new CopyOnWriteArraySet<>();   // 连接的数量
    private static final String GUEST_PREFIX = "Guest";
    private static final AtomicInteger connectionIds = new AtomicInteger(0);
    private Session session;  // 保存的客户端的session
    private final String nickname;

    public WSServer()  {
        nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
    }

    public void sendMsgToAll(String message) throws IOException {
        for (WSServer eve : connections){
            eve.session.getBasicRemote().sendText(message);
        }
    }

    @OnOpen
    public void start(Session session) throws IOException {  // webSocket包下的Session类
        System.out.println(new String("连接建立成功".getBytes(),"utf-8"));
        this.session = session;
        connections.add(this);
        String message = String.format("* %s %s", nickname, "加入了聊天室.");
        sendMsgToAll(message);
    }


    @OnClose
    public void end() throws IOException {
        System.out.println("连接关闭");
        connections.remove(this);
        String message = String.format("* %s %s", nickname, "离开了聊天室.");
        sendMsgToAll(message);
        connectionIds.getAndDecrement();
    }


    @OnMessage
    public void incoming(String message) throws IOException {  // 接收前台发送的消息
        System.out.println(nickname+"说: "+message);
        sendMsgToAll(message);
    }

    @OnError
    public void onError(Throwable t) throws Throwable{
        System.out.println("Chat Error: " + t.toString());
    }
}

5.效果



原文地址:https://www.cnblogs.com/biturd/p/12623154.html