Docker一键部署项目,无需登录XShell
文章目录
- 一键部署项目
- Docker手动部署SpringBoot项目
- 编写docker部署的脚本文件
- script.sh 脚本内容
- 特别注意!
- 编写dockerfile
- dockerfile 文件内容
- 上传后端服务的jar包到服务器中
- 执行 script 脚本部署后端服务
- 自动部署SpringBoot项目
- 引入jsch依赖
- 编写jsch工具类
- 执行部署命令
- Docker手动部署Vue项目
- 编写docker部署的脚本文件
- script.sh 脚本内容
- 编写dockerfile
- dockerfile文件内容
- 编写nginx配置文件
- nginx配置文件内容
- 上传前端服务的打包文件到服务器
- 执行 script 脚本部署前端服务
- 访问 ip:9002 查看是否运行成功
- 自动部署Vue项目
- 工具类(慎重!包含服务器的删除操作!)
- main 函数
- 总结
一键部署项目
Git仓库地址!
我们每次部署项目都需要手动传输 jar 包,或者前端打包好的文件到服务器上,再连接服务器执行部署脚本,为了省去这个步骤,我们直接借助 jsch 包,来通过执行一个方法,就可以将打包好的文件上传至服务器,并且自动执行部署脚本。
Docker手动部署SpringBoot项目
编写docker部署的脚本文件
cd / # 进入根目录
mkdir develop/docker-deploy # 创建两级目录
cd develop/docker-deploy
vi script.sh # 编写部署脚本chmod +x ./script.sh # 授予脚本文件可执行的权限
script.sh 脚本内容
特别注意!
在 script.sh 脚本文件中,docker build 命令使用 -f 参数指定 dockerfile 文件的路径,并且指定docker镜像构建的上下文
-
dockerfile文件路径为/develop/docker-deploy/dockerfile -
指定 docker 镜像构建上下文目录为
/develop/docker-deploy/
那么在镜像构建的时候,就会把当前服务器的 /develop/docker-deploy/目录下的所有文件都发送给 docker 的守护进程。
在构建的时候会去执行 dockerfile 中的命令,在 dockerfile 中,ADD <src> <dest> 将 src 文件复制到容器的 dest 中,这里的 src 只能使用相对路径,相对的就是构建镜像的上下文,即 /develop/docker-deploy/ 目录。
我们后边使用 jsch 进行自动化部署时,由于 jsch 无法执行 cd 命令,不能切换路径,因此都需要通过绝对路径来指定docker的构建环境!
#!/bin/bash#构建docker镜像
echo "========================================正在构建镜像================================="
# -f 指定dockerfile文件 docker build最后边的参数不可以使用. 如果在其他目录执行该脚本文件
# 就会把执行脚本文件的目录当作构建镜像的上下文传送给docker的守护进程,那么在dockerfile中通过add添加的文件
# 都是以相对路径添加的,那么就会出现找不到文件的情况
docker build -t docker-deploy:01 -f /develop/docker-deploy/dockerfile /develop/docker-deploy/ # 停止并删除容器
echo "========================================正在删除容器================================="
docker stop docker-deploy
docker rm docker-deploy# 运行容器
echo "========================================正在创建新容器================================="
docker run --name docker-deploy -p 9001:9001 -d docker-deploy:01
编写dockerfile
cd develop/docker-deploy
vi dockerfile # 编写 dockerfile,如下
dockerfile 文件内容
#基础镜像
FROM openjdk:8-jdk-alpine
#作者
MAINTAINER abc
#执行命令,主要用来安装相关的软件
#RUN
# ADD将文件复制到镜像中
ADD Docker-Deploy-0.0.1-SNAPSHOT.jar /usr/local
RUN chmod u+x /usr/local/Docker-Deploy-0.0.1-SNAPSHOT.jar # 给当前目录下的test.py文件所有者添加执行权限
#挂载目录到容器
#VOLUME ["/data"]
#环境变量设置
#ENV #开放端口
EXPOSE 9001
#启动时执行的命令
CMD ["/bin/bash"]
#启动时执行的命令
ENTRYPOINT ["java","-jar","/usr/local/Docker-Deploy-0.0.1-SNAPSHOT.jar"]
上传后端服务的jar包到服务器中
最后目录如下:

执行 script 脚本部署后端服务
/develop/docker-deploy/script.sh # 测试绝对路径执行脚本
显示结果如下,表示执行成功

使用 docker ps 查看是否部署 docker 镜像成功

那么,手动部署没问题了,我们就可以通过 Java 的 jsch 包来实现不需要去服务器就可以进行部署项目。
自动部署SpringBoot项目
引入jsch依赖
<!-- jsch -->
<dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.54</version>
</dependency>
编写jsch工具类
package com.example.jschquickdeploy.utils;import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;/*** @author 千祎来了* @date 2023/8/7 15:08*/
public class ShellCommandExecution {private static final Logger logger = LoggerFactory.getLogger(ShellCommandExecution.class);public static Session getSession(String username, String password, String host, int port) {// 创建JSch对象JSch jSch = new JSch();Session jSchSession = null;try {// 根据主机账号、ip、端口获取一个Session对象jSchSession = jSch.getSession(username, host, port);// 存放主机密码jSchSession.setPassword(password);Properties config = new Properties();// 去掉首次连接确认config.put("StrictHostKeyChecking", "no");jSchSession.setConfig(config);// 超时连接时间为3秒jSchSession.setTimeout(3000);// 进行连接jSchSession.connect();} catch (Exception e) {logger.warn(e.getMessage());}return jSchSession;}/*** 下载文件,将 sourceFile 文件下载至 destinationFile* @param jSchSession* @param sourceFile* @param destinationFile* @throws Exception*/public static void downloadFiles(Session jSchSession, String sourceFile, String destinationFile) throws Exception {// Opening an SFTP ChannelChannelSftp chSftp = (ChannelSftp)jSchSession.openChannel("sftp");// Example Establish a connection to the SFTP channelchSftp.connect();// Set encoding formatchSftp.setFilenameEncoding("UTF-8");/*** 说明:* 1、当前上读取文件信息没有任何反馈,如果没有异常则代表成功* 2、如果需要判断是否读取成功的进度,可参考https://blog.csdn.net/coding99/article/details/52416373?locationNum=13&fps=1* 3、将src文件下载到dst路径中*/chSftp.get(sourceFile, destinationFile);logger.info("download file " + sourceFile + " success,location is:" + destinationFile);}/*** 将 sourceFile 上传至 destinationFile* @param jSchSession* @param sourceFile* @param destinationFile*/public static void uploadFiles(Session jSchSession, String sourceFile, String destinationFile) throws Exception{// Opening an SFTP ChannelChannelSftp chSftp = (ChannelSftp)jSchSession.openChannel("sftp");// Example Establish a connection to the SFTP channelchSftp.connect();// Set encoding formatchSftp.setFilenameEncoding("UTF-8");/*** 说明:* 1、当前上读取文件信息没有任何反馈,如果没有异常则代表成功* 2、如果需要判断是否读取成功的进度,可参考https://blog.csdn.net/coding99/article/details/52416373?locationNum=13&fps=1* 3、将src文件下载到dst路径中*/chSftp.put(sourceFile, destinationFile);logger.info("upload file " + sourceFile + " success,location is:" + destinationFile);}/*** 执行命令* @param command* @param jSchSession* @return* @throws Exception*/public static StringBuffer execCommand(String command, Session jSchSession) throws Exception{Channel exec = null;StringBuffer result = new StringBuffer();try {exec = jSchSession.openChannel("exec");((ChannelExec) exec).setCommand(command);exec.setInputStream(null);// 错误信息输出流,用于输出错误的信息,当exitstatus<0的时候((ChannelExec) exec).setErrStream(System.err);// 执行命令,等待结果exec.connect();// 获取命令执行结果InputStream in = exec.getInputStream();// 推出状态码int exitStatus = 0;/*** 通过channel获取信息的方式,采用官方Demo代码*/byte[] tmp = new byte[1024];while (true) {while (in.available() > 0) {int i = in.read(tmp, 0, 1024);if (i < 0) {break;}result.append(new String(tmp, 0, i));}// 从channel获取全部信息之后,channel会自动关闭if (exec.isClosed()) {if (in.available() > 0) {continue;}exitStatus = exec.getExitStatus();break;}try {Thread.sleep(1000);} catch (Exception ee) {}}logger.info("命令:【" + command + "】的执行结果为:" + result);// 如果状态码不是0,则表示执行失败if (exitStatus != 0) {logger.error("状态码为:" + exitStatus + ",命令执行失败:" + result);throw new Exception("命令:【" + command + "】执行失败,执行结果为:" + result);}} finally {// 关闭 jschChannel 流if (exec != null && exec.isConnected()) {exec.disconnect();}}return result;}
}
执行部署命令
在 main 方法中,只需要做2件事就可以一键部署了:
- 将我们使用 maven 工具打包好的 jar 包的路径上传到服务器指定目录
- 调用服务器上的执行脚本即可
注意:这里执行需要使用绝对路径,在 jsch 中无法使用 cd 命令
package com.example.jschquickdeploy.utils;import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.Properties;/*** @author 千祎来了* @date 2023/8/9 21:43*/
public class QuickDeploy {private static final Logger logger = LoggerFactory.getLogger(ShellCommandExecution.class);public static void main(String[] args) {/*** 连接服务器*/String username = "root";String password = "123456";String host = "127.0.0.1";int port = 2222;Session jSchSession = null;try {jSchSession = ShellCommandExecution.getSession(username, password, host, port);/*** 上传 jar 包到服务器*/ShellCommandExecution.uploadFiles(jSchSession, "D:\\Project\\IDEA\\Docker-Deploy\\target\\Docker-Deploy-0.0.1-SNAPSHOT.jar", "/develop/docker-deploy");/*** 执行部署命令*/ShellCommandExecution.execCommand("/develop/docker-deploy/script.sh", jSchSession);/*** 查看镜像*/ShellCommandExecution.execCommand("docker ps", jSchSession);} catch (Exception e) {logger.warn(e.getMessage());} finally {// close jschSesson streamif (jSchSession != null && jSchSession.isConnected()) {jSchSession.disconnect();}}}
}
Docker手动部署Vue项目
编写docker部署的脚本文件
cd /develop # 进到部署对应目录
mkdir docker-deploy-front # 创建前端部署目录
cd docker-deploy-front
vi script.sh # 编写部署脚本
chmod +x ./script.sh # 授予脚本执行权限
script.sh 脚本内容
#!/bin/bashecho "========================================正在构建镜像================================="
docker build -t docker-deploy-front:1.0 -f /develop/docker-deploy-front/dockerfile /develop/docker-deploy-front/# 停止并删除容器
echo "========================================正在删除容器================================="
docker stop docker-deploy-front
docker rm docker-deploy-front# 运行容器
echo "========================================正在创建新容器================================="
docker run --name docker-deploy-front -d -p 9002:80 docker-deploy-front:1.0
~
编写dockerfile
vi dockerfile
dockerfile文件内容
# 设置基础镜像,这里使用最新的nginx镜像,前面已经拉取过了
FROM nginx
#作者
MAINTAINER abc
#执行命令,主要用来安装相关的软件
RUN rm /etc/nginx/conf.d/default.conf
# 将 nginx 配置文件复制到镜像中
ADD default.conf /etc/nginx/conf.d/ #添加文件
#将dist文件中的内容复制到 /usr/share/nginx/html/ 这个目录下面
#容器内nginx默认的html文件目录为 /usr/share/nginx/html/
COPY dist/ /usr/share/nginx/html/
编写nginx配置文件
vi default.conf
nginx配置文件内容
server {listen 80;listen [::]:80;server_name localhost;location / {root /usr/share/nginx/html;index index.html index.htm;try_files $uri $uri/ /index.html;}error_page 500 502 503 504 /50x.html;location = /50x.html {root /usr/share/nginx/html;}
}
上传前端服务的打包文件到服务器
进入 vue 项目根目录,调用 npm run build 打包前端项目,生成 dist 文件夹
最后,前端需要的所有文件如下:

执行 script 脚本部署前端服务
执行 ./script 即可
/develop/docker-deploy-front/script # 执行脚本
docker ps # 查看docker容器是否启动成功
访问 ip:9002 查看是否运行成功
http://localhost:9002/ (我这里是本地,服务器要加上服务器ip)

自动部署Vue项目
这里使用的项目和自动部署后端项目使用的是同一个项目,因此依赖和工具类不需要重新引入
由于自动部署后端代码时,上传的只有一个 jar 包,因此上传功能比较好些,但是 vue 项目打包生成的是 dist 目录,因此需要给工具类添加上传目录的方法,如下:
工具类(慎重!包含服务器的删除操作!)
拿到工具类之后,不要立即执行在,将路径换为自己服务器上的路径再执行!以免误删文件!
在 uploadDir 方法中有一个删除操作,删除的是服务器上已经存在的打包的目录,也就是服务器上的 dist 文件夹所在目录!
相较于后端部署时,多添加了一个 uploadDir 方法,用于上传一整个目录
该方法中使用递归去遍历文件,因为 jsch 中并没有直接上传目录的操作,因此需要我们自己去遍历目录,并上传每一个文件
package com.example.jschquickdeploy.utils;import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.Properties;/*** @author 千祎来了* @date 2023/8/7 15:08*/
public class ShellCommandExecution {private static final Logger logger = LoggerFactory.getLogger(ShellCommandExecution.class);private static Session jSchSession = null;public static Session getSession(String username, String password, String host, int port) {// 创建JSch对象JSch jSch = new JSch();Session jSchSession = null;try {// 根据主机账号、ip、端口获取一个Session对象jSchSession = jSch.getSession(username, host, port);// 存放主机密码jSchSession.setPassword(password);Properties config = new Properties();// 去掉首次连接确认config.put("StrictHostKeyChecking", "no");jSchSession.setConfig(config);// 超时连接时间为3秒jSchSession.setTimeout(3000);// 进行连接jSchSession.connect();ShellCommandExecution.jSchSession = jSchSession;} catch (Exception e) {logger.warn(e.getMessage());}return jSchSession;}/*** 下载文件,将 sourceFile 文件下载至 destinationFile* @param sourceFile* @param destinationFile* @throws Exception*/public static void downloadFiles(String sourceFile, String destinationFile) throws Exception {// Opening an SFTP ChannelChannelSftp chSftp = (ChannelSftp)jSchSession.openChannel("sftp");// Example Establish a connection to the SFTP channelchSftp.connect();// Set encoding formatchSftp.setFilenameEncoding("UTF-8");/*** 说明:* 1、当前上读取文件信息没有任何反馈,如果没有异常则代表成功* 2、如果需要判断是否读取成功的进度,可参考https://blog.csdn.net/coding99/article/details/52416373?locationNum=13&fps=1* 3、将src文件下载到dst路径中*/chSftp.get(sourceFile, destinationFile);logger.info("download file " + sourceFile + " success,location is:" + destinationFile);}/*** 将 sourceDir 目录下的所有文件上传至 destinationDir 目录下* 假设 sourceDir = "D:\Project\IDEA\Docker-Quick-Deploy\docker-deploy-front\dist"* destinationDir = "/develop/docker-deploy-front"* 那么该方法将 dist 目录所有文件都传输至 /develop/docker-deploy-front/dist 目录中* @param sourceDir* @param destinationDir* @throws Exception*/public static void uploadDir(String sourceDir, String destinationDir) throws Exception{// Opening an SFTP ChannelChannelSftp chSftp = (ChannelSftp)jSchSession.openChannel("sftp");// Example Establish a connection to the SFTP channelchSftp.connect();// Set encoding formatchSftp.setFilenameEncoding("UTF-8");// 文件夹名称String dirName = sourceDir.substring(sourceDir.lastIndexOf("\\") + 1);String linuxRootDir = destinationDir + "/" + dirName;String windowsRootDir = sourceDir;execCommand("rm -rf " + linuxRootDir);logger.info("删除文件夹" + linuxRootDir);execCommand("mkdir " + linuxRootDir);logger.info("创建文件夹" + linuxRootDir);/*** 将 sourceDir 目录下的文件传输至 targetDir*/transFile(chSftp, sourceDir, windowsRootDir, linuxRootDir);}/*** 递归传输文件** @param chSftp* @param sourceDir* @param windowsRootDir* @param linuxRootDir* @throws IOException* @throws SftpException*/private static void transFile(ChannelSftp chSftp, String sourceDir, String windowsRootDir, String linuxRootDir) throws Exception {File root = new File(sourceDir);for (File file : Objects.requireNonNull(root.listFiles())) {if (file.isFile()) {Path src = Paths.get(file.getPath());String des = file.getPath().replace(windowsRootDir, linuxRootDir).replace("\\", "/");file.getPath().replace(windowsRootDir, "");logger.info("上传源文件:" + src.toString() + "到目的文件:" + des);chSftp.put(Files.newInputStream(src), des);} else if (file.isDirectory()) {String dirName = file.getPath().replace(windowsRootDir, linuxRootDir).replace("\\", "/");execCommand("mkdir " + dirName);logger.info("创建文件夹:" + dirName);transFile(chSftp, file.getPath(), windowsRootDir, linuxRootDir);}}}/*** 将 sourceFile 上传至 destinationFile* @param sourceFile 必须为文件* @param destinationFile*/public static void uploadFiles(String sourceFile, String destinationFile) throws Exception{ChannelSftp chSftp = null;try {// Opening an SFTP ChannelchSftp = (ChannelSftp)jSchSession.openChannel("sftp");// Example Establish a connection to the SFTP channelchSftp.connect();// Set encoding formatchSftp.setFilenameEncoding("UTF-8");/*** 说明:* 1、当前上读取文件信息没有任何反馈,如果没有异常则代表成功* 2、如果需要判断是否读取成功的进度,可参考https://blog.csdn.net/coding99/article/details/52416373?locationNum=13&fps=1* 3、将src文件下载到dst路径中*/chSftp.put(sourceFile, destinationFile, ChannelSftp.OVERWRITE);logger.info("upload file " + sourceFile + " success,location is:" + destinationFile);} finally {// 关闭 jschChannel 流if (chSftp != null && chSftp.isConnected()) {chSftp.disconnect();}}}/*** 执行命令* @param command* @return* @throws Exception*/public static StringBuffer execCommand(String command) throws Exception{Channel exec = null;StringBuffer result = new StringBuffer();try {exec = jSchSession.openChannel("exec");((ChannelExec) exec).setCommand(command);exec.setInputStream(null);// 错误信息输出流,用于输出错误的信息,当exitstatus<0的时候((ChannelExec) exec).setErrStream(System.err);// 执行命令,等待结果exec.connect();// 获取命令执行结果InputStream in = exec.getInputStream();// 推出状态码int exitStatus = 0;/*** 通过channel获取信息的方式,采用官方Demo代码*/byte[] tmp = new byte[1024];while (true) {while (in.available() > 0) {int i = in.read(tmp, 0, 1024);if (i < 0) {break;}result.append(new String(tmp, 0, i));}// 从channel获取全部信息之后,channel会自动关闭if (exec.isClosed()) {if (in.available() > 0) {continue;}exitStatus = exec.getExitStatus();break;}try {Thread.sleep(1000);} catch (Exception ee) {}}logger.info("命令:【" + command + "】的执行结果为:" + result);// 如果状态码不是0,则表示执行失败if (exitStatus != 0) {logger.error("状态码为:" + exitStatus + ",命令执行失败:" + result);throw new Exception("命令:【" + command + "】执行失败,执行结果为:" + result);}} finally {// 关闭 jschChannel 流if (exec != null && exec.isConnected()) {exec.disconnect();}}return result;}
}
main 函数
package com.example.jschquickdeploy.utils;import com.jcraft.jsch.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** @author 千祎来了* @date 2023/8/10 9:51*/
public class QuickDeployFront {private static final Logger logger = LoggerFactory.getLogger(ShellCommandExecution.class);public static void main(String[] args) {/*** 连接服务器*/String username = "root";String password = "123456";String host = "127.0.0.1";int port = 2222;Session jSchSession = null;try {jSchSession = ShellCommandExecution.getSession(username, password, host, port);/*** 上传 Vue 打包文件到服务器*/ShellCommandExecution.uploadDir(jSchSession, "D:\\Project\\IDEA\\Docker-Quick-Deploy\\docker-deploy-front\\dist", "/develop/docker-deploy-front");/*** 执行部署命令*/ShellCommandExecution.execCommand("/develop/docker-deploy-front/script.sh", jSchSession);/*** 查看镜像*/ShellCommandExecution.execCommand("docker ps", jSchSession);} catch (Exception e) {logger.warn(e.getMessage());} finally {// close jschSesson streamif (jSchSession != null && jSchSession.isConnected()) {jSchSession.disconnect();}}}
}
总结
这样一键部署项目就完成了,部署步骤如下:
后端部署:
- 对 springboot 项目打成 jar 包
- 在方法中指定 jar 包位置和上传服务器位置
- 在方法中指定部署脚本
script执行命令 - 执行 main 方法
前端部署:
- 对 vue 项目打包
- 在方法中指定 dist 文件夹位置和上传服务器位置
- 在方法中指定部署脚本
script执行命令 - 执行 main 方法
相关文章:
Docker一键部署项目,无需登录XShell
文章目录 一键部署项目Docker手动部署SpringBoot项目编写docker部署的脚本文件script.sh 脚本内容 特别注意!编写dockerfiledockerfile 文件内容 上传后端服务的jar包到服务器中执行 script 脚本部署后端服务 自动部署SpringBoot项目引入jsch依赖编写jsch工具类执行…...
GIt Squash 多个提交压缩提交
假设你有一个名为 feature 的分支,它包含三个提交(A, B, C),并且你想将这三个提交压缩成一个。下面是如何做到这一点的。 首先,找出你要开始压缩的那个最早提交的哈希值。在这个例子中,我们假设 A 是最早的…...
【数据结构】栈与队列
1 栈 1.1 栈的概念及结构 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出 LIFO (Last In First Out) 的原则。 压栈:栈…...
突然让做性能测试?试试RunnerGo
当前,性能测试已经是一名软件测试工程师必须要了解,甚至熟练使用的一项技能了,在工作时可能每次发版都要跑一遍性能,跑一遍自动化。性能测试入门容易,深入则需要太多的知识量,今天这篇文章给大家带来&#…...
(7)(7.4) 集结航点
文章目录 7.4.1 概述 7.4.2 设置集结航点 7.4.3 飞行示例 7.4.4 附录 7.4.1 概述 通常情况下,当固定翼或旋翼飞机进入"返回发射"(Return to Launch (RTL))模式(通常由自动驾驶仪失控保护触发)(failsafe)时,默认行为…...
基于kubeadm部署K8S集群:上篇
目录 一、环境准备 1、主机初始化配置 2、配置主机名绑定hosts,不同主机名称不同 3、主机配置初始化 4、部署docker环境 二、部署kubernetes集群 1、组件介绍 2、所有主机配置阿里云yum源 3、安装kubelet 、kubeadm 、kubectl 4、配置init-config.yaml 5、…...
机器学习-特征选择:如何使用递归特征消除算法自动筛选出最优特征?
一、引言 在实际应用中,特征选择作为机器学习和数据挖掘领域的重要环节,对于提高模型性能和减少计算开销具有关键影响。特征选择是从原始特征集中选择最相关和最具区分力的特征子集,以提高模型的泛化能力和可解释性。 特征选择在实践中具有以…...
学生成绩管理系统V1.0
某班有最多不超过30人(具体人数由键盘输入)参加某门课程的考试,用一维数组作函数参数编程实现如下学生成绩管理: (1)录入每个学生的学号和考试成绩; (2)计算课程的总分…...
嵌入式:ARM Day1
1. 思维导图 2.作业一 3.作业2...
Android 网络协议与网络编程
一、TCP/IP协议 Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联 协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP 协议组成。协议采用了4层的层级结构。…...
【讯飞星火认知大模型】大模型之星火手机助理
目录 1. 讯飞星火认知大模型介绍 2. API 申请 3. 星火手机助理 4. 效果展示 1. 讯飞星火认知大模型介绍 讯飞星火认知大模型是科大讯飞自研的基于深度学习的自然语言处理模型,它可以理解和生成中文,执行多种任务,如问答、翻译、写作、编…...
centos中的swap.img可以删除吗
swap.img 是 CentOS 系统中的交换分区文件,用于辅助内存管理。交换分区在系统内存不足时用于存储不常用的数据,而不是直接写入硬盘。一般情况下,不建议删除交换分区文件,因为它对系统的正常运行非常重要。 如果您真的希望删除交换…...
Java多线程编程中的线程死锁
Java多线程编程中的线程死锁 在多线程编程中,线程死锁是一种常见的问题,它发生在两个或多个线程互相等待对方释放资源的情况下,导致程序无法继续执行。本文将介绍线程死锁的概念、产生原因、示例以及如何预防和解决线程死锁问题。 线程死…...
在浏览器中使用javascript打印HTML中指定Div带背景图片内容生成PDF电子证书查询的解决方案
在浏览器中使用javascript打印HTML中指定Div带背景图片内容生成PDF电子证书查询的解决方案 一、指定内容打印二、背景图片打印1.CSS背景图片设置2.div相对定位居中 三、完整案例展示1.CSS样式表2.HTML容器构建 一、指定内容打印 要调用浏览器中的打印功能,并指定需…...
【Redis实践篇】使用Redisson 优雅实现项目实践过程中的5种场景
文章目录 1.前言2.使用方式1. 添加Redisson依赖:2. 配置Redis连接信息3. 使用场景3.1. 分布式锁3.2. 限流器(Rate Limiter)3.3. 可过期的对象(Expirable Object)3.4. 信号量(Semaphore)3.5. 分布…...
污水处理厂人员定位方案介绍
污水处理厂人员定位在现代化的污水处理厂中具有重要的意义,它可以带来多方面的优势和好处: 安全管理: 污水处理厂通常涉及到各种危险环境和设备,如化学品、高压设备等。人员定位系统可以追踪人员的位置,确保他们不会进…...
约数个数(质因子分解)
思路: (1)由数论基本定理,任何一个正整数x都能写作,其中p1,p2..pk为x的质因子。 (2)由此可以推断,要求一个数约数的个数,注意到约数就是p1,p2...pk的一种组合ÿ…...
【QT】 QSS样式表设计一文了解
很高兴在雪易的CSDN遇见你 ,给你糖糖 欢迎大家加入雪易社区-CSDN社区云 前言 本文分享QT界面设计中的QSS样式技术,主要从**、**和**方面展开,希望对各位小伙伴有所帮助!学会了QSS样式设计,就可以开动你的审美&#…...
9-AJAX-1入门
AJAX 目录 AJAX 概念和 axios 使用认识 URLURL 查询参数常用请求方法和数据提交HTTP协议-报文接口文档案例 - 用户登录form-serialize 插件 01.AJAX 概念和 axios 使用 目标 了解 AJAX 概念并掌握 axios 库基本使用 讲解 什么是 AJAX ? mdn 使用浏览器的 XMLHttpRequest…...
ssh免密登录
客户端 第一步:生成密钥 ssh-keygen -t rsa 第二步:从“~/.ssh/id_rsa.pub”拷贝公钥 服务器端 填写公钥 打开authorized_keys,并把刚刚的公钥填进去 重启服务 sudo systemctl restart sshd...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
