当前位置: 首页 > news >正文

Springboot整合Jsch-Sftp

背景

  开发一个基于jsch的sftp工具类,方便在以后的项目中使用。写代码的过程记录下来,作为备忘录。。。

Maven依赖

  • springboot依赖
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.0</version>
</parent>
  • jsch依赖
 <dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version>
</dependency>
  • 完整依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>jsch-sftp</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.0</version></parent><dependencies><!-- web应用相关 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 单元测试 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId></dependency><!-- jsch SFTP --><dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>

项目结构

在这里插入图片描述

Sftp连接工具类

  • JschSftpRun: 项目启动类
package cn.com.soulfox;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;/*** 启动类** @author xxxx* @create 2024/7/5 11:50*/
@SpringBootApplication
public class JschSftpRun {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(JschSftpRun.class, args);}
}
  • JschSftpConneciton: 创建sftp连接工具类
      用于创建sftp连接,类中提供了创建sftp连接的方法,另外还提供了在创建sftp连接失败后,重新尝试创建连接的方法
package cn.com.soulfox.jsch;import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;/*** @author xxxx* @create 2024/7/4 12:15*/
@Slf4j
public class JschSftpConneciton {private static final String SFTP_PROTOCOL = "sftp";private static final Integer DEFAULT_RETRY_COUNT_5 = 5;private static final Long SLEEP_ITME_1000 = 1000L;//每次重试的时间间隔private String host;private Integer port;private String username;private String password;private Integer sessionTimeout;private Integer connectionTimeout;public JschSftpConneciton setHost(String host) {this.host = host;return this;}public JschSftpConneciton setPort(Integer port) {this.port = port;return this;}public JschSftpConneciton setUsername(String username) {this.username = username;return this;}public JschSftpConneciton setPassword(String password) {this.password = password;return this;}public JschSftpConneciton setSessionTimeout(Integer sessionTimeout) {this.sessionTimeout = sessionTimeout;return this;}public JschSftpConneciton setConnectionTimeout(Integer connectionTimeout) {this.connectionTimeout = connectionTimeout;return this;}/*** 返回SftpWrapper对象,是为了方便释放Session,Channel,ChannelSftp资源* SFTP连接服务器*/public SftpWrapper connect() throws  Exception {JSch jsch = new JSch();Session session = null;Channel channel = null;ChannelSftp sftp = null;try {session = jsch.getSession(username, host, port);if (session == null) {throw new JSchException("create session error");}//设置登陆主机的密码session.setPassword(password);//设置第一次登陆的时候提示,可选值:(ask | yes | no)session.setConfig("StrictHostKeyChecking", "no");//设置登陆超时时间session.connect(sessionTimeout);session.sendKeepAliveMsg();//创建sftp通信通道channel = session.openChannel(SFTP_PROTOCOL);channel.connect(connectionTimeout);sftp = (ChannelSftp) channel;return new SftpWrapper(session, channel, sftp);}catch (JSchException e){log.error("SFTP连接异常:", e);if (sftp != null ) {sftp.disconnect();}if (channel != null ) {channel.disconnect();}if (session != null ) {session.disconnect();}throw e;} catch (Exception e1) {log.error("SFTP连接异常:", e1);if (sftp != null ) {sftp.disconnect();}if (channel != null ) {channel.disconnect();}if (session != null ) {session.disconnect();}throw e1;}}/*** 获取sftp连接,获取连接失败时会重试,* 默认重试次数:5次* @return* @throws Exception*/public SftpWrapper connectWithRetry() throws Exception {return connectWithRetry(DEFAULT_RETRY_COUNT_5);}public SftpWrapper connectWithRetry(int retryCount) throws Exception {//最大重试次数int maxRetryCount = DEFAULT_RETRY_COUNT_5;if(retryCount > 0){maxRetryCount = retryCount;}int retry = 0;Throwable t = null;do {try {SftpWrapper channelSftpWrapper = this.connect();if(channelSftpWrapper != null){t = null;return channelSftpWrapper;}} catch (Exception e) {t = e;}try {Thread.sleep(SLEEP_ITME_1000);//休息1秒} catch (InterruptedException e) {}}while (retry++ < maxRetryCount);if(t != null){throw new Exception(t);}return null;}}
  • SftpWrapper: sftp连接对象包装类,属性包括Session,Channel,ChannelSftp
      执行sftp操作有ChannelSftp就可以了,使用Sftp包装类,是为了方便关闭资源
package cn.com.soulfox.jsch;import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.Session;
import lombok.AllArgsConstructor;
import lombok.Data;/*** SftpWrapper类简单包装ChannelSftl对象,方便关闭资源* @author xxxx* @create 2024/7/4 14:26*/
@AllArgsConstructor//生成全字段,构造方法
@Data //生成 getter,setter方法
public class SftpWrapper {private Session session = null;private Channel channel = null;private ChannelSftp sftp = null;/*** 关闭资源*/public void disconnect() {if (sftp != null && sftp.isConnected()) {sftp.disconnect();}if (channel != null && channel.isConnected()) {channel.disconnect();}if (session != null && session.isConnected()) {session.disconnect();}}
}
  • JschSftpConfig: jsch sftp配置类
      初始化 jsch sftp
package cn.com.soulfox.config;import cn.com.soulfox.jsch.JschSftpConneciton;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;/*** @author xxxx* @create 2024/7/4 12:12*/
@Configuration
public class JschSftpConfig {@Value("${jsch.sftp.host}")private String host;@Value("${jsch.sftp.port:22}")private Integer port;@Value("${jsch.sftp.username}")private String username;@Value("${jsch.sftp.password}")private String password;@Value("${jsch.sftp.session-timeout:60000}")private Integer sessionTimeout;//单位毫秒@Value("${jsch.sftp.connect-timeout:5000}")private Integer connectTimeout;//单位毫秒@Bean@Lazypublic JschSftpConneciton jschSftpConneciton(){return new JschSftpConneciton().setHost(host).setPort(port).setUsername(username).setPassword(password).setSessionTimeout(sessionTimeout).setConnectionTimeout(connectTimeout);}}

sftp连接信息配置在文件application.yml里
jsch:
sftp:
host: 172.168.xxx.xx
port: 1221 #默认22,1221公司自己定义的,这里要配置正确
username: xxxx #远程服务器用户名
password: xxxx #远程服务器密码
sftp连接信息

SftpUitl 工具类,提供下载,上传文件功能

package cn.com.soulfox.jsch;import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.SftpException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.*;/*** @author xxxx* @create 2024/7/4 14:28*/
@Component
@Slf4j
public class JschSftpUtil {private static JschSftpConneciton jschSftpConneciton;@Autowiredpublic void setJschSftpConneciton(JschSftpConneciton jschSftpConneciton) {JschSftpUtil.jschSftpConneciton = jschSftpConneciton;}/*** 下载文件* @param remotePath            远程目录* @param downloadFileName      待下载的远程文件名称* @param localSavePath         下载文件保存的本地目录*/public static void downloadFile(String remotePath, String downloadFileName, String localSavePath) {SftpWrapper sftpWrapper = null;try {//sftp连接对象sftpWrapper = jschSftpConneciton.connectWithRetry();//进入远程服务器指定的目录sftpWrapper.getSftp().cd(remotePath);if (!checkLocalPath(localSavePath)) {log.info("本地目录[{}]不存在,且新建失败+++++", localSavePath);return;}String localFile = checkPathEnd(localSavePath) + downloadFileName;File outFile = new File(localFile);sftpWrapper.getSftp().get(downloadFileName, new FileOutputStream(outFile));log.info("从远程目录[{}]下载文件[{}]到本地目录[{}]成功", remotePath, downloadFileName, localSavePath);} catch (SftpException e) {log.info("从远程目录[{}]下载文件[{}]到本地目录[{}]失败", remotePath, downloadFileName, localSavePath);log.error("下载文件失败: ", e);} catch (Exception e) {log.info("从远程目录[{}]下载文件[{}]到本地目录[{}]失败", remotePath, downloadFileName, localSavePath);log.error("下载文件失败: ", e);} finally {if (sftpWrapper != null) {sftpWrapper.disconnect();}}}/**** @param localDir              保存上传文件的本地目录* @param uploadFileName        上传文件名称* @param remoteSaveDir         保存上传文件的远程目录, 建议使用绝对路径*                              如果使用相对路径,建议基准目录使用sfpt登录后所在的目录*                              这个目录,使用channelSftp.goHome()可以获取*/public static void uploadFile(String localDir, String uploadFileName, String remoteSaveDir) {String uploadFilePath = checkPathEnd(localDir) + uploadFileName;File uploadFile = new File(uploadFilePath);uploadFile(uploadFile, remoteSaveDir);}/*** 上传文件* @param uploadFilePath        本地文件的路径* @param remoteSaveDir         保存上传文件的远程目录, 建议使用绝对路径*                              如果使用相对路径,建议基准目录使用sfpt登录后所在的目录*                              这个目录,使用channelSftp.goHome()可以获取*/public static void uploadFile(String uploadFilePath, String remoteSaveDir) {File uploadFile = new File(uploadFilePath);uploadFile(uploadFile, remoteSaveDir);}/*** 上传文件* @param uploadFile        上传文件的File对象* @param remoteSavePath    保存上传文件的远程目录, 建议使用绝对路径*                          如果使用相对路径,建议基准目录使用sfpt登录后所在的目录*                          这个目录,使用channelSftp.goHome()可以获取*/public static void uploadFile(File uploadFile, String remoteSavePath) {if(uploadFile == null ){log.info("本地文件对象不存在++++");return;}if(!uploadFile.exists()){log.info("本地文件[{}]不存在", uploadFile.getAbsoluteFile());return;}InputStream is = null;try {is = new FileInputStream(uploadFile);} catch (FileNotFoundException e) {log.info("获取本地文件[{}]的文件流失败", uploadFile.getAbsoluteFile());log.error("获取文件流失败: ", e);if(is != null){try {is.close();} catch (IOException ioException) {}}return;}SftpWrapper sftpWrapper = null;try {//sftp连接对象sftpWrapper = jschSftpConneciton.connectWithRetry();//检查远程目录,不存在则创建createLinuxRemoteDirs(sftpWrapper.getSftp(), remoteSavePath);//进入用户home目录,sftpWrapper.getSftp().cd(sftpWrapper.getSftp().getHome());//保证当前目录在上传文件保存的目录sftpWrapper.getSftp().cd(remoteSavePath);//上传文件sftpWrapper.getSftp().put(is, uploadFile.getName());} catch (SftpException e) {log.info("上传本地文件[{}]到远程目录[{}]失败", uploadFile.getAbsoluteFile(), remoteSavePath);log.error("上传本地文件失败: ", e);} catch (Exception e) {log.info("上传本地文件[{}]到远程目录[{}]失败", uploadFile.getAbsoluteFile(), remoteSavePath);log.error("上传本地文件失败: ", e);} finally {if (sftpWrapper != null) {sftpWrapper.disconnect();}if(is != null){try {is.close();} catch (IOException e) {}}}}/*** 检查目录结是否以目录分隔符结尾* 如果不是,则加上目录分隔符结尾** @param localPath 本地目录* @return*/private static String checkPathEnd(String localPath) {if (localPath.endsWith("/") || localPath.endsWith("\\")) {return localPath;}return localPath + File.separator;}/*** 检查本地目录是否存在,不存在就创建。* 为了防止其他线程已创建目录,加上了重试代码** @param localPath 本地目录* @return*/private static boolean checkLocalPath(String localPath) {int maxRetryCount = 5;int retry = 0;do {File localDir = new File(localPath);if (localDir.exists()) {return true;}boolean result = localDir.mkdirs();if (result) {return true;}try {Thread.sleep(1000L);//休息1秒} catch (InterruptedException e) {}} while (retry++ < maxRetryCount);return false;}/*** 检查和创建[ linux系统 ]的远程多级目录,* 外部调用, 单纯的创建远程目录,不作其他操作* @param remoteDir     远程目录* @throws SftpException*/public static void createLinuxRemoteDirs( String remoteDir) throws SftpException {SftpWrapper sftpWrapper = null;try {sftpWrapper = jschSftpConneciton.connectWithRetry();createLinuxRemoteDirs(sftpWrapper.getSftp(), remoteDir);} catch (SftpException e) {log.info("创建Linux远程目录[{}]失败", remoteDir);log.error("创建Linux远程目录失败: ", e);} catch (Exception e) {log.info("创建Linux远程目录[{}]失败", remoteDir);log.error("创建Linux远程目录失败: ", e);} finally {if (sftpWrapper != null) {sftpWrapper.disconnect();}}}/*** 检查和创建[ linux系统 ]的远程多级目录,* linux系统目录分隔符是 “/”* 内部上传文件的方法调用** @param sftpChannel* @param remoteDir  远程目录* @throws SftpException*/public static void createLinuxRemoteDirs(ChannelSftp sftpChannel, String remoteDir) throws SftpException {if(remoteDir == null || "".equals(remoteDir)){log.info("待创建的远程目录为空++++++++");return;}String[] dirs = remoteDir.split("/");;if(dirs == null || dirs.length == 0){log.info("拆分目录[{}]失败,没有获取到目录数组", remoteDir);return;}//进入用户home目录,保证初始目录正确sftpChannel.cd(sftpChannel.getHome());if( dirs.length == 1){//只有一层目录,直接处理try {sftpChannel.cd(dirs[0]);} catch (SftpException e) {if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {log.info("开始创建远程目录[{}]", dirs[0]);sftpChannel.mkdir(dirs[0]);} else {throw e;}}return;}StringBuilder sb = new StringBuilder();//处理第一个元素if(remoteDir.startsWith(".")){//相对路径,把缺少的路径补上sb.append(sftpChannel.getHome()).append("/");}else if(remoteDir.startsWith("/")){//绝对路径,把"/"放到目录开头sb.append("/");}else {//既不是”/“开头,也不是”.“开头//属于相对路径的一种情况try {//先处理第一层目录sftpChannel.cd(dirs[0]);} catch (SftpException e) {if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {log.info("开始创建远程目录[{}]", dirs[0]);sftpChannel.mkdir(dirs[0]);} else {throw e;}}//把已处理的目录加上sb.append(sftpChannel.getHome()).append("/").append(dirs[0]).append("/");}//从第二个元素开始创建不存在的目录for (int i = 1; i < dirs.length; i++) {String dir = dirs[i];if (dir.isEmpty() ) {//跳过空字符串continue;}sb.append(dir + "/");try {sftpChannel.cd(sb.toString());} catch (SftpException e) {if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {log.info("开始创建远程目录[{}]", sb.toString());sftpChannel.mkdir(sb.toString());} else {throw e;}}}
//        for (String dir : dirs) {
//            if (dir.isEmpty() || dir.contains(".")) {
//                //跳过空字符串,和"."字符串
//                continue;
//            }
//            sb.append(dir + "/");
//            try {
//                sftpChannel.cd(sb.toString());
//            } catch (SftpException e) {
//                if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
//                    sftpChannel.mkdir(sb.toString());
//                } else {
//                    throw e;
//                }
//            }
//        }}
}

单元测试

  • JschSftpConfigTest: 测试类
package cn.com.soulfox.config;import cn.com.soulfox.JschSftpRun;
import cn.com.soulfox.jsch.JschSftpConneciton;
import cn.com.soulfox.jsch.JschSftpUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;/*** @author xxxx* @create 2024/7/5 12:57*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = JschSftpRun.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class JschSftpConfigTest {@Autowiredprivate JschSftpConneciton sftpConneciton;/*** 下载文件*/@Testpublic void testDownload(){//从远程服务器上的下载 /home/jiyh/ 目录下的 testabc.txt//下载文件保存到 d:\jiyhString remotePath = "/home/jiyh/";String downloadFileName = "testabc.txt";String localSavePath = "d:\\jiyh";JschSftpUtil.downloadFile(remotePath, downloadFileName, localSavePath);}/*** 上传文件*/@Testpublic void testUpload(){//上传传本地 d:\jiyh 目录下的 test123.txt文件//到远程 /home/jiyh/test/test 目录//目录不存在,会自动创建JschSftpUtil.uploadFile("d:\\jiyh", "test123.txt", "/home/jiyh/test/test");}
}
  • 在远程服务器准备测试文件 文件内容随便,这里我准备的内容为“112dadfdefee”
    在这里插入图片描述

  • 测试下载功能
    测试结果:
    在这里插入图片描述

  • 测试上传功能 :在本地 d:/jiyh 目录准备测试文件“test123.txt”,内容为“dfdfdfdfdaerwrt”
    测试结果
    在这里插入图片描述

相关文章:

Springboot整合Jsch-Sftp

背景 开发一个基于jsch的sftp工具类&#xff0c;方便在以后的项目中使用。写代码的过程记录下来&#xff0c;作为备忘录。。。 Maven依赖 springboot依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-par…...

生成随机的验证码图片(Python)

文章目录 一、导入包二、生成随机的验证码三、生成随机的rgb颜色四、生成图片验证码总结&#xff1a; 一、导入包 import random from PIL import Image, ImageDraw, ImageFont二、生成随机的验证码 def random_code(length4):默认返回4位随机验证码&#xff0c;字符串code …...

0/1背包问题总结

文章目录 &#x1f347;什么是0/1背包问题&#xff1f;&#x1f348;例题&#x1f349;1.分割等和子集&#x1f349;2.目标和&#x1f349;3.最后一块石头的重量Ⅱ &#x1f34a;总结 博客主页&#xff1a;lyyyyrics &#x1f347;什么是0/1背包问题&#xff1f; 0/1背包问题是…...

模电基础 - 放大电路的频率响应

目录 一. 简介 二. 频率响应的基本概念 三. 波特图 四. 晶体管的高频等效模型 五. 场效应管的高频等效模型 六. 单管放大电路的频率响应 七.多级放大电路的频率响应 八. 频率响应与阶跃响应 一. 简介 放大电路的频率响应是指在输入不同频率的正弦信号时&#xff0c;电路…...

Java 8 到 Java 22 新特性详解

Java 8 到 Java 22 新特性详解 Java自发布以来一直在不断演进&#xff0c;添加新特性以提升开发效率和性能。本文将介绍Java 8到Java 22的主要新特性&#xff0c;帮助开发者了解各版本的新功能和改进。 Java 8 (2014) 1. Lambda 表达式 Lambda 表达式允许使用简洁的语法定义…...

华为OD机试题-提取字符串中最长数学表达式

题目描述 https://blog.csdn.net/weixin_51055612/article/details/139841128 题目描述 提取字符串中的最长合法简单数学表达式&#xff0c;字符串长度最长的&#xff0c;并计算表达式的值。如果没有&#xff0c;则返回0。 简单数学表达式只能包含以下内容&#xff1a;0-9数字&…...

专家指南:如何为您的电路选择理想的压敏电阻或热敏电阻

保护和维持电路功能需要两种设备&#xff1a;压敏电阻和热敏电阻。这两个电气元件有时会因后缀相似而混淆&#xff0c;但它们具有不同且重要的用途。 由于这种混淆&#xff0c;我们需要准确地了解这些组件是什么&#xff0c;这就是本文将要讨论的内容——应用程序、作用、优点…...

基于主流SpringBoot进行JavaWeb开发的学习路线

目录 一、学习路线 &#xff08;1&#xff09;第一部分&#xff08;Web前端开发的技术栈&#xff09; &#xff08;2&#xff09;第二部分&#xff08;Web后端开发&#xff09; 二、学习之后必备的技能 三、学习Web开发的基础与未来的收获 学完这一类知识目标&#xff1a;…...

医疗机器人中的具身智能进展——自主超声策略模型的任务编码和局部探索

医疗机器人一直是具身智能的研究热点。医学图像、医疗触诊、血压血氧、心率脉搏和生物电信号等多模态生物医学信息&#xff0c;不断丰富着医疗机器人的感知范畴。 自主超声 “自主超声”属于具身智能医疗机器人领域中话题度较高的研究方向。作为临床检查的重要手段之一&#…...

探索人工智能在电子商务平台与游戏发行商竞争中几种应用方式

过去 12 年来&#xff0c;电脑和视频游戏的发行策略发生了巨大变化。数字游戏的销量首次超过实体游戏的销量 在20132020 年的封锁进一步加速了这一趋势。例如&#xff0c;在意大利&#xff0c;封锁的第一周导致数字游戏下载量 暴涨174.9%. 展望未来&#xff0c;市场有望继续增…...

【Altium】AD-网络版一个用户非人为异常占用多个License的解决方法

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 当出现一个用户同时占用多个授权&#xff0c;又无法单独释放一个授权的情况下&#xff0c;该如何解决。 2、 问题场景 一个用户获取网络版授权后&#xff0c;AD会自动重复获取授权&#xff0c;直到该license下所有授…...

*算法训练(leetcode)第二十五天 | 134. 加油站、135. 分发糖果、860. 柠檬水找零、406. 根据身高重建队列

刷题记录 134. 加油站135. 分发糖果860. 柠檬水找零406. 根据身高重建队列 134. 加油站 leetcode题目地址 记录全局剩余油量和当前剩余油量&#xff0c;当前剩余小于0时&#xff0c;其实位置是当前位置的后一个位置。若全局剩余油量为负&#xff0c;则说明整体油量不足以走完…...

乐鑫ESPC3 ESP8685 WiFi蓝牙模块透传程序设置教程,抛开繁琐AT指令,简单Web页面配置,即可实现透传

完整文档请下载规格书 TTL-WiFi 透传产品 使用手册 一. 产品概述 二. 接口定义 三. 软件透传WEB配置使用说明 3.1 STATUS配置界面 3.2 MODULE配置界面 n Serial&#xff08;串口配置&#xff09; n WiFi&#xff08;WiFi配置&#xff09; n Networks&#xff08;网络…...

怎么样才能为公司申请OV证书?

OV证书&#xff0c;全称为组织验证型SSL证书&#xff08;Organization Validation SSL Certificate&#xff09;&#xff0c;是一种高级别的SSL/TLS证书&#xff0c;用于加密网站通信并验证网站所属组织的合法身份。相比于基本的域名验证型证书&#xff08;DV证书&#xff09;&…...

Python的`queue`模块

队列&#xff08;Queue&#xff09; 在Python的queue模块中&#xff0c;Queue类是一个线程安全的队列实现&#xff0c;用于在多线程编程中安全地交换信息。它遵循先入先出&#xff08;FIFO&#xff09;的原则。Queue类提供了几种主要的方法&#xff1a; put(item): 将一个项目…...

牛客周赛 Round 50

A题&#xff1a;小红的最小最大 思路&#xff1a; 大水题 code&#xff1a; inline void solve() {int a, b, c; cin >> a >> b >> c;if (min(a, b) c > max(a, b)) cout << "YES\n";else cout << "NO\n";return; }…...

后端之路——登录校验

前言&#xff1a;Servlet 【登录校验】这个功能技术的基础是【会话技术】&#xff0c;那么在讲【会话技术】的时候必然要谈到【Cookie】和【Session】这两个东西&#xff0c;那么在这之前必须要先讲一下一个很重要但是很多人都会忽略的一个知识点&#xff1a;【Servlet】 什么是…...

无线网卡怎么连接台式电脑?让上网更便捷!

随着无线网络的普及&#xff0c;越来越多的台式电脑用户希望通过无线网卡连接到互联网。无线网卡为台式电脑提供了无线连接的便利性&#xff0c;避免了有线网络的束缚。本文将详细介绍无线网卡怎么连接台式电脑的四种方法&#xff0c;包括使用USB无线网卡、内置无线网卡以及使用…...

【45 Pandas+Pyecharts | 去哪儿海南旅游攻略数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 查看数据信息2.3 日期处理&#xff0c;提取年份、月份2.4 经费处理2.5 天数处理 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 出发日期_…...

Vue3项目给ElementPlus设置中文的两个方案

介绍 在Vue3项目将ElementPlus切换为中文 1、在App.vue的文件中修改 <template><el-config-provider :locale"zhCn"><router-view></router-view></el-config-provider> </template><script lang"ts" setup>im…...

C#开发单实例应用程序并响应后续进程启动参数

C#默认的WinForm模板是不支持设置单实例的&#xff0c;也没有隔壁大哥VB.NET那样有个“生成单个实例应用程序”的勾选选项&#xff08;VB某些时候要比C#更方便&#xff09;&#xff0c;实现单实例可以有多种方法&#xff1a; 检测同名进程&#xff1a;Process.GetProcessesByNa…...

STM32智能机器人导航系统教程

目录 引言环境准备智能机器人导航系统基础代码实现&#xff1a;实现智能机器人导航系统 4.1 数据采集模块 4.2 数据处理与导航算法 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;机器人导航应用与优化问题解决方案与优化收尾与总结 1. 引言 智能机器…...

Android 15 适配之16K Page Size :为什么它会是最坑的一个适配点

首先什么是 Page Size &#xff1f;一般意义上&#xff0c;页面(Page)指的就是 Linux 虚拟内存管理中使用的最小数据单位&#xff0c;页面大小(Page Size)就是虚拟地址空间中的页面大小&#xff0c; Linux 中进程的虚拟地址空间是由固定大小的页面组成。 Page Size 对于虚拟内…...

下载linux的吐槽

本来这几天放假了&#xff0c;想下一个linux玩一玩 教程&#xff08;我就是根据这个教程进行下载的&#xff0c;但是呢在进行修改BIOS 模式的 地方遇见了困难&#xff0c;也许是电脑修过的原因&#xff0c;我狂按F12 以及 FnF12都没有BIOS设置&#xff0c;只有一个让我选择用w…...

【HTML入门】第四课 - 换行、分割横线和html的注释

这一小节&#xff0c;我们继续说HTML的入门知识&#xff0c;包括换行、横线分割以及注释&#xff08;html的注释&#xff09;。 目录 1 换行 2 分割横线 3 html注释 1 换行 html中分为块元素和行内元素。这一小节呢&#xff0c;先不说这些元素们&#xff0c;我们先说一下换…...

基于Hadoop平台的电信客服数据的处理与分析④项目实现:任务15:数据生产

任务描述 电信数据生产是一个完整且严密的体系&#xff0c;这样可以保证数据的鲁棒性。在本项目的数据生产模块中&#xff0c;我们来模拟生产一些电信数据。同时&#xff0c;我们必须清楚电信数据的格式和数据结构&#xff0c;这样才能在后续的数据产生、存储、分析和展示环节…...

Kotlin中的数据类型

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…...

提高交易决策质量,Anzo Capital昂首资本只需两个交易策略

要想提高交易决策质量&#xff0c;其实很简单&#xff0c;Anzo Capital昂首资本只需两个交易策略&#xff0c;结合价格行为和VSA(成交量与价格分析)就可以达成我们的目的。首先&#xff0c;理解这两个概念&#xff1a; 1. 价格行为&#xff1a;价格行为是市场价格变动的方式&a…...

Ubuntu TensorRT安装

什么是TensorRT 一般的深度学习项目&#xff0c;训练时为了加快速度&#xff0c;会使用多 GPU 分布式训练。但在部署推理时&#xff0c;为了降低成本&#xff0c;往往使用单个 GPU 机器甚至嵌入式平台&#xff08;比如 NVIDIA Jetson&#xff09;进行部署&#xff0c;部署端也…...

spring mvc学习

第四章 Spring MVC 第一节 Spring MVC 简介 1. Spring MVC SpringMVC是一个Java 开源框架&#xff0c; 是Spring Framework生态中的一个独立模块&#xff0c;它基于 Spring 实现了Web MVC&#xff08;数据、业务与展现&#xff09;设计模式的请求驱动类型的轻量级Web框架&am…...