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

news2024/11/22 23:00:28

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

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

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


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

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


<%@ 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 页面。

<%@ 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

/**
 *  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-74.png

tomcat-75.png

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

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

/**
 *  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 类,

/**
 *  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

/**
 *   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 服务,进行测试。观察控制台输出结果。

tomcat-76.png

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

tomcat-77.png

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2098756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

花生壳的登录及获取二级域名

1、下载花生壳客户端 2、安装完毕 3、扫码登录 4、微信登录花生壳管理后台 5、二级域名的注册 已经帮我们自动生成了一个免费的二级域名。 我们可以用这个二级域名快速的建立网站了。

[YM]课设-C#-WebApi-Vue-员工管理系统 (七)员工统计表

前端&#xff1a; 注&#xff1a;这里主要解释下echarts组件&#xff0c;需要一定的Vue基础 emmmmm 明显能看到上面写“对不起暂未开发” 是的 这个是博主自己加上去的 but 这个统计表也是类似于Element UI的小组件 Element&#xff1a;Element - 网站快速成型工具 &am…

Quartz.Net_依赖注入

简述 有时会遇到需要在IJob实现类中依赖注入其他类或接口的情况&#xff0c;但Quartz的默认JobFactory并不能识别具有有参构造函数的IJob实现类&#xff0c;也就无法进行依赖注入 需要被依赖注入的类&#xff1a; public class TestClass {public TestClass(Type jobType, s…

Python 从入门到实战5(列表的其它操作)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;通过熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 之前的文章我们通过举例学习了python 中列表的简单操作&#xff0…

虚拟机输入ip addr不显示IP地址

本机配置 Window10 VMware Workstation 17 CentOS 7 虚拟机输入ip addr查询不到ip地址&#xff08;下图&#xff09; 解决办法&#xff1a; 查看配置文件&#xff0c;输入下面命令(用于编辑文件) vi /etc/sysconfig/network-scripts/ifcfg-ens33进入配置配置文件&#xf…

交叉编译 gmp

文章目录 交叉编译 gmp1 概述2 源码下载2.1 官网下载2.2 使用 apt source 下载 3 交叉编译4 关于 DESTDIR 的说明 交叉编译 gmp 1 概述 GMP (GNU Multiple Precision Arithmetic Library) 是一个用于任意精度计算设计的数学库&#xff0c;它的主要目标应用是密码学应用和研究…

ARP协议和DNS的工作原理

ARP协议 ARP协议的工作原理&#xff1a; 首先主机向自己的网络广播发送一个arp请求&#xff0c;请求报文包括目的端的ip地址和目的端的以太网地址。网络上的其他机器收到这个请求&#xff0c;但只有被请求的才会回应一个应答报文&#xff0c;报文中有自己的物理地址。 arp维护了…

【python因果推断库1】协方差分析(ANCOVA)用于处理前/后非等效组设计

目录 生成合成数据 分析 这是一个基于合成数据的初步示例。希望不久之后能用真实研究的数据进行更新。 在只有一次预处理测量和一次后处理测量的情况下&#xff0c;我们可以使用类似于协方差分析(ANCOVA)的方法来分析非等效组设计(NEGD)实验的数据。基本模型是&#xff1a; i指…

Vue(五). 安装脚手架及一些基本配置

文章目录 vue脚手架前言1. 安装脚手架1. 安装nvm2. 使用nvm安装node3. 配置node的全局路径和缓存路径4. 配置npm默认镜像源5. 安装脚手架全局路径和缓存测试 2. 文件结构及项目配置2.1 文件结构2.2 项目基本配置补充. vue项目安装依赖的一个问题 vue脚手架前言 脚手架也叫Vue …

敏捷需求管理,推动敏捷项目成功——Leangoo领歌敏捷工具

在敏捷项目管理中&#xff0c;需求管理是决定项目成功的关键环节。准确捕捉和高效管理需求&#xff0c;不仅能避免项目偏航&#xff0c;还能确保最终交付的产品与客户预期高度契合。Leangoo领歌敏捷工具&#xff0c;正是为此而生&#xff0c;助力团队轻松实现需求管理的每一步。…

vue中使用原生的video播放flv和mp4格式的视频

安装 npm i flv.js html <video v-if"videoId"controls id"videoElement"preload"metadata"controlslist"nodownload noremoteplayback" ><source :type"video/${videoType}" />您的浏览器不支持HTML5视频播…

Ansible一键安装Harbor服务

环境说明 企业内网环境,使用docker-compose的方式安装Harbor服务,需要先安装docker、docker-compose两个服务,将以二进制的方式安装docker和docker-compose,以适配各种安装环境。 docker版本:20.10.21,建议使用20.10以上的版本,低版本的会出现安装异常;Docker-compose版…

记一次ssh伪终端修改为shell

问题 用户ssh进行连接后&#xff0c;默认为伪终端。 解决办法&#xff0c;可以先拿到终端shell&#xff0c;查看用户是否为/bin/bash&#xff1a; 不是/bin/bash&#xff0c;使用如下命令进行修改&#xff1a; chsh -s /bin/bash rootservice sshd restart

在繁忙工作环境中提升开发效率:JetBrains IntelliJ IDEA 的应用

目录 前言1. IntelliJ IDEA 的核心功能1.1 智能代码补全&#xff1a;提升编码效率的利器1.2 深度代码分析&#xff1a;防患于未然1.3 代码重构&#xff1a;保持代码整洁有序 2. 提升团队协作与项目管理2.1 集成版本控制&#xff1a;高效的团队协作2.2 内置任务管理&#xff1a;…

开店到经营,分贝通帮助连锁经营企业这样省钱

如果说大企业的经营核心是做好主营业务的大生意,那么对于连锁经营企业而言,线下门店的一个个小生意,其实也隐藏着“大学问”。费用支出方面,如何从细节处节流,让资金流呈现更良性循环,是连锁经营行业的重要课题。 1、开店前:选址BD全国跑,筐筐发票财务恼 2、日常经营:费用类目…

Qt:玩转QPainter后转之时钟

前言 简单了解了QPainter之后当然是要找两个例子练练手啦。 正文 先看效果图 在绘制之前我们要先构思好自己要绘制的对象可以分成几部分&#xff0c;比如我要绘制时钟的话&#xff0c;我可以分成&#xff1a;外边框(圆环或者圆)&#xff0c;圆形背景&#xff0c;刻度&…

MySQL 使用C语言链接

mysql的基础&#xff0c;我们之前已经学过&#xff0c;后面我们只关心使用 要使用C语言连接mysql&#xff0c;需要使用mysql官网提供的库&#xff0c;大家可以去官网下载 我们使用C接口库来进行连接 要正确使用&#xff0c;我们需要做一些准备工作&#xff1a; 保证mysql服务有…

【WPF】WPF学习之【二】布局学习

WPF布局学习 常用布局Grid网格布局StackPanel 布局CanvasDockPanel布局WrapPanel布局 常用布局 1、StackPanel: 学习如何使用StackPanel进行垂直和水平布局。 2、Grid: 掌握Grid的网格布局技术。 3、Canvas: 了解Canvas的绝对定位布局。 4、DockPanel: 学习DockPanel的停靠…

【加密社】马后炮视角来看以太坊二层战略

阅读正文前先给大家普及下知识&#xff0c;以下文章中提到的 Blobs指的是&#xff1a;"Blob Carriers" 或 "Calldata Blobs" 这是在以太坊网络中用于携带数据的一种方式&#xff0c;尤其是在涉及Rollup&#xff08;如Optimistic Rollup和ZK-Rollup&#xf…

数据结构-复杂度

数据结构&#xff1a;在内存中管理数据&#xff0c;内存速度快&#xff0c;带电存储 数据库&#xff1a;在磁盘中管理数据&#xff0c;磁盘速度慢&#xff0c;不带电存储 时间复杂度 大O的渐进表示法&#xff1a;忽略常数、系数&#xff0c;保留最高次数项 如果只有常数&am…