JRT多平台初始化程序

news2024/11/22 21:38:53

这么多年客户端一直只做Windows,所以初始化程序用C#写个Exe,按网站生成的下载清单文件一个个下载和部署客户端环境是可以的。新的由于设计目标就是支持多平台的,所以需要重新考虑初始化设计。

JRT-Linux初始化演示

JRT-Windows初始化演示

设计目标有以下:
1.方便更新客户端程序的单个文件
2.多平台初始化体验接近
3.不能运行脚本的电脑也要让手工能下载压缩包自己放程序
4.尽可能少占用服务器空间
5.服务器上程序修改之后要能自动更新下载的zip包

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

文件布局
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

压缩包生成目录,在加载环境下载页面时候会检查是否需要生成压缩包文件,下列情况会触发生成新压缩包:
1.download/clienttmp目录没windows.zip或linux.zip
2.download/data目录没linuxinitjrt.sh或windowsinitjrt.ps1
3.download/client下文件比download/clienttmp目录没windows.zip或linux.zip新
在这里插入图片描述
环境下载页检查之后生成的压缩包
在这里插入图片描述

在线初始化脚本的模板
linux

#!/bin/bash
#shell在linux上初始化jrt
#20240413
#zlz
#initfile由程序构造初始化脚本时候替换成下载文件命令
#----------------------------------------------------------
rm -y /usr/share/JRTBase/linux.zip
${initfile}
cd /usr/share/JRTBase
unzip linux.zip
#调用本地初始化脚本
touch /usr/share/JRTBase/linux/inlinecall.flag
#调用本地初始化脚本
bash /usr/share/JRTBase/linux/install.sh


windows

#get-executionpolicy
#set-executionpolicy remotesigned
Add-Type -TypeDefinition @"  
    using System.Net;  
    using System.Security.Cryptography.X509Certificates;  
    public class TrustAllCertsPolicy : ICertificatePolicy {  
        public bool CheckValidationResult(  
            ServicePoint srvPoint, X509Certificate certificate,  
            WebRequest request, int certificateProblem) {  
            return true;  
        }  
    }  
"@  

[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12  
Write-Host "Welcome to the JRT-Windows initialization script, which will perform initialization operations"
Write-Host "downloading windows.zip please wait"
${initfile}
Write-Host "unzip windows.zip"
Expand-Archive -Path 'C:\JRTBase\windows.zip' -DestinationPath 'C:\JRTBase'
Write-Host "copy link to desktop"
$sourcePath = "C:\JRTBase\windows\JRTClient-win\JRTClient.lnk" 
$desktopPath = [Environment]::GetFolderPath("Desktop")
Copy-Item -Path $sourcePath -Destination $desktopPath
$sourcePath = "C:\JRTBase\windows\JRTBrowser-win32-ia32\JRTLogin.lnk" 
$desktopPath = [Environment]::GetFolderPath("Desktop")
Copy-Item -Path $sourcePath -Destination $desktopPath
& "C:\JRTBase\windows\JRTClient-win\JRTClient.exe"
& "C:\JRTBase\windows\JRTBrowser-win32-ia32\JRTBrowser.exe"
Remove-Item -Path "C:\JRTBase\windows.zip"
Write-Host "JRT InitEnd"
Pause

linux的install脚本,windows由于可以任意运行,只要发快捷方法,就不提供本地install了

#!/bin/bash
#shell安装LISClient脚本
#20221125
#zlz
#----------------------------------------------------------
#检测安装dotnet5


mypath=$(cd $(dirname ${BASH_SOURCE[0]}); pwd )
echo "当前路径:${mypath}"
#没有在线标志文件,认为是本地执行初始化脚本
if [ ! -f /usr/share/JRTBase/linux/inlinecall.flag ];then
	echo "执行本地安装"
	echo "创建文件夹/usr/share/JRTBase"
	mkdir /usr/share/JRTBase
	echo "创建文件夹/usr/share/JRTBase/linux"
	mkdir /usr/share/JRTBase/linux
	echo "拷贝${mypath}/JRTBrowser-linux-x64到/usr/share/JRTBase/linux"
	cp -r ${mypath}/JRTBrowser-linux-x64 /usr/share/JRTBase/linux
	echo "拷贝${mypath}/JRTClient-linux到/usr/share/JRTBase/linux"
	cp -r ${mypath}/JRTClient-linux /usr/share/JRTBase/linux
fi
#删除在线调用标识
rm /usr/share/JRTBase/linux/inlinecall.flag

#初始化浏览器
echo "授权执行权限"
sudo chmod -R +777 /usr/share/JRTBase/linux/JRTBrowser-linux-x64/*
echo "创建快捷方式到/usr/share/applications/JRTBrowser.desktop"
sudo cp /usr/share/JRTBase/linux/JRTBrowser-linux-x64/resources/app/JRTBrowser.desktop /usr/share/applications/
echo "授权快捷方式"
sudo chmod +777 /usr/share/applications/JRTBrowser.desktop
echo "让沙箱属于root"
sudo chown -R root:root /usr/share/JRTBase/linux/JRTBrowser-linux-x64/chrome-sandbox
echo "设置沙箱权限"
sudo chmod 4755 /usr/share/JRTBase/linux/JRTBrowser-linux-x64/chrome-sandbox
#给每个用户拷贝快捷方式
HOME_DIR="/home"  
#使用find命令查找名为"桌面"或"Desktop"的目录  
find "${HOME_DIR}" -type d \( -name "桌面" -o -name "Desktop" \) | while read -r DESKTOP_DIR; do  
    echo "${DESKTOP_DIR}/"  
	sudo cp /usr/share/JRTBase/linux/JRTBrowser-linux-x64/resources/app/JRTBrowser.desktop "${DESKTOP_DIR}/" 
	echo "授权快捷方式"
	sudo chmod +777 ${DESKTOP_DIR}/JRTBrowser.desktop
done



#初始化打印导出客户端
echo "授权执行权限"
sudo chmod -R +777 /usr/share/JRTBase/linux/JRTClient-linux/*
echo "创建快捷方式到/usr/share/applications/JRTClient.desktop"
sudo cp /usr/share/JRTBase/linux/JRTClient-linux/app/lib/JRTClient.desktop /usr/share/applications/
echo "授权快捷方式"
sudo chmod +777 /usr/share/applications/JRTClient.desktop
#给每个用户拷贝快捷方式
#使用find命令查找名为"桌面"或"Desktop"的目录  
find "${HOME_DIR}" -type d \( -name "桌面" -o -name "Desktop" \) | while read -r DESKTOP_DIR; do  
    echo "${DESKTOP_DIR}/"  
	sudo cp /usr/share/JRTBase/linux/JRTClient-linux/app/lib/JRTClient.desktop "${DESKTOP_DIR}/" 
	echo "授权快捷方式"
	sudo chmod +777 ${DESKTOP_DIR}/JRTClient.desktop
done

echo "初始化JRT客户端环境完成"

环境下载页后台实现

import JRT.Core.MultiPlatform.JRTContext;
import JRT.Core.Util.DirUtil;
import JRT.Core.Util.TxtUtil;
import JRTBLLBase.BaseHttpHandlerNoSession;
import JRTBLLBase.Helper;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 生成Linux和Windows下初始化环境的脚本,供用户用脚本初始化环境,环境下载页面初始化时候调用此逻辑检查并且生效初始化脚本
 */
public class ashDownLoad extends BaseHttpHandlerNoSession {
    /**
     * 是否正在压缩文件
     */
    private static boolean iszip = false;

    /**
     * 得到所有能下载的文件数据
     *
     * @return
     * @throws Exception
     */
    public String GetAllDataFiles() throws Exception {
        String basePath = Paths.get(JRTContext.WebBasePath, "download", "data").toString();
        File base = new File(basePath);
        List<File> allFile = new ArrayList<>();
        SeeFile(base, allFile);
        List<String> retList = new ArrayList<>();
        if (allFile != null && allFile.size() > 0) {
            for (File f : allFile) {
                retList.add(f.getName());
            }
        }
        return Helper.Object2Json(retList);
    }

    /**
     * 尝试生成初始化脚本
     *
     * @return
     */
    public String TryMakeInitScript() throws Exception {
        String RootPath = Helper.ValidParam(JRT.Core.MultiPlatform.JRTContext.GetRequest(Request, "RootPath"), "");
        //处理所有客户端程序存放目录
        String basePath = Paths.get(JRTContext.WebBasePath, "download", "client").toString();
        //存下载程序的临时目录,所有文件加上.jrt后缀,防止各种类型太多mime限制
        String basePathTmp = Paths.get(JRTContext.WebBasePath, "download", "clienttmp").toString();
        //文件下载目录,最后生成初始化脚本让人下载用
        String dataPath = Paths.get(JRTContext.WebBasePath, "download", "data").toString();
        File linuxZip = Paths.get(basePathTmp, "linux.zip").toFile();
        File windowsZip = Paths.get(basePathTmp, "windows.zip").toFile();
        File base = new File(basePath);
        List<File> allFile = new ArrayList<>();
        SeeFile(base, allFile);
        //是否需要构造新的初始化脚本
        boolean needMakeNewInit = false;
        //压缩文件不存在就需要更新
        if (!linuxZip.exists() || !windowsZip.exists()) {
            needMakeNewInit = true;
        } else {
            //检查并且拷贝文件,生成下载用的临时文件
            if (allFile != null && allFile.size() > 0) {
                for (File f : allFile) {
                    if (f.lastModified() > linuxZip.lastModified() || f.lastModified() > windowsZip.lastModified()) {
                        needMakeNewInit = true;
                    }
                }
            }
        }
        //下载页面后台data文件夹没有下载脚本就生成
        File winInit = Paths.get(dataPath, "windowsinitjrt.ps1").toFile();
        File linuxInit = Paths.get(dataPath, "linuxinitjrt.sh").toFile();
        //构造初始化脚本
        if (needMakeNewInit == true || ((!winInit.exists()) || (!linuxInit.exists()))) {
            System.out.println("开始压缩");
            if (iszip != true) {
                iszip = true;
                try {
                    //压缩linux文件
                    ZipFolder(Paths.get(basePath, "linux").toFile(), linuxZip);
                    //压缩windows文件
                    ZipFolder(Paths.get(basePath, "windows").toFile(), windowsZip);
                    System.out.println("压缩完成");
                    StringBuilder winSB = new StringBuilder();
                    //构造powershell脚本
                    AddOneWinDownload(RootPath + "/download/clienttmp/windows.zip", "windows.zip", "", winSB);
                    //读取win模板命令
                    String winCmd = TxtUtil.ReadTextStr(Paths.get(basePath, "windowsinitjrt.ps1").toString());
                    //替换占位符
                    winCmd = winCmd.replace("${initfile}", winSB.toString());
                    //把命令写入下载地址
                    TxtUtil.WriteText2File(Paths.get(dataPath, "windowsinitjrt.ps1").toFile(), winCmd);

                    StringBuilder liSB = new StringBuilder();
                    //构造sh脚本
                    AddOneLinDownload(RootPath + "/download/clienttmp/linux.zip", "linux.zip", "", liSB);
                    //读取linux模板命令
                    String linuxCmd = TxtUtil.ReadTextStr(Paths.get(basePath, "linuxinitjrt.sh").toString());
                    //替换占位符
                    linuxCmd = linuxCmd.replace("${initfile}", liSB.toString());
                    //把命令写入下载地址
                    TxtUtil.WriteText2File(Paths.get(dataPath, "linuxinitjrt.sh").toString(), linuxCmd);
                } finally {
                    iszip = false;
                }
            }
        }
        return Helper.Success();
    }

    /**
     * 构造Windows下载脚本
     *
     * @param url             路径
     * @param fileName        文件名
     * @param remoteAddrLocal 相对路径
     * @param sb              字符串
     */
    private void AddOneWinDownload(String url, String fileName, String remoteAddrLocal, StringBuilder sb) {
        fileName = fileName.replace(".jrt", "");
        //下载路径
        sb.append("$url = \"" + url + "\" " + "\r\n");
        //本地路径
        sb.append("$localFolder = \"C:\\JRTBase\\" + remoteAddrLocal.replace("/", "\\") + "\" " + "\r\n");
        //本地文件名
        sb.append("$localFileName = \"" + fileName + "\" " + "\r\n");
        //拼接路径
        sb.append("$localFile = Join-Path $localFolder $localFileName" + "\r\n");
        //尝试创建目录
        sb.append("if (!(Test-Path -Path $localFolder -PathType Container)) {  " + "\r\n");
        sb.append("    New-Item -ItemType Directory -Path $localFolder -Force | Out-Null " + "\r\n");
        sb.append("} " + "\r\n");
        //不显示现在进度
        sb.append("$ProgressPreference = 'SilentlyContinue'\n" + "\r\n");
        //执行下载
        sb.append("Invoke-WebRequest -Uri $url -OutFile $localFile" + "\r\n");
    }

    /**
     * 构造linux下载脚本
     *
     * @param url             路径
     * @param fileName        文件名
     * @param remoteAddrLocal 相对路径
     * @param sb              字符串
     */
    private void AddOneLinDownload(String url, String fileName, String remoteAddrLocal, StringBuilder sb) {
        fileName = fileName.replace(".jrt", "");
        //创建目录
        sb.append("mkdir -p /usr/share/JRTBase/" + remoteAddrLocal.replace("\\", "/") + " " + "\n");
        //删除老文件
        sb.append("rm -y /usr/share/JRTBase/" + remoteAddrLocal.replace("\\", "/") + fileName + " " + "\n");
        //下载新文件
        sb.append("curl " + url + " -o /usr/share/JRTBase/" + remoteAddrLocal.replace("\\", "/") + fileName + "\n");
    }

    /**
     * 要压缩的目录
     *
     * @param folderToZip 路径
     * @param zipFile     输出文件名
     * @throws Exception
     */
    public static void ZipFolder(File folderToZip, File zipFile) throws Exception {
        FileOutputStream fos = new FileOutputStream(zipFile);
        ZipOutputStream zos = new ZipOutputStream(fos);
        ZipFile(folderToZip, folderToZip.getName(), zos);
        zos.close();
        fos.close();
    }

    /**
     * 压缩文件
     *
     * @param fileToZip 要压缩的文件
     * @param fileName  文件名
     * @param zos       输出流
     * @throws Exception
     */
    private static void ZipFile(File fileToZip, String fileName, ZipOutputStream zos) throws Exception {
        if (fileToZip.isHidden()) {
            return;
        }
        if (fileToZip.isDirectory()) {
            if (fileName.endsWith("/")) {
                zos.putNextEntry(new ZipEntry(fileName));
                zos.closeEntry();
            } else {
                zos.putNextEntry(new ZipEntry(fileName + "/"));
                zos.closeEntry();
            }
            File[] children = fileToZip.listFiles();
            for (File childFile : children) {
                ZipFile(childFile, fileName + "/" + childFile.getName(), zos);
            }
            return;
        }
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileName);
        zos.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zos.write(bytes, 0, length);
        }
        fis.close();
        zos.closeEntry();
    }


    /**
     * 扫描文件
     *
     * @param dir
     * @param paths
     */
    private static void SeeFile(File dir, List<File> paths) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    SeeFile(file, paths);
                } else {
                    paths.add(file);
                }
            }
        }
    }
}

页面代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <title>JRT环境下载页</title>
    <link rel="shortcut icon" href="../../resource/common/images/favicon.ico"/>
    <script src="../../resource/common/js/JRTBSBase.js" type="text/javascript"></script>
    <script src="../../jrtprint/js/JRTPrint.js" type="text/javascript"></script>
    <script type="text/javascript">
        var me = {
            //文件数组
            fileArray: []
        };
        //初始化入口
        $(function () {
            $.messager.progress({ text: TranslateDataMTHD("prepare download data,please wait","正在构造下载数据,第一次会比较慢,请耐心等待", ""), interval: 500 });
            setTimeout(function () {
                $.messager.progress('close');
            }, 80000);
            //生成下载清单
            $.ajax({
                type: "post",
                dataType: "text", //text, json, xml
                cache: false, //
                async: true, //为true时,异步,不等待后台返回值,为false时强制等待;-asir
                url: '../ashx/ashDownLoad.ashx?Method=TryMakeInitScript',
                data: {
                    RootPath: GetRootPath()
                },
                success: function (result, status) {
                    //结束等待
                    $.messager.progress('close');
                    //渲染可以下载的文件
                    $.ajax({
                        type: "GET",
                        dataType: "json", //text, json, xml
                        cache: false, //
                        async: false, //为true时,异步,不等待后台返回值,为false时强制等待;-asir
                        url: '../ashx/ashDownLoad.ashx?Method=GetAllDataFiles',
                        success: function (result, status) {
                            //对数据进行筛选,是后台抛的信息的话,就提示,以及决定是否继续
                            if (!FilterBackData(result)) {
                                return;
                            }
                            if (result != null && result.length > 0) {
                                for (var i = 0; i < result.length; i++) {
                                    if (result[i] == "linuxinitjrt.sh") {
                                        continue;
                                    }
                                    if (result[i] == "windowsinitjrt.ps1") {
                                        continue;
                                    }
                                    AddFile("../..download/data/" + result[i], result[i]);
                                }
                            }
                        }
                    });
                    LoadFileList();
                }
            });
        });

        //得到网站根路径
        function GetRootPath() {
            var curPageUrl = window.document.location.href;
            var rootPath = curPageUrl.split("//")[0] + "//" + curPageUrl.split("//")[1].split("/")[0] + "//" + curPageUrl.split("//")[1].split("/")[1];
            return rootPath + "/";
        }

        //初步的处理数据
        function AddFile(url, name) {
            var arr = name.split(".");
            // 获取文件后缀,根据后缀设置图标
            var ext = arr[arr.length - 1];
            var icon = "../images/download.png";
            var title = arr[0];
            me.fileArray.push({
                icon: icon,
                url: url,
                name: name,
                title: title
            });
        }

        //根据me.fileArray,加载页面文件列表
        function LoadFileList() {
            for (var i = 0; i < me.fileArray.length; i++) {
                var file = me.fileArray[i];
                var box = $("<a></a>");
                box.attr({
                    class: "easyui-tooltip file_item",
                    title: file.title,
                    href: file.url,
                    target: "_blank",
                });
                var img = $("<img/>");
                img.attr({
                    src: file.icon,
                    class: "file_icon",
                });
                var name = $("<div></div>");
                name.attr({
                    class: "file_text",
                });
                name.text(file.name);
                box.append(img);
                box.append(name);
                $("#panel_Main").append(box);
            }
        }

    </script>
    <style>
        .fileDiv {
            display: flex;
            flex-wrap: wrap;
            padding: 0 20px 36px 20px;
        }

        .fileDiv .file_item {
            display: flex;
            margin-right: 20px;
            height: 20px;
            margin-top: 20px;
            line-height: 20px;
            cursor: pointer;
        }

        .fileDiv .file_text {
            margin-left: 5px;
            color: #0670c6;
            width: 140px;
            overflow: hidden;
            display: -webkit-box;
            -webkit-box-orient: vertical;
            -webkit-line-clamp: 1;
        }

        .fileDiv .file_icon {
            width: 20px;
            height: 20px;
        }
    </style>
</head>
<body>
<div class="easyui-layout" fit="true">
    <div region="north" split="false" border="0" style="padding:10px;height:80px;">
        <div>
            欢迎使用JRT环境下载页,这里提供客户端所需要的环境及工具,请根据需要下载文件!
            </br>
            "linux初始化脚本"下载到linux后直接bash执行下载的脚步进行客户端环境初始化。windows初始化脚本用powershell执行,windows默认没开启执行脚本权限,用管理员打开powershell执行set-executionpolicy remotesigned开启。然后下载的脚步用powershell打开执行。对无法执行powershell的电脑直接下载window压缩包到本地解压,把客户端和浏览器快捷方式发送到桌面。对linux也可以下载压缩包到本地解压后运行目录的install.sh初始化。如果想把其他需要的软件放入下载页面让用户下载,那么把文件投入网站的download/data里即可。
        </div>
    </div>
    <div region="center" split="true" title="&nbsp&nbsp&nbsp环境以及工具下载">
        <div id="panel_Main" class="fileDiv">
            <a class="easyui-tooltip file_item" title="linux初始化脚本" href="../data/linuxinitjrt.sh" target="_blank"><img
                    src="../images/download.png" class="file_icon">
                <div class="file_text">linux初始化脚本</div>
            </a>
            <a class="easyui-tooltip file_item" title="windows初始化脚本" href="../data/windowsinitjrt.ps1"
               target="_blank"><img src="../images/download.png" class="file_icon">
                <div class="file_text">windows初始化脚本</div>
            </a>
            <a class="easyui-tooltip file_item" title="linux程序包" href="../clienttmp/linux.zip" target="_blank"><img
                    src="../images/download.png" class="file_icon">
                <div class="file_text">linux压缩包</div>
            </a>
            <a class="easyui-tooltip file_item" title="windows程序包" href="../clienttmp/windows.zip" target="_blank"><img
                    src="../images/download.png" class="file_icon">
                <div class="file_text">windows压缩包</div>
            </a>
            <a class="easyui-tooltip file_item" title="老版本谷歌安装包" href="../data/41.0.2272.101_chrome_installer.exe"
               target="_blank"><img src="../images/download.png" class="file_icon">
                <div class="file_text">谷歌浏览器下载</div>
            </a>
            <a class="easyui-tooltip file_item" title="新版本谷歌安装包" href="../data/chrome_installernew.exe" target="_blank"><img
                    src="../images/download.png" class="file_icon">
                <div class="file_text">新谷歌浏览器下载</div>
            </a>
        </div>
    </div>
</div>
</body>
</html>

这样就基本完成windows和linux的环境初始化设计,JRT从构想、到demo、到雏形、到1.0发布、到正式用水准推进。

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

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

相关文章

【STL详解 —— list的介绍及使用】

STL详解 —— list的介绍及使用 list的介绍list的介绍使用list的构造list iterator的使用list capacitylist element accesslist modifiers 示例list的迭代器失效 list的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭…

Linux内核中KASLR功能是什么?有什么作用?怎么破除?以及如何实操?(地址空间、layout random、kallsyms)

1. 背景 KASLR是一个什么技术点其实不重要&#xff0c;但重要的是有了KASLR这个功能后&#xff0c;造成内核中某个符号&#xff08;函数 or 变量&#xff09;在System.map中的地址和实际不一样了&#xff08;实际&#xff1a; cat /proc/kallsyms&#xff09;&#xff0c;进一…

vector及cv::Mat删除指定元素并不改变位置

1、vector删除指定元素且不改变原有的顺序 使用erase方法&#xff0c;测试例子如下所示&#xff1a; //测试用例 struct MyStruct {int a;int b; }; std::vector<MyStruct> spotInfo; spotInfo.push_back({ 1,2 }); spotInfo.push_back({ 3,4 }); spotInfo.push_back({…

SSM整合时的配置文件

文章目录 SSM整合时的配置文件pom.xmlweb.xmlmybatis-config.xmlspring-mvc.xmlspring-mapper.xmldatabase.propertiesapplication.xml项目结构图 SSM整合时的配置文件 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"ht…

蓝桥杯第2152题——红绿灯

问题描述 爱丽丝要开车去上班, 上班的路上有许多红绿灯, 这让爱丽丝很难过。为 了上班不迟到, 她给自己的车安装了氮气喷射装置。现在她想知道自己上班最 短需要多少时间。 爱丽丝的车最高速度是 米每秒, 并且经过改装后, 可以瞬间加速到小于 等于最高速的任意速度, 也可以瞵…

【从浅学到熟知Linux】环境变量详谈(含使用程序获取环境变量的3种方法、如何查看环境变量)

&#x1f3e0;关于专栏&#xff1a;Linux的浅学到熟知专栏用于记录Linux系统编程、网络编程及数据库等内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 环境变量基本概念查看环境变量的方法环境变量相关命令环境变量组织方式及获取环境变量的3种方法验…

链表中常见的使用方法逻辑整理

文章目录 1. 二叉树特点1.1 完全二叉树1.2 满二叉树 2. 二叉树创建2.1 通过先序序列带有叶子结点标识符创建二叉树2.2 通过层次遍历顺序创建二叉树2.3 通过 先序中序 创建二叉树2.4 通过 先序中序 创建二叉树2.5 通过 中序后序 创建二叉树 3. 二叉树遍历通用方法3.1 先序遍历(深…

【软考中级】软件设计师考点分布

文章目录 软考官网资格设置软考报考流程 【软件设计师】考点分布选择题考点分布案例题考点分布 软考官网 中国计算机技术职业资格网&#xff1a;https://www.ruankao.org.cn/ 官网报名平台&#xff1a;https://bm.ruankao.org.cn/sign/welcome 资格设置 计算机软件计算机网…

SSM整合配置案例

一、什么是SSM整合 SSM整合用到两个容器&#xff0c;web容器是root容器的子容器&#xff0c;父子容器关系。 为了方便编写&#xff0c;我们可以三层架构每层对应一个配置类&#xff0c;分别指定两个容器加载 Ioc如何初始化&#xff1f; 二、简单实现整合SSM &#xff08;一…

是的,本科毕业八年,我考研了

今天&#xff0c;是一篇纯分享文。 是的&#xff0c;本科毕业八年&#xff0c;我考研了。 停更10个月&#xff0c;历时296天&#xff0c;我考研上岸了。 小伙伴们&#xff0c;好久不见。 一 发今年第一篇文章的时候刚处理完后续事宜&#xff0c;就简单说了句&#xff0c;后台…

QThread的学习

锁住该线程直到下面的情况之一出现&#xff1a; (1)和该线程连接的对象已经执行完成&#xff08;例如&#xff1a;当它从run()中返回时&#xff09; 如果该线程已经结束&#xff0c;该函数将返回true。 如果该线程还没有开始&#xff0c;它也返回true。 (2)time毫秒已经过去。如…

Linux 内核学习(2) --- regulator 框架

目录 Regulator 介绍Regulator provider 注册struct regulator_descstruct regualtor_configDTS 配置和解析On BoardConfig 配置regulator_ops总结 Regulator Consumer 使用struct regulator 获取regulator 操作使用Multi Regulator 参考博客 Regulator 介绍 Regulator 指的是…

电子烟特效音语音方案选型-WTN6020-8S-E

随着科技的迅猛进步&#xff0c;电子烟行业亦在持续创新与突破&#xff0c;引领着全新的潮流。其中&#xff0c;电子烟产品所特有的吸烟声音特效播报功能&#xff0c;无疑成为了技术革新的璀璨亮点。这一设计巧妙地将吸烟的声效融入使用体验中&#xff0c;使得用户在吸电子烟时…

Javascript 斐波那契搜索-迭代与递归(Fibonacci Search)

给定一个大小为 n 的排序数组 arr[] 和要在其中搜索的元素 x。如果 x 存在于数组中&#xff0c;则返回 x 的索引&#xff0c;否则返回 -1。 例子&#xff1a; 输入&#xff1a; arr[] {2, 3, 4, 10, 40}, x 10输出&#xff1a; 3 元素 x 出现在索引 3 处。 输入&#xff1…

HarmonyOS开发实例:【app帐号管理】

应用帐号管理 介绍 本示例选择应用进行注册/登录&#xff0c;并设置帐号相关信息&#xff0c;简要说明应用帐号管理相关功能。效果图如下&#xff1a; 效果预览 使用说明参考鸿蒙文档&#xff1a;qr23.cn/AKFP8k点击或者转到。 1.首页面选择想要进入的应用&#xff0c;首次进…

【Redis】持久化

文章目录 一、RDB1.1、RDB的自动备份与手动备份1.1.1、自动备份1.1.2、手动备份 1.2、RDB优点1.3、RDB缺点1.4、RDB快照1.5、RDB优化配置项 二、AOF2.1、AOF工作流程2.2、AOF写回策略2.3、MP-AOF实现2.4、AOF优缺点2.5、AOF重写机制 三、RDBAOF混合持久化3.1、数据恢复顺序和加…

生产环境中秒杀接口并发量剧增与负载优化策略探讨

✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天开心哦&#xff01;✨✨ &#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; 目录 引言 1. 实施限流措施 1.1 令牌桶算法&#xff1a; 1.2 漏…

如何申请阿里云服务器学生优惠,入口在这呢!

阿里云学生服务器免费申请&#xff0c;之前是云翼计划学生服务器9元/月&#xff0c;现在是高校计划&#xff0c;学生服务器可以免费申请&#xff0c;先完成学生认证即可免费领取一台云服务器ECS&#xff0c;配置为2核2G、1M带宽、40G系统盘&#xff0c;在云服务器ECS实例过期之…

什么是队头阻塞以及如何解决

前言 通常我们提到队头阻塞&#xff0c;指的可能是TCP协议中的队头阻塞&#xff0c;但是HTTP1.1中也有一个类似TCP队头阻塞的问题&#xff0c;下面各自介绍一下。 TCP队头阻塞 队头阻塞&#xff08;head-of-line blocking&#xff09;发生在一个TCP分节丢失&#xff0c;导致…

ip地址切换器安卓版,保护隐私,自由上网

在移动互联网时代&#xff0c;随着智能手机和平板电脑的普及&#xff0c;移动设备的网络连接变得愈发重要。为了满足用户在不同网络环境下的需求&#xff0c;IP地址切换器安卓版应运而生。本文将以虎观代理为例&#xff0c;为您详细解析IP地址切换器安卓版的功能、应用以及其所…