Jasypt加密库基本使用方法
1 Jasypt简介...
2 基础知识回顾...
3 Jasypt+基本加密器...
4 Jasypt+PBE加密器...
5 Jasypt+池化加密器...
6 Jasypt+客户端工具...
7 Jasypt+Springboot基本用法...
8 Jasypt+Springboot自定义加密器...
9 Jasypt+Springboot配置文件加密...
1、Jasypt简介
Jasypt是一个java的加密库,通过对java自带加密算法的二次包装,提供了十分简洁的加密接口,在保证安全的同时,降低了密码算法的使用门槛,并且提供多种数据类型的加密。在Jasypt-spring-boot的加持下,Jasypt可以在Spring应用中轻易集成,充分利用Spring的依赖注入,属性检测等特性。本文提供Jasypt用法的介绍,基本覆盖Jasypt绝大部分的使用场景。
2、基础知识回顾
对称加密(Symmetric encryption):加密和解密用同一个密钥的方法,即为对称加密算法。
哈希算法(Hash):也叫散列、杂凑、摘要,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值,哈希算法是单向算法,即无法通过哈希值倒推原始数据。
口令散列(Password Hashing):是将用户输入的密码通过一系列算法处理后,生成一个固定长度的散列值。口令散列常用语口令存储和密钥生成。在软件系统中,出于安全需求,用户密码不允许直接在数据库中明文存储的,通过对口令做哈希在入库,这样即是数据库泄露了,用户密码依然不会泄露。对于密钥生成的场景,需区分口令和密钥的区别,密钥是指加密过程中实际作用于加密算法的数据串,也叫key,key一般长度较长(16或32字节以上),实际场景中不太可能让用户去设置和记住这么长的密码,因此一般使用用户设置的短密码(也叫口令),用hash算法对口令做散列,用散列出的key加密数据。由于用户口令普遍较短,密码空间较小,重复率比较高,如果数据库发生泄漏,攻击者通过密码和散列值的映射表(又称彩虹表)用于多个用户口令的碰撞,于是在实际散列的时候需加入其它“值”合并计算。该值又称盐或salt,且每个用户的salt都不一样。如果攻击者试图通过彩虹表对口令做碰撞,需要针对每个用户生成口令长度(散列值隐去了实际口令长度)不同的彩虹表,大大增加了破解的难度。口令散列可简化为:hash(口令+salt)。
3、Jasypt+基本加密器
1)摘要计算
Digester = new Digester();
digester.setAlgorithm("MD5");
byte[] digest = digester.digest("123".getBytes());
输出:202cb962ac59075b964b07152d234b70
使用外部工具验证,结果符合预期:
Digester仅提供两个setter,setAlgorithm用户设置算法类型,支持的算法类型有:MD2, MD5, SHA, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256, SHA3-224, SHA3-256, SHA3-384, SHA3-512,setProvider,设置算法提供的厂商Provider,基本不会用到,缺省即可。
2)密码验证
xxxPasswordEncryptor接口用于密码的加密存储和验证,加密存储即对口令做散列用于存储,验证接口用于用户再次提供口令比对验证,用法如下:
BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor();
String password= "123456";
String encryptedPassword = passwordEncryptor.encryptPassword(password);
System.out.println(String.format("密文是:%s,输出接口可用于数据库存储", encryptedPassword));
if (passwordEncryptor.checkPassword(password, encryptedPassword)) {System.out.println("口令比对通过!");
} else {System.out.println("口令比对不通过!");
}
Jasypt提供了两个不同算法强度的接口:BasicPasswordEncryptor和StrongPasswordEncryptor,BasicPasswordEncryptor基于MD5,StrongPasswordEncryptor基于SHA-256,使用方法一致。
3)文本加密
Jasypt提供了不同强度的文本(String)加密接口,根据强度排序依次为:
- BasicTextEncryptor(PBEWithMD5AndDES)
- StrongTextEncryptor (PBEWithMD5AndTripeDES)
- AES256TextEncryptor (PBEWithHMACSHA512AndAES_256)
使用方法均为:先调用setPassword设置密码,再调用encrypt或decrypt做加解密(其他加密器的使用替换BasicTextEncryptor类型即可):
BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
textEncryptor.setPassword("passwd");
String myEncryptedText = textEncryptor.encrypt("123456");
System.out.println(myEncryptedText);
String plainText = textEncryptor.decrypt(myEncryptedText);
System.out.println(plainText);
4)二进制加密
二进制加密和文本加密的区别仅在于入参不同,其他基本一致,根据算法强度二进制加密提供如下接口:
- BasicBinaryEncryptor (PBEWithMD5AndDES)
- StrongBinaryEncryptor (PBEWithMD5AndTripeDES)
- AES256TextEncryptor (PBEWithHMACSHA512AndAES_256)
基本用法为:
BasicBinaryEncryptor binaryEncryptor = new BasicBinaryEncryptor();
binaryEncryptor.setPassword("passwd");
byte[] bytes = {'1', '2', '3'};
byte[] myEncryptedByte = binaryEncryptor.encrypt(bytes);
System.out.println(String.format("加密后的密文是:%s",Base64.getEncoder().encodeToString(myEncryptedByte)));
byte[] plainText = binaryEncryptor.decrypt(myEncryptedByte);
System.out.println(String.format("解密后的明文是:%s", new String(plainText)));
输出:
加密后的密文是:1a8117840c945323dc91a7ecf09583bd
解密后的明文是:123
5)数值加密
Jasypt提供了BigInteger和BigDecimal类型数据的加密接口,此类型加密器使用较少,本文不做详细介绍,基本用法如下:
BigInteger myNumber = new BigInteger("123");
BasicIntegerNumberEncryptor numberEncryptor = new BasicIntegerNumberEncryptor();
numberEncryptor.setPassword("passwd");
BigInteger encryptMyNumber = numberEncryptor.encrypt(myNumber);
System.out.println(String.format("加密后的密文是:%d", encryptMyNumber));
BigInteger decryptMyNumber = numberEncryptor.decrypt(encryptMyNumber);
System.out.println(String.format("解密后的明文是:%d", decryptMyNumber));
输出:
加密后的密文是:442164205133206440127638602826610783717381111824
解密后的明文是:123
4、Jasypt+PBE加密器
PBE,基于口令的密码运算,即在实际加密前,先用用户口令散列出加密key,再用key做加解密运算。上节中所涉及的接口均为Jasypt PBE算法的包装类,旨在隐去一些不常用的细节,为用户提供简洁的接口。Jasypt提供四个不同类型的PBE加密器,均以StandardPBE<类型>Encryptor命名,通过追踪调用链可发现,这4个不同类型的加密器中,以StandardPBEByteEncryptor为基本接口,这也容易理解,程序计算的基本单位是字节,不管什么数据类型,最终都得转为字节类型再做运算,下列仅以StandardPBEByteEncryptor做举例:
StandardPBEStringEncryptor = new StandardPBEStringEncryptor();
standardPBEStringEncryptor.setPassword("passwd");
String cihperText = standardPBEStringEncryptor.encrypt("123456");
System.out.println(String.format("StandardPBEStringEncryptor的加密结果:%s", cihperText));
BasicTextEncryptor = new BasicTextEncryptor();
basicTextEncryptor.setPassword("passwd");
System.out.println(String.format("basicTextEncryptor的解密结果:%s", basicTextEncryptor.decrypt(cihperText)));
输出:
StandardPBEStringEncryptor的加密结果:ZCWgTEa2pWGXPnI23NFI8Q==
basicTextEncryptor的解密结果:123456
StandardPBEByteEncryptor的配置项如下:
PBEWITHHMACSHA1ANDAES_128
PBEWITHHMACSHA1ANDAES_256
PBEWITHHMACSHA224ANDAES_128
PBEWITHHMACSHA224ANDAES_256
PBEWITHHMACSHA256ANDAES_128
PBEWITHHMACSHA256ANDAES_256
PBEWITHHMACSHA384ANDAES_128
PBEWITHHMACSHA384ANDAES_256
PBEWITHHMACSHA512ANDAES_128
PBEWITHHMACSHA512ANDAES_256
PBEWITHMD5ANDDES
PBEWITHMD5ANDTRIPLEDES
PBEWITHSHA1ANDDESEDE
PBEWITHSHA1ANDRC2_128
PBEWITHSHA1ANDRC2_40
PBEWITHSHA1ANDRC4_128
PBEWITHSHA1ANDRC4_40
PBE接口均提供了以下settter:
1) setAlgorithm
设置算法,缺省为PBEWithMD5AndDES,可选算法有:
2)setPassword
设置密码,不可缺省
3)setKeyObtentionIterations
设置口令散列的迭代次数,缺省为1000
4)setSaltGenerator
设置盐的生成器,缺省为org.jasypt.salt.RandomSaltGenerator,也是对JCE提供的随机数生成器的二次包装
5)setIvGenerator
用于生成IV(Initial vector)值用于CBC、CFB等其他需要初始向量的加密模式,IV生成器的本质也是随机数生成器,缺省为org.jasypt.iv.RandomIvGenerator,也是对JCE提供的随机数生成器的二次包装
6)setProviderName
设置JCE的Provider,默认是SunJCE。
对于不需要特别定制的场景,使用PBE接口仍可以保持和上节中的加密接口一样间接的使用方式,在使用前仅配置密码,其他项均保持缺省。
5、Jasypt+池化加密器
Jasypt引入了池化加密器的概念,旨在提高在多核处理器下的计算性能。在应用程序中频繁使用加密和解密操作时,每次创建和销毁加密器实例都会带来一定的性能开销。为了避免这种开销,Jasypt将多个加密器实例保存在一个池,按需从池中获取加密器实例并重复使用。这种方式可以避免重复创建和销毁加密器实例,提高应用程序的性能。Jasypt的方法均为线程安全方法,但是StandardPBEByteEncryptor的encrytor和decryptor中存在线程同步代码,这意味着如果多个线程同时使用一个加密器,存在同步竞争问题,影响系统性能,所以Jasypt池化加密器的本质是通过池化为并发下的每个线程提供不同的加密器,避免竞争问题。应用需自己保证池化的加密器为单例模式。
Jasypt对PBE接口均实现了相应的池化,命名格式为PooledPBE<类型>Encryptor,使用方法除了多了个setPoolSize,其他配置完全一样。setPoolSize建议和CPU核心数一样或略高于核心数,示例代码如下:
// pooledPBEStringEncryptor 全局变量
PooledPBEStringEncryptor = new PooledPBEStringEncryptor();
pooledPBEStringEncryptor.setPoolSize(4);
pooledPBEStringEncryptor.setPassword("passwd");
String cihperText = pooledPBEStringEncryptor.encrypt("123456");
System.out.println(String.format("PooledPBEStringEncryptor的加密结果:%s", cihperText));//使用基本接口对池化的计算接口做验证
BasicTextEncryptor = new BasicTextEncryptor();
basicTextEncryptor.setPassword("passwd");
System.out.println(String.format("BasicTextEncryptor的解密结果:%s", basicTextEncryptor.decrypt(cihperText)));
输出:
PooledPBEStringEncryptor的加密结果:D0rSSuL79lNooMEyHRdB/g==
basicTextEncryptor的解密结果:123456
6、Jasypt+客户端工具
Jasypt提供了客户端工具可直接用于加密运算,下载地址:链接。解压后的bin的目录为Jasypt客户端工具脚本,工具包包含加密、解密和摘要计算脚本,脚本的本质均为调用Jasypt依赖包下的指定类完成密码运算。直接运行相关脚本可查看帮助信息:
下面使用客户端工具做数据加密,并使用代码对结果做解密验证:
客户端工具默认使用BasicTextEncryptor加密器,因此可用代码做验证:
BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
textEncryptor.setPassword("passwd");
String myEncryptedText = textEncryptor.decrypt("8zfUPVd/ruyBC3Ah4lRziQ==");
System.out.println(String.format("解密结果为:%s", myEncryptedText) );
输出:
解密结果为:123456
结果符合预期。
下面是用客户端工具做摘要计算的验证过程:
输出结果为base64编码,对输出做base64解码后并以HEX格式显示时,实际结果为:
当盐的长度为0,迭代次数为1(默认为1000)时,等同于一次普通的摘要计算,因此可以使用其他MD5工具对结果做验证比对:
结果符合预期。
7、Jasypt+Springboot基本用法
使用starter完成引入:
<dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.5</version>
</dependency>
jasypt-spring-boot是Jasypt的springboot框架,引入框架之后即可根据配置自动注入相应的加密器,该框架还提供属性检测功能,可用于敏感配置的加密,在使用的时候自动完成解密。Jasypt-spring-boot基本配置如下:
Key | Required | Default Value |
jasypt.encryptor.password | TRUE |
|
jasypt.encryptor.algorithm | FALSE | PBEWITHHMACSHA512ANDAES_256 |
jasypt.encryptor.key-obtention-iterations | FALSE | 1000 |
jasypt.encryptor.pool-size | FALSE | 1 |
jasypt.encryptor.provider-name | FALSE | SunJCE |
jasypt.encryptor.provider-class-name | FALSE | null |
jasypt.encryptor.salt-generator-classname | FALSE | org.jasypt.salt.RandomSaltGenerator |
jasypt.encryptor.iv-generator-classname | FALSE | org.jasypt.iv.RandomIvGenerator |
jasypt.encryptor.string-output-type | FALSE | base64 |
jasypt.encryptor.proxy-property-sources | FALSE | FALSE |
jasypt.encryptor.skip-property-sources | FALSE | empty list |
以上配置除了后面两项,其他配置和PBExxx类的setter方法基本一致。其中jasypt.encryptor.password为必须用户指定,其他配置均提供缺省值,algorithm的缺省配置弃用PBExxx默认的PBEWithMD5AndDES,改为强度更高的PBEWITHHMACSHA512ANDAES_256, 因此对Springboot中的加密结果做Jasypt手工解密时,需同时做password和algorithm的配置。下面案例展示使用默认数据加密,并使用Jasypt“原生”接口做解密验证:
application.properties添加配置:
jasypt.encryptor.password=passwd@Autowired
StringEncryptor;String cypherText = stringEncryptor.encrypt("123456");
System.out.println(String.format("密文为:%s", cypherText));
输出:
密文为:iw7cURRMFU2Wl7/k31mG0Sn8CVjdJ10xu4cb9vodOjbB7efNLui3CI6xgv4DSItY
使用“原生”接口对输出做解密:
AES256TextEncryptor textEncryptor = new AES256TextEncryptor();
textEncryptor.setPassword("passwd");
String myEncryptedText = textEncryptor.decrypt("iw7cURRMFU2Wl7/k31mG0Sn8CVjdJ10xu4cb9vodOjbB7efNLui3CI6xgv4DSItY");
System.out.println(String.format("解密结果为:%s", myEncryptedText) );
输出:
解密结果为:123456
8、Jasypt+Springboot自定义加密器
Jasypt-spring-boo默认注入StringEncryptor加密器的bean-id为”jasyptStringEncryptor”,如需覆盖该加密器,只需在配置类中重新声明新的类型为StringEncryptor且bean-id为”jasyptStringEncryptor”的加密器即可,jasypt-spring-boot-starter通过是否已存在该名称的bean决定是否注入默认的加密器,案例如下:
//添加配置类
@Configuration
public class JasyptConfig {@Bean(name="jasyptStringEncryptor")@Primarystatic public StringEncryptor stringEncryptor() {StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();encryptor.setPassword("passwd");encryptor.setAlgorithm("PBEWITHMD5ANDDES");return encryptor;}
}
输出:
加密结果为:H3QMRyMGPNzYW8QcdhFg1w==
解密结果为:123456
从加密结果长度可看出,@Autowired注入的为自定义的加密器,结果符合预期。自定义加密器仅要求返回StringEncryptor接口,如果开发者需要实现自己的加密算法,只需要实现该接口即可。
9、Jasypt+Springboot配置文件加密
jasypt-spring-boot提供属性检测的功能,对于配置文件的配置项,如果符合jasypt-spring-boot指定的规则,则会自动解密还原为明文注入到对应的代码中,默认规则为ENC(),举例:
//配置文件为
jasypt.encryptor.password=passwd
my.password=ENC(H3QMRyMGPNzYW8QcdhFg1w==)@Value("${my.password:}")private String password;
System.out.println(String.format("my.password:%s", password));
输出:
my.password: 123456
为避免jasypt.encryptor.password本文直接写在配置文件里,jasypt-spring-boot允许通过环境变量或启动参数传入所以配置,因此可以通过环境变量隐藏口令,步骤如下:
启动前:
export jasypt.encryptor.password=xxx启动应用:
java -jar xxx.jar待应用java完成配置注入后,删除环境变量:
export jasypt.encryptor.password=
相关文章:
Jasypt加密库基本使用方法
目录 1 Jasypt简介... 2 基础知识回顾... 3 Jasypt基本加密器... 4 JasyptPBE加密器... 5 Jasypt池化加密器... 6 Jasypt客户端工具... 7 JasyptSpringboot基本用法... 8 JasyptSpringboot自定义加密器... 9 JasyptSprin…...
C++并发编程之五 高级线程管理
文章目录5.1.1 线程池5.1.1 线程池 在前面我们引入了线程的通信和同步手段,那么为什么还要引入线程池呢? 线程池是一种管理多个线程的技术,它可以减少线程的创建和销毁的开销,提高并发性能。线程池中有一定数量的空闲线程&#x…...
单片机——IIC协议与24C02
1、基础知识 1.1、IIC串行总线的组成及工作原理 I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。 1.2、I2C总线的数据传输 I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟…...
案例05-将不必要的逻辑放到前端(发送调查问卷)
目录一:背景介绍背景二:思路&方案重大问题:解决办法优点:三:总结一:背景介绍 本篇博客书写的意义是警示大家不必把不必要的逻辑放到前端。 明确前后端分离的意义。 背景 下面的主要逻辑是࿱…...
【每日一题】——矩阵相等判定
🌏博客主页:PH_modest的博客主页 🚩当前专栏:每日一题 💌其他专栏: 🔴 每日反刍 🟢 读书笔记 🟡 C语言跬步积累 🌈座右铭:广积粮,缓称…...
Linux防火墙的关闭
查看防火墙的状态打开终端输入如下命令systemctl status firewalld如图所示:running表示防火墙目前处于打开状态输入命令进行关闭防火墙:systemctl stop firewalld如图所示正常的用户是没有权限的,需要输入管理员的密码才能够进行关闭防火墙。…...
Request和Response的概述
⭐作者介绍:大二本科网络工程专业在读,持续学习Java,输出优质文章⭐作者主页:︶ㄣ释然⭐如果觉得文章写的不错,欢迎点个关注😉有写的不好的地方也欢迎指正,一同进步😁Request和Respo…...
常见的Web安全漏洞:SYN攻击/CSRF/XSS
一、SYN攻击(属于DOS攻击) 什么情况下被动方出现SYN_RCVD状态?(flood攻击服务) 客户伪造 ip 端口, 向服务端发送SYN请求。完成2次握手,第三次服务端 等待客户端ACK确认,但由于客户不存在服务端一直未收到确认&#…...
【STC15单片机】 超声波模块的使用
目录 1 基于STC15F2K60S2的超声波测距代码 1.1 基本注意事项 1.1.1 跳线帽接法 1.1.2 晶振设置 1.2 板载超声波工作原理 1.2.1 原理总结 1.2.2 超声波代码思路 1.3 STC15单片机代码部分 1.3.1 定时器0&定时器1初始化 1.3.2 超声波ultrasonic.c ultrasonic.h文件配…...
SpringBoot 动态操作定时任务(启动、停止、修改执行周期)增强版
前段时间编写了一篇博客SpringBoot 动态操作定时任务(启动、停止、修改执行周期,该篇博客还是帮助了很多同学。 但是该篇博客中的方法有些不足的地方: 只能通过前端控制器controller手动注册任务。【具体的应该是我们提前配置好我们的任务&am…...
快排函数 -- qsort函数(Quick Sort)
文章目录🔎1.qsort函数简介💡1.1.函数原型💡1.2.参数含义🔎2.比较函数介绍🔎3.比较函数使用案例💡3.1.整型数组💡3.2.浮点型数组💡3.3.结构体类型 - 字符串🔎4.利用冒泡排…...
条形码和二维码
前言:需要的包的相关文档 1. Barcode:https://pypi.org/project/python-barcode/0.8.1/ 2. Qrcode:https://pypi.org/project/qrcode/ 3. Zbar: https://pypi.org/project/pyzbar/ 4. Opencv: https://docs.opencv.org/3.4.11/ 5. OpenC…...
大数据-学习实践-5企业级解决方案
大数据-学习实践-5企业级解决方案 (大数据系列) 文章目录大数据-学习实践-5企业级解决方案1知识点2具体内容2.1小文件问题2.1.1 SequenceFile2.1.2 MapFile2.1.3 小文件存储计算2.2数据倾斜2.3 YARN2.3.1 YARN架构2.3.2 YARN调度器2.3.2 YARN多资源队列配置和使用2.4Hadoop官方…...
破解吲哚花菁素IR-808 N3,IR-808 azide,IR-808叠氮,酯溶性染料修饰叠氮基团,相关知识
基础产品数据(Basic Product Data):CAS号:N/A中文名:IR-808叠氮英文名:IR-808 N3,IR-808 azideIR-808结构式(Structural):详细产品数据(Detailed …...
面试官:MQ的好处到底有哪些?
💗推荐阅读文章💗 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》🌺MySQL系列🌺👉2️⃣《MySQL系列教程》🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》…...
事务机制:Redis能实现ACID属性吗?
ACID特性无需多言。我们知道关系数据库比如mysql可以实现事务的ACID特性,begin,commit,回滚实现。 那么redis可以实现ACID吗,结论是不能完全保证。 首先要知道redis通过MULTI关键字开启事务,中间一系列操作,加到操作队列中并不执…...
如何在 Apinto 实现 HTTP 与 gRPC 的协议转换(上)
什么是 gRPC 像 gRPC 是由 google 开发的一个高性能、通用的开源 RPC 框架,主要面向移动应用开发且基于 HTTP/2 协议标准而设计,同时支持大多数流行的编程语言。 gRPC 基于 HTTP/2 协议传输,而 HTTP/2 相比 HTTP1.x ,有以下优势:…...
3分钟看完-丄-Python自动化测试【项目实战解析】经验分享
目录:导读 引言 自动化测试 背景 测试团队 测试体系发展 测试平台 自动化测试现状 现状一: 现状二: 现状三: 现状四: 现状五: 现状六: 失败的背景 失败的经历 失败总结 引言 内…...
Web漏洞-命令执行和代码执行漏洞
命令执行原理就是指用户通过浏览器或其他辅助程序提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令。漏洞成因它所执行的命令会继承WebServer的权限,也就是说可以任意读取、修改、执行Web目录下的…...
Towards Unsupervised Text Classification Leveraging Experts and Word Embeddings
Towards Unsupervised Text Classification Leveraging Experts and Word Embeddings Abstract 该论文提出了一种无监督的方法,使用每个文档中相关单词之间的文本相似度以及每个类别的关键字字典将文档分为几类。所提出的方法通过人类专业知识和语言模型丰富了类别…...
linux进程管理
进程管理 进程是启动的可执行程序的一个指令 1、进程简介 (1)进程的组成部分 已分配内存的地址空间安全属性,包括所有权凭据和特权程序代码的一个或多个执行线程进程状态 (2)程序和进程的区别 程序是一个静态的二进制…...
【深度强化学习】(6) PPO 模型解析,附Pytorch完整代码
大家好,今天和各位分享一下深度强化学习中的近端策略优化算法(proximal policy optimization,PPO),并借助 OpenAI 的 gym 环境完成一个小案例,完整代码可以从我的 GitHub 中获得: https://gith…...
【数据结构】第二站:顺序表
目录 一、线性表 二、顺序表 1.顺序表的概念以及结构 2.顺序表的接口实现 3.顺序表完整代码 三、顺序表的经典题目 1.移除元素 2.删除有序数组中的重复项 3.合并两个有序数组 一、线性表 在了解顺序表前,我们得先了解线性表的概念 线性表(linear…...
嵌入式安防监控项目——实现真实数据的上传
目录 一、相关驱动开发 二、A9主框架 三、脚本及数据上传实验 https://www.yuque.com/uh1h8r/dqrma0/tx0fq08mw1ar1sor?singleDoc# 《常见问题》 上个笔记的相关问题 一、相关驱动开发 /* mpu6050六轴传感器 */ i2c138B0000 { /* #address-cells <1>…...
SAP 生成UUID
UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织应用在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部分。 UUID-Universally…...
DevOPs介绍,这一篇就足够了
一、什么是DevOps? DevOps是一种将软件开发和IT运维进行整合的文化和运动。它的目标是通过加强软件开发、测试和运维之间的协作和沟通,使整个软件开发和交付过程更加高效、快速、安全和可靠。DevOps涵盖了从计划和设计到开发、测试、交付和部署的全生命…...
libcurl库简介
一、libcurl简介libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,和用户认证。…...
Spark SQL支持DataFrame操作的数据源
DataFrame提供统一接口加载和保存数据源中的数据,包括:结构化数据、Parquet文件、JSON文件、Hive表,以及通过JDBC连接外部数据源。一个DataFrame可以作为普通的RDD操作,也可以通过(registerTempTable)注册成…...
Java【归并排序】算法, 大白话式图文解析(附代码)
文章目录前言一、排序相关概念1, 什么是排序2, 什么是排序的稳定性3, 七大排序分类二、归并排序1, 图文解析2, 代码实现三、性能分析四、七大排序算法总体分析前言 各位读者好, 我是小陈, 这是我的个人主页 小陈还在持续努力学习编程, 努力通过博客输出所学知识 如果本篇对你有…...
【springboot】数据库访问
1、SQL 1、数据源的自动配置-HikariDataSource 1、导入JDBC场景 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency>数据库驱动? 为什么导入JD…...
文章一键导入wordpress/域名买卖交易平台
1.pip 功能:pip 是 Python 包管理工具,该工具提供了对Python 包的查找、下载、安装、卸载的功能。 2.pip 安装:Python 2.7.9 或 Python 3.4 以上版本都自带 pip 工具。 3.验证pip是否安装: pip --version 4.pip 下载的包的目录…...
网站群如何做网站/站长推荐入口自动跳转
传送门:hdu4185 Oil Skimming 题意:n*n的方格里有字符*和#,只能在字符#上放1*2的板子且不能相交,求最多能放多少个。 分析:直接给#字符编号,然后相邻的可以匹配,建边后无向图跑匈牙利算法&#…...
500m主机空间能做视频网站吗/游戏推广合作
最近蚂蚁金服的名字变了,全称已从“蚂蚁小微金融服务股份有限公司”改为“蚂蚁科技集团股份有限公司”。金服变为科技,浙江的区域标签也拿掉,凸显了数字化、全球战略的升级。这岂不意味着新一波的招聘需求?打开 boss 一看…...
建设什么网站/官网优化 报价
图论涉及的内容广泛,复杂,综合性较强。我在学习《算法竞赛进阶指南》图论部分后,为了方便日后复习让自己感觉学了东西,写下这篇大杂汇,内容主要源自我自己对《算法竞赛进阶指南》图论部分概括以及学习做题的经验。 一、…...
建立网站准备工作/郑州手机网站建设
看到个好文章,翻译一遍分享一下。 此为https://go101.org/article/channel-closing.html的翻译,侵删。 文章目录怎么优雅地关闭通道通道的关闭原则简单粗暴的方案礼貌的方案优雅的方案更多场景?结论怎么优雅地关闭通道 许多天前,…...
萝岗网站建设/腾讯企点app
在海底捞、西贝等餐饮企业涨价之后,妹子们用来续命的奶茶也开始涨价了,近一个月内,喜茶、奈雪、CoCo、一点点部分产品都涨价1-4元。奶茶涨价,别拿原材料涨价当借口事实上,从 2月中旬开始,喜茶旗下的豆豆波波…...