# 利刃出鞘_Tomcat 核心原理解析(十一)-- Tomcat 附加功能 WebSocket -- 2

利刃出鞘_Tomcat 核心原理解析(十一)-- Tomcat 附加功能 WebSocket -- 2

一、Tomcat专题 - WebSocket - 案例 - 登录功能

1、在项目 dzs168_chat_room 中,导入 tomcat 项目依赖( dzs168_chat_room/web/lib/ )

bash 复制代码
idea ---> File
---> Project Structure 
---> Modules 
	选择我们的项目 dzs168_chat_room
	---> Dependencies:  点击 + 添加
	---> Library...
	---> Application Server Libraries
	---> Tcomcat 
	---> Add Selected
	---> Apply 
---> OK。

2、项目 dzs168_chat_room 中,login.jsp 页面。

java 复制代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<head>
    <title>段子手聊天室------登录</title>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="keywords"
          content="Transparent Sign In Form Responsive Widget,Login form widgets, Sign up Web forms , Login signup Responsive web form,Flat Pricing table,Flat Drop downs,Registration Forms,News letter Forms,Elements"/>
    <script type="application/x-javascript">
        addEventListener("load", function () {
            setTimeout(hideURLbar, 0);
        }, false);

        function hideURLbar() {
            window.scrollTo(0, 1);
        }
    </script>

    <script src="js/jquery-1.9.1.min.js"></script>
    <link rel="icon" href="img/chat.ico" type="image/x-icon"/>
    <link rel="stylesheet" href="css/font-awesome.css"/> <!-- Font-Awesome-Icons-CSS -->
    <link rel="stylesheet" href="css/login.css" type="text/css" media="all"/> <!-- Style-CSS -->
</head>

<body class="background">
<div class="header-w3l">
    <h1>段子手168聊天室</h1>
</div>
<div class="main-content-agile">
    <div class="sub-main-w3">
        <h2>登录</h2>
        <form>

            <div class="icon1">
                <input placeholder="用户名" id="username" type="text"/>
            </div>

            <div class="icon2">
                <input placeholder="密码" id="password" type="password"/>
            </div>

            <div class="clear"></div>
            <input type="button" value="登录" onclick="login()"/>
        </form>
    </div>
</div>
<div class="footer">
    <p>段子手168 版权所有Copyright 2024-9-1  All Rights Reserved </p>
</div>
</body>
<script type="text/javascript">
    function login() {
        $.ajax({
            type: 'POST',
            url: '/login',
            dataType: 'json',
            data: {
                username: $("#username").val(),
                password: $("#password").val()
            },
            success: function (data) {
                if (data.success) {
                    window.location.href = "chat.jsp";
                } else {
                    alert(data.message);
                }
            }
        });
    }

</script>
</html>
<!-- project_tomcat\dzs168_chat_room\web\login.jsp -->

3、项目 dzs168_chat_room 中,chat.jsp 页面。

java 复制代码
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="format-detection" content="telephone=no">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta content="yes" name="apple-mobile-web-app-capable">
    <meta content="yes" name="apple-touch-fullscreen">
    <meta name="full-screen" content="yes">
    <meta content="default" name="apple-mobile-web-app-status-bar-style">
    <meta name="screen-orientation" content="portrait">
    <meta name="browsermode" content="application">
    <meta name="msapplication-tap-highlight" content="no">
    <meta name="x5-orientation" content="portrait">
    <meta name="x5-fullscreen" content="true">
    <meta name="x5-page-mode" content="app">
    <base target="_blank">
    <title>段子手168-聊天室</title>
    <link href="css/bootstrap.min.css" rel="stylesheet" type="text/css"/>
    <link rel="stylesheet" href="css/chat.css">
    <script src="js/jquery-1.9.1.min.js"></script>

    <script type="text/javascript">
        <%
            String name = session.getAttribute("username")+"";
        %>
        var self = "<%= name %>";
    </script>
    <script type="text/javascript" src="js/ws.js"></script>
</head>

<body  onload="startWebSocket(self);">

<img style="width:100%;height:100%" src="img/chat_bg.jpg">

<div class="abs cover contaniner">
    <div class="abs cover pnl">
        <div class="top pnl-head" style="padding: 20px ; color: white;" id="userName"></div>
        <div class="abs cover pnl-body" id="pnlBody">
            <div class="abs cover pnl-left">
                <div class="abs cover pnl-msgs scroll" id="show">
                    <div class="pnl-list" id="hists"><!-- 历史消息 --></div>
                    <div class="pnl-list" id="msgs">
                        <!-- 消息这展示区域 -->
                    </div>
                </div>

                <div class="abs bottom pnl-text">
                    <div class="abs cover pnl-input">
                        <textarea class="scroll" id="context_text" onkeydown="sendMessage(self)" wrap="hard" placeholder="在此输入文字信息..."></textarea>
                        <div class="abs atcom-pnl scroll hide" id="atcomPnl">
                            <ul class="atcom" id="atcom"></ul>
                        </div>
                    </div>

                    <div class="abs br pnl-btn" id="submit" style="background-color: rgb(32, 196, 202); color: rgb(255, 255, 255);" onclick="sendMsg(self)">
                        发送
                    </div>
                    <div class="pnl-support" id="copyright"><a href="http://www.itcast.cn">段子手168,版本所有</a></div>
                </div>
            </div>

            <div class="abs right pnl-right">
                <div class="slider-container hide"></div>
                <div class="pnl-right-content">
                    <div class="pnl-tabs">
                        <div class="tab-btn active" id="hot-tab">好友列表</div>
                    </div>
                    <div class="pnl-hot">
                        <ul class="rel-list unselect" id="userlist">
                        </ul>
                    </div>

                </div>

                <div class="pnl-right-content">
                    <div class="pnl-tabs">
                        <div class="tab-btn active">系统广播</div>
                    </div>
                    <div class="pnl-hot">
                        <ul class="rel-list unselect" id="broadcastList">
                        </ul>
                    </div>
                </div>

            </div>
        </div>
    </div>
</div>
</body>
</html>
<!-- project_tomcat\dzs168_chat_room\web\chat.jsp -->

4、在项目 dzs168_chat_room 中,创建 用户登录的 servlet 类 LoginServlet.java

bash 复制代码
/**
 *  project_tomcat\dzs168_chat_room\src\djh\it\servlet\LoginServlet.java
 *
 *  2024-9-1 创建 用户登录的 servlet 类 LoginServlet.java
 */

package djh.it.servlet;

import com.alibaba.fastjson.JSON;

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 java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@WebServlet(name = "loginServlet",urlPatterns = "/login")
public class LoginServlet extends HttpServlet {

    private static final String PASSWORD = "dzs168";

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //处理中文乱码问题
        resp.setCharacterEncoding("UTF-8");

        //1. 接收页面传递的参数 , 用户名/密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        Map resultMap = new HashMap();
        //2. 判定用户名密码是否正确
        //3. 如果正确, 响应登录成功的信息
        if(PASSWORD.equals(password)){
            resultMap.put("success",true);
            resultMap.put("message","登录成功");

            req.getSession().setAttribute("username",username);
        }else{//4. 如果不正确, 响应登录失败的信息
            resultMap.put("success",false);
            resultMap.put("message","用户名或密码错误");
        }

        //5. 响应数据
        resp.getWriter().write(JSON.toJSONString(resultMap));

    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }
}

5、运行 tomcat 服务,进行测试。浏览器地址栏输入:localhost:8080/ 输入错误密码 和 正确密码,分别进行测试。

二、Tomcat专题 - WebSocket - 案例 - OnOpen

1、在项目 dzs168_chat_room 中,工具类 MessageUtil.java

bash 复制代码
/**
 *  project_tomcat.dzs168_chat_room.src.djh.it.utils.MessageUtil.java
 *
 *  2024-9-2 工具类 MessageUtil.java
 */
package djh.it.utils;

import com.alibaba.fastjson.JSON;

import java.util.HashMap;
import java.util.Map;

public class MessageUtil {

    public final static String TYPE = "type";
    public final static String DATA = "data";
    public final static String FROM_NAME = "fromName";
    public final static String TO_NAME = "toName";

    public final static String TYPE_MESSAGE = "message";
    public final static String TYPE_USER = "user";


    //组装消息, 然后返回一个json格式的消息数据
    public static String getContent(String type, String fromName, String toName, String content) {
        Map<String, Object> userMap = new HashMap<String, Object>();
        userMap.put(MessageUtil.TYPE, type);
        userMap.put(MessageUtil.DATA, content);
        userMap.put(MessageUtil.FROM_NAME, fromName);
        userMap.put(MessageUtil.TO_NAME, toName);

        String jsonMsg = JSON.toJSONString(userMap);
        return jsonMsg;
    }
}

2、在项目 dzs168_chat_room 中,创建 获取 HttpSession 的 GetHttpSessionConfigurator.java 类,

bash 复制代码
/**
 *  project_tomcat\dzs168_chat_room\src\djh\it\websocket\GetHttpSessionConfigurator.java
 *
 *  2024-9-2 创建 获取 HttpSession 的 GetHttpSessionConfigurator.java 类,
 */

package djh.it.websocket;

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;

public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {

    @Override  //重写方法
    public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        config.getUserProperties().put(HttpSession.class.getName(),httpSession);
    }
}

3、在项目 dzs168_chat_room 中,创建 websocket 类 ChatSocket.java

bash 复制代码
/**
 *   project_tomcat\dzs168_chat_room\src\djh\it\websocket\ChatSocket.java
 *
 *   2024-9-2 创建 websocket 类 ChatSocket.java
 */

package djh.it.websocket;

import djh.it.utils.MessageUtil;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;

@ServerEndpoint(value = "/websocket",configurator = GetHttpSessionConfigurator.class )
public class ChatSocket {

    private  Session session;
    private  HttpSession httpSession;

    //保存当前系统中登录的用户的HttpSession信息, 及对应的Endpoint实例信息
    private static Map<HttpSession , ChatSocket> onlineUsers = new HashMap<HttpSession, ChatSocket>();
    private static int onlineCount = 0;

    @OnOpen
    public void onOpen(Session session, EndpointConfig config){

        //1. 记录webSocket的会话信息对象Session
        this.session = session;

        //2. 获取当前登录用户HttpSession信息.
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        this.httpSession = httpSession;

        System.out.println("当前登录用户 : " + httpSession.getAttribute("username") +", Endpoint : " +hashCode());

        //3. 记录当前登录用户信息, 及对应的Endpoint实例
        if (httpSession.getAttribute("username") != null){
            onlineUsers.put(httpSession,this);
        }

        //4. 获取当前所有登录用户 --------> DZS168,dzs,TOM...
        String names = getNames();

        //5. 组装消息 ---> {"data":"dzs168,Deng,study","toName":"","fromName":"","type":"user"}
        String message = MessageUtil.getContent(MessageUtil.TYPE_USER, "", "", names);

        //6. 通过广播的形式发送消息
        //session.getBasicRemote().sendText("");
        broadcastAllUsers(message);

        //7. 记录当前用户登录数 .
        incrCount();

    }

    // 发送广播消息
    private void broadcastAllUsers(String message) {

        for (HttpSession hsession : onlineUsers.keySet()) {
            try {
                onlineUsers.get(hsession).session.getBasicRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    //获取所有的在线用户
    private String getNames() {
        String names = "";
        if(onlineUsers.size()>0){
            for (HttpSession hsession : onlineUsers.keySet()) {
                String username = (String) hsession.getAttribute("username");
                names += username+",";
            }
        }
        return names.substring(0,names.length()-1);
    }

    public int getOnlineCount(){
        return onlineCount;
    }

    public synchronized void incrCount(){
        onlineCount ++;
    }

    public synchronized void decrCount(){
        onlineCount --;
    }

}

三、Tomcat专题 - WebSocket - 案例 - OnOpen测试

1、运行 tomcat 服务,进行测试。观察控制台输出结果。

2、多个 浏览器地址栏输入:localhost:8080/ 进行测试,观察控制台输出结果。

上一节关联链接请点击
# 利刃出鞘_Tomcat 核心原理解析(十一)-- WebSocket -- 1
利刃出鞘_Tomcat 核心原理解析(十)-- Tomcat 性能调优--2

相关推荐
懒人村杂货铺25 分钟前
✅ WebSocket 接口从本地开发到生产部署的关键步骤与常见问题
websocket
奋进的芋圆1 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin2 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20052 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉2 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国2 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882483 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈3 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_993 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹3 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理