首页 > 其他分享 ># 利刃出鞘_Tomcat 核心原理解析(十一)-- Tomcat 附加功能 WebSocket -- 3

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

时间:2024-09-19 15:19:27浏览次数:14  
标签:toName WebSocket String Tomcat -- fromName session hsession message

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

一、Tomcat专题 - WebSocket - 案例 - OnMessage分析

1、WebSocket DEMO 案例 实现流程分析:OnMessage 分析

tomcat-72.png

2、在项目 dzs168_chat_room 中,在 websocket 类 ChatSocket.java 中,

创建 public void onMessage(String message, Session session) {…} 方法。分析流程。


    //{"fromName":"Deng","toName":"HEIMA","content":"约会呀"}
    @OnMessage
    public  void onMessage(String message, Session session) {
       
        //1. 获取客户端的信息内容, 并解析
       
        //2. 判定是否有接收人
        
        //3. 如果接收人是否是广播(all), 如果是, 则说明发送广播消息
       
	    //4. 不是all , 则给指定的用户推送消息
       
    }

二、Tomcat专题 - WebSocket - 案例 - OnMessage功能实现

1、在项目 dzs168_chat_room 中,在 websocket 类 ChatSocket.java 中,

完成 onMessage(String message, Session session) {…} 方法代码编写。


    //{"fromName":"Deng","toName":"HEIMA","content":"约会呀"}
    @OnMessage
    public  void onMessage(String message, Session session) throws IOException {
        System.out.println("onMessage : name = " + httpSession.getAttribute("username")+ ", message=" + message );
        //1. 获取客户端的信息内容, 并解析
        Map<String,String> messageMap = JSON.parseObject(message, Map.class);
        String fromName = messageMap.get("fromName");
        String toName = messageMap.get("toName");
        String content = messageMap.get("content");

        //2. 判定是否有接收人
        if(toName == null || toName.isEmpty()){
            return;
        }

        //3. 如果接收人是否是广播(all), 如果是, 则说明发送广播消息
        String messageContent = MessageUtil.getContent(MessageUtil.TYPE_MESSAGE, fromName, toName, content);
        System.out.println("服务端给客户端发送消息, 消息内容: " + messageContent);
        if("all".equals(toName)){
            //3.1 组装消息内容
            broadcastAllUsers(messageContent);
        }else{//4. 不是all , 则给指定的用户推送消息
            singlePushMessage(messageContent, fromName,toName);
        }

    }

2、在项目 dzs168_chat_room 中,在 websocket 类 ChatSocket.java 中,

创建 //给指定用户推送消息 private void singlePushMessage(String content, String fromName, String toName) throws IOException {…} 方法,并完成代码编写。


    //给指定用户推送消息
    private void singlePushMessage(String content, String fromName, String toName) throws IOException {
        boolean isOnline = false;
        //1. 判定当然接收人是否在线
        for (HttpSession hsession : onlineUsers.keySet()) {
            if(toName.equals(hsession.getAttribute("username"))){
                isOnline = true;
            }
        }

        //2. 如果存在, 发送消息
        if(isOnline){
            for (HttpSession hsession : onlineUsers.keySet()) {
                if (hsession.getAttribute("username").equals(fromName) || hsession.getAttribute("username").equals(toName)){
                    onlineUsers.get(hsession).session.getBasicRemote().sendText(content);
                }
            }
        }

    }

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 com.alibaba.fastjson.JSON;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
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();

    }

    //{"fromName":"Deng","toName":"HEIMA","content":"约会呀"}
    @OnMessage
    public  void onMessage(String message, Session session) throws IOException {
        System.out.println("onMessage : name = " + httpSession.getAttribute("username")+ ", message=" + message );
        //1. 获取客户端的信息内容, 并解析
        Map<String,String> messageMap = JSON.parseObject(message, Map.class);
        String fromName = messageMap.get("fromName");
        String toName = messageMap.get("toName");
        String content = messageMap.get("content");

        //2. 判定是否有接收人
        if(toName == null || toName.isEmpty()){
            return;
        }

        //3. 如果接收人是否是广播(all), 如果是, 则说明发送广播消息
        String messageContent = MessageUtil.getContent(MessageUtil.TYPE_MESSAGE, fromName, toName, content);
        System.out.println("服务端给客户端发送消息, 消息内容: " + messageContent);
        if("all".equals(toName)){
            //3.1 组装消息内容
            broadcastAllUsers(messageContent);
        }else{//4. 不是all , 则给指定的用户推送消息
            singlePushMessage(messageContent, fromName,toName);
        }

    }

    //给指定用户推送消息
    private void singlePushMessage(String content, String fromName, String toName) throws IOException {
        boolean isOnline = false;
        //1. 判定当然接收人是否在线
        for (HttpSession hsession : onlineUsers.keySet()) {
            if(toName.equals(hsession.getAttribute("username"))){
                isOnline = true;
            }
        }

        //2. 如果存在, 发送消息
        if(isOnline){
            for (HttpSession hsession : onlineUsers.keySet()) {
                if (hsession.getAttribute("username").equals(fromName) || hsession.getAttribute("username").equals(toName)){
                    onlineUsers.get(hsession).session.getBasicRemote().sendText(content);
                }
            }
        }

    }


    // 发送广播消息
    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 - 案例 - OnMessage功能测试

1、项目 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  onl oad="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 -->

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 中,//定义全局的webSocket对象 ws.js 源码。

…\project_tomcat\dzs168_chat_room\web\js\ws.js



//定义全局的webSocket对象
var ws = null;

function startWebSocket(self) {
    //构建WebSocket对象
    if ('WebSocket' in window) {
        ws = new WebSocket("ws://localhost:8080/websocket");
    } else if ('MozWebSocket' in window) {
        ws = new MozWebSocket("ws://localhost:8080/websocket");
    } else {
        alert("not support");
    }

    //监听消息, 有消息传递, 会触发此方法
    ws.onmessage = function (evt) {
        var _data = evt.data;
        console.log(">> : " + _data);

        var o = JSON.parse(_data);

        if (o.type == 'message') { //如果后端, 响应的是消息, 在页面展示
            setMessageInnerHTML(o, self);
        } else if (o.type == 'user') { // 如果服务端响应的是用户列表, 在界面展示用户列表
            var userArry = o.data.split(',');
            $("#userlist").empty();
            $("#userlist").append('<li class="rel-item"><input type="radio" name="toUser" value="all">广播</input></li>');
            $.each(userArry, function (n, value) {
                if (value != self && value != 'admin') {
                    $("#userlist").append('<li class="rel-item"><input type="radio"  name="toUser" value="'+value+'">'+value+'</input></li>');

                    $("#broadcastList").append('<li class="rel-item">您的好友 '+value+' 已上线</li>');
                }
            });
        }
    };

    //关闭链接时触发
    ws.onclose = function (evt) {
        $('#userName').html("用户: "+ self +"<span style='float: right;color: red'>离线</span>");
    };

    //打开时触发
    ws.onopen = function (evt) {
        $('#userName').html("用户: "+ self +"<span style='float: right;color: green'>在线</span>");
    };
}

function setMessageInnerHTML(msg, self) {

    //根据后台响应的数据, 判定是展示在左侧还是右侧.
    var str = "";

    if(msg.toName == 'all'){
        $("#broadcastList").append('<li class="rel-item"> 系统广播消息: '+msg.data+' </li>');
    }else if (msg.fromName == self) {
        str = "<div class=\"msg guest\"><div class=\"msg-right\"><div class=\"msg-host headDefault\"></div><div class=\"msg-ball\" title=\"今天 17:52:06\">" + msg.data + "</div></div></div>"
    } else if(msg.toName == self){
        str = "<div class=\"msg robot\"><div class=\"msg-left\" worker=\"" + msg.fromName + "\"><div class=\"msg-host photo\" style=\"background-image: url(../img/avatar/Member002.jpg)\"></div><div class=\"msg-ball\" title=\"今天 17:52:06\">" + msg.data + "</div></div></div>";
    }

    //获取到现有的内容, 追加新的消息内容
    var msgs = document.getElementById("msgs");
    msgs.innerHTML = msgs.innerHTML + str;


    //判定消息来源的用户 , 勾选对应的好友信息
    var a = $('input[name="toUser"]');
    for(var i=0 ; i < a.length ; i++){
        if(a[i].value == msg.fromName){
            console.log(a[i]);
            a[i].checked='checked';
        }
    }
}

// 组装消息, 发送消息
function sendMsg(self) {
    var content = $("#context_text").val();

    if(!content){
        alert('请输入消息内容');
        return ;
    }

    var message = {};
    message.fromName = self;
    message.toName = $('input:radio:checked').val();  //根据界面勾选的用户, 来决定消息发送给谁
    message.content = content; //获取输入文本框中输入的内容
    var msg = JSON.stringify(message);

    console.log(" msg: "+msg);

    ws.send(msg);//发送消息
    $("#context_text").val(''); //将输入框内容置为空
}

function sendMessage(self){
    if(event.keyCode == 13){
        sendMsg(self);
    }
}

4、运行 tomcat 服务,进行测试。

5、多个 浏览器地址栏输入:localhost:8080/ 登录几个不同用户,进行测试。

tomcat-78.png

tomcat-79.png

四、Tomcat专题 - WebSocket - 案例 - OnClose及OnError介绍

1、在项目 dzs168_chat_room 中,在 websocket 类 ChatSocket.java 中,

创建 public void onClose(Session session, CloseReason closeReason){…} 方法。


    @OnClose
    public void onClose(Session session, CloseReason closeReason){
        decrCount();
        System.out.println("客户端关闭了一个连接 , 当前在线人数 : " + getOnlineCount());
    }

2、在项目 dzs168_chat_room 中,在 websocket 类 ChatSocket.java 中,

创建 public void one rror(Session session, Throwable throwable){…} 方法。


    @OnError
    public void one rror(Session session, Throwable throwable){
        throwable.printStackTrace();
        System.out.println("服务异常");
    }

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 com.alibaba.fastjson.JSON;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
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();

    }

    //{"fromName":"Deng","toName":"HEIMA","content":"约会呀"}
    @OnMessage
    public  void onMessage(String message, Session session) throws IOException {
        System.out.println("onMessage : name = " + httpSession.getAttribute("username")+ ", message=" + message );
        //1. 获取客户端的信息内容, 并解析
        Map<String,String> messageMap = JSON.parseObject(message, Map.class);
        String fromName = messageMap.get("fromName");
        String toName = messageMap.get("toName");
        String content = messageMap.get("content");

        //2. 判定是否有接收人
        if(toName == null || toName.isEmpty()){
            return;
        }

        //3. 如果接收人是否是广播(all), 如果是, 则说明发送广播消息
        String messageContent = MessageUtil.getContent(MessageUtil.TYPE_MESSAGE, fromName, toName, content);
        System.out.println("服务端给客户端发送消息, 消息内容: " + messageContent);
        if("all".equals(toName)){
            //3.1 组装消息内容
            broadcastAllUsers(messageContent);
        }else{//4. 不是all , 则给指定的用户推送消息
            singlePushMessage(messageContent, fromName,toName);
        }

    }

    //给指定用户推送消息
    private void singlePushMessage(String content, String fromName, String toName) throws IOException {
        boolean isOnline = false;
        //1. 判定当然接收人是否在线
        for (HttpSession hsession : onlineUsers.keySet()) {
            if(toName.equals(hsession.getAttribute("username"))){
                isOnline = true;
            }
        }

        //2. 如果存在, 发送消息
        if(isOnline){
            for (HttpSession hsession : onlineUsers.keySet()) {
                if (hsession.getAttribute("username").equals(fromName) || hsession.getAttribute("username").equals(toName)){
                    onlineUsers.get(hsession).session.getBasicRemote().sendText(content);
                }
            }
        }

    }


    // 发送广播消息
    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);
    }


    @OnClose
    public void onClose(Session session, CloseReason closeReason){
        decrCount();
        System.out.println("客户端关闭了一个连接 , 当前在线人数 : " + getOnlineCount());
    }


    @OnError
    public void one rror(Session session, Throwable throwable){
        throwable.printStackTrace();
        System.out.println("服务异常");
    }


    public int getOnlineCount(){
        return onlineCount;
    }

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

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

}

4、重新运行 tomcat 服务,多个 浏览器地址栏输入:localhost:8080/ 登录几个不同用户,再退出登录,进行测试。

tomcat-80.png

tomcat-81.png

上一节关联链接请点击

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

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

标签:toName,WebSocket,String,Tomcat,--,fromName,session,hsession,message
From: https://blog.csdn.net/qfyh_djh/article/details/142342032

相关文章

  • NOTES
    二叉树对于任意一棵二叉树,满足度数为\(2\)的节点数是度数为叶子数量减\(1\)。一棵度数为\(k\)的树,设度数为\(1,2,3\dots\)的节点数分别为\(w_1,w_2,w_3\dots\)该树节点数为\(\sum\limits_{i-1}^kw_i\timesi+1\)。原理:一棵树的节点数量\(n\)等于所有儿子数量\(+......
  • 国产数据库VastBase适配指南
     背景  目前数据库市场上,仍然是甲骨文、IBM为代表的国外数据库软件处于主导地位,国产化的数据库的使用率,与推广面很有限。相对于主流数据库而言,国产数据库的优势并不明显,还有相当远的距离。那么我们为什么要用国产数据库呢?因为数据安全。相对于其它新特性而言,安全尤为重要。数......
  • reids安装部署
    一、安装tar包1.下载文件https://redis.io/downloads/2.解压文件tar-zxvfredis-7-C/opt/module/redis3.安装编译make&&makeinstall4.管理redis创建bin和etc文件夹bin:用于存放可执行文件etc:用于存放redis.conf文件5.移动文件#移动配置文件mvredis.c......
  • 易优eyoucms网站报错 /core/library/think/db/Connection.php 第 389 行左右,如何解决?
    SQLSTATE[42S22]:Columnnotfound:1054Unknowncolumn'groupid'in'whereclause'遇到“SQLSTATE[42S22]:Columnnotfound:1054Unknowncolumn'groupid'in'whereclause'”这类错误,通常是因为数据库表结构与代码中的查询不匹配。具体来说,可能是数据库表中缺少某个列......
  • 如何用Python将HTTP接口封装成可视化页面。
        在软件行业中,经常会遇到有一些功能只能通过接口触发,没有页面。这样很不方便,。我们这里,就是通过PyQt5实现,将接口的入参,封装成一个可视化的表单。将用户在表单中填写的数据,传给接口,接口再带参请求业务 1.先看最终的效果,用户打开桌面应用后,只会出现下面的弹窗, 接口......
  • 易优eyoucms网站php5.4版本,报错:Can't use method return value in write context
    当你在使用PHP5.4版本时遇到“Can'tusemethodreturnvalueinwritecontext”的错误,这通常是因为你在代码中错误地使用了方法返回值。这种错误通常发生在试图将方法返回值直接赋值给变量或用于其他上下文时。解决方案以下是一些常见的原因和解决方法:1.检查代码中的赋......
  • jeecg v3 表格自定义按钮打开Modal并传参
    List列表页面行内添加自定义按钮,弹出自定义页面分五步1.在template里加入<UrAdspotsMapModal@register="register4"/>2.在脚本中importimportUrAdspotsMapModalfrom'./components/UrAdspotsMapModal.vue'3.在script里注册const[register4,{openMo......
  • 汇总区间
    给定一个有序的list,需要根据数据的连续性进行区间的汇总实例如下: 解决方法:设置左右指针,固定左指针,当右指针对应的数+1=右指针+1对应的数and 右指针不要越界,就移动右指针,直到跳出while,并更新左指针=右指针+1classSolution(object):defsummaryRange......
  • [1065] Reverse geocoding in python
    ToimplementreversegeocodinginPython,youcanusethegeopylibrary,whichprovidesaconvenientinterfaceforvariousgeocodingservices.Here’sastep-by-stepguidetohelpyougetstarted:Step-by-StepGuideInstallthegeopylibrary:pipinstall......
  • 【LeetCode Hot 100】4. 寻找两个正序数组的中位数
    题目描述要求出两个数组的中位数,第一想法当然是将这两个数组进行归并排序,然后直接得到排序后长数组的中位数。由于本题的两个数组都是排序后的数组,因此省去了排序的步骤。这种方法的时间复杂度为\(O(m+n)\),空间复杂度由于要存储排序后的长数组,所以也是\(O(m+n)\)。有没有相对更......