QT MD4 MD5 Sha1等几种加密方式

QT MD4 MD5 Sha1等几种加密方式

  • [1] QT MD4 MD5 Sha1等几种加密方式
  • [2] qt MD5 和AES 加密
    • 一 、MD5 加密
    • 二、AES 加密和解密
  • [3] QT中sqlite数据库数据加密/混淆---MD5/SHA1/SHA2/SHA3
    • (1)创建一个加密对象
    • (2)放入要加密的数据
    • (3)获取加密的结果
    • 测试
    • 结果显示
  • [4] [Qt学习笔记]Qt程序加密,实现软件运行次数和硬件信息绑定
    • 1、思路分析
    • 2、实现函数
    • 3、示例代码
    • 4、效果展示
  • [5] Qt--探讨.exe程序加密
    • 一、前言
    • 二、分析
    • 三、实现(核心代码)
    • 四、效果
    • 附:MD5加密注册码
  • [6] Qt之Base64编解码
    • 编码
    • 解码
    • CTK Plugin Framework插件框架学习1--Qt编译CTK


[1] QT MD4 MD5 Sha1等几种加密方式

原文链接:https://blog.csdn.net/xiezhongyuan07/article/details/80594108?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-80594108-blog-121167585.235%5Ev35%5Epc_relevant_increate_t0_download_v2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-80594108-blog-121167585.235%5Ev35%5Epc_relevant_increate_t0_download_v2&utm_relevant_index=3

QT 自带有QCryptographicHash类可以进行很方便的进行 md4 、md5等加密。使用方法很简单,直接提供了一个静态的方法。

QByteArray QCryptographicHash::hash(const QByteArray &data, Algorithm method)

data就是要加密的数据, method是加密的方法,看官方文档选择加密的方式就行。
在这里插入图片描述

QString strCipher = QCryptographicHash::hash(strKey.toLocal8Bit(), QCryptographicHash::Md5);
QString MainWindow::fileMd5(const QString &sourceFilePath) {
 
    QFile sourceFile(sourceFilePath);
    qint64 fileSize = sourceFile.size();
    const qint64 bufferSize = 10240;
 
    if (sourceFile.open(QIODevice::ReadOnly)) {
        char buffer[bufferSize];
        int bytesRead;
        int readSize = qMin(fileSize, bufferSize);
 
        QCryptographicHash hash(QCryptographicHash::Md5);
 
        while (readSize > 0 && (bytesRead = sourceFile.read(buffer, readSize)) > 0) {
            fileSize -= bytesRead;
            hash.addData(buffer, bytesRead);
            readSize = qMin(fileSize, bufferSize);
        }
 
        sourceFile.close();
        return QString(hash.result().toHex());
    }
    return QString();
}

[2] qt MD5 和AES 加密

一 、MD5 加密

#include <QCryptographicHash>
 
 
// MD5 加密
QString Dialog_login::MD5_encryption(const QString &data)
{
    QCryptographicHash md5(QCryptographicHash::Md5);    //使用MD5加密
    md5.addData(data.toUtf8(),data.size());   // 添加数据
    QByteArray bArry = md5.result();    //获取MD5加密后的密码
    QString md5_date;
    md5_data.append(bArry.toHex());
 
    return md5_data;
}

二、AES 加密和解密

https://blog.csdn.net/chen1231985111/article/details/125748534

1. 下载库:https://github.com/bricke/Qt-AES

下载后需要下面5个文件,把这些文件复制出来放到一个文件夹下:
在这里插入图片描述
2. qt 工程添加这些文件
在这里插入图片描述
3. 编写加密解密代码

#include "aesni/qaesencryption.h"
 
 
// 加密
QString Dialog_login::AES_encryption(const QString &data, const QString &key)
{
    QAESEncryption encryption(QAESEncryption::AES_128, QAESEncryption::ECB, QAESEncryption::PKCS7);
    QByteArray enBA = encryption.encode(data.toUtf8(), key.toUtf8());
    return QString::fromLatin1(enBA.toBase64());
}
 
// 解密
QString Dialog_login::AES_decryption(const QString &data, const QString &key)
{
    QAESEncryption encryption(QAESEncryption::AES_128, QAESEncryption::ECB, QAESEncryption::PKCS7);
    QByteArray  enBA = QByteArray::fromBase64(data.toUtf8());
    QByteArray deBA = encryption.decode(enBA, key.toUtf8());
    return QString::fromLatin1(QAESEncryption::RemovePadding(deBA, QAESEncryption::PKCS7));
}

[3] QT中sqlite数据库数据加密/混淆—MD5/SHA1/SHA2/SHA3

原文链接:https://blog.csdn.net/qq_43533553/article/details/123416880

利用分解质因数的运算(质数取模)原理实现的,比如:给你100个数让你乘起来比较容易但是给你一个数让你求它100个质数就会比较难,所以数据加密就用这种方法来实现。
MD5是一种将任意长度的数据进行变换得到128位2进制数据,无法通过128位数据求的原始数据。
在QT中使用:

(1)创建一个加密对象

QCryptographicHash hash(QCryptographicHash::Md5);

(2)放入要加密的数据

void QCryptographicHash::addData(const QByteArray &data);
//hash.addData(password.toUft8());

(3)获取加密的结果

QByteArray QCryptographicHash::result() const;
//hash.result();

测试

//对密码进行MD5加密
//1.创建加密对象
 QCryptographicHash hash(QCryptographicHash::Md5);
 //2.放入要加入的数据
 hash.addData(password.toUtf8());
 //3.获取加密的结果
 QByteArray  arr = hash.result();
 password = arr.toHex();
 qDebug()<<password; 

结果显示

在这里插入图片描述

[4] [Qt学习笔记]Qt程序加密,实现软件运行次数和硬件信息绑定

原文链接:https://blog.csdn.net/fengyaowuhui/article/details/126150459

前言
程序员为了防止自己的成果被白嫖,或者发布的软件在公司层面上要做一些防抄袭处理,这时就需要在软件层面上加锁、加密等操作。
1、单机终端软件
这类软件一般在未联网的情况下使用,所以不能通过网络去判定是否得到授权,一般采用绑定硬件信息来对软件进行加密,这样软件与设备绑定就无法进行随意使用。
2、远程授权监控
终端软件在启动后就会跟服务器通讯来检查当前设备是否已经得到授权,可实现远程锁定程序,设置程序的使用时间和使用次数。
以上两种方法都是最基础的软件加密方法,根据加密的算法的复杂度其破解的难度也不同,不过作为普通的一种加密方法已经够用了,市面上有比较成熟的加密加壳的软件,其安全程度要远高于软件加密的方法,下次抽时间介绍一下软件VMProtect的加、解密过程。

1、思路分析

单机软件想要每次启动前去验证是否有授权,需要从软件的配置中获取授权的验证信息,这里以软件的使用次数来举例,我们需要把软件的可使用次数写入配置文件ini或数据库中。每次在软件重新启动时,我们根据配置文件中信息来判断软件剩余的使用次数。
在这里插入图片描述

这里设定软件的剩余使用次数为2次,不过这里有一个很明显的缺点,就是明文写到配置文件里,就可以自己修改,然后就失去了加密的属性,这里就需要对这个信息进行加密后再写入。这里使用Qt自带的base64对字符串进行加密。

2、实现函数

//加密
QString Widget::Encode(QString row)
{
    QByteArray byteArray = row.toUtf8();
    byteArray = byteArray.toBase64();
    return  byteArray;
}
//解密
QString Widget::Decode(QString passwd)
{
    QByteArray byteArray = passwd.toUtf8();
    byteArray = QByteArray::fromBase64(byteArray);
    return byteArray;
}
//从配置文件获取信息
QString Widget::getInfoFromIni(QString str)
{
    QString info;
    QFile file(str);
    if(!file.exists()) { //如果文件不存在
        QString times_str = "RemainTime:"+time;
        WriteInfo2Ini(str, times_str);
    }
    file.open(QFile::ReadWrite | QFile::Text);
    info = file.readAll(); //读取信息
    file.close();
    return info;
}
//将信息写入到配置文件
void Widget::WriteInfo2Ini(QString str, QString info_text)
{
    QFile file(str);
    file.open(QFile::ReadWrite | QFile::Text | QFile::Truncate);
    file.write(Encode(info_text).toUtf8()); //写入信息
    file.close();
}

这种方法有一种弊端,就是如果重新覆盖配置文件可以跳出限制,比如这里如果事前拷贝一份ini文件,当软件次数为0后,重新拷贝原始ini文件后又获得初始的软件使用次数。
如果考虑不使用ini文件来记录授权信息,而是使用注册表来记录授权信息,这样软件使用者就不容易去发现授权信息的位置

void Widget::WriteInfo2Registry(QString str)
{
    //写入注册表
    QSettings settings("HKEY_CURRENT_USER\\Software\\Code_Encryption\\Settings",QSettings::NativeFormat);
    settings.setValue("remain_times",Encode(str).toUtf8());
}

QString Widget::getInfoFromRegistry()
{
    QString info;
    //通过写入注册表来判断
    QSettings settings("HKEY_CURRENT_USER\\Software\\Code_Encryption\\Settings",QSettings::NativeFormat);
    info = settings.value("remain_times").toString();
    return info;
}

3、示例代码

widget.cpp

#pragma execution_character_set("utf-8")
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    QString str = getCpuId();
    qDebug()<<"cpu id is"<<str;
//    QString times_str = "RemainTime:"+time;
//    WriteInfo2Registry(times_str);
    Judge_Authorize_times(1);
}

Widget::~Widget()
{
    delete ui;
}

QString Widget::getWMIC(const QString &cmd)
{
    //获取cpu名称:wmic cpu get Name
    //获取cpu核心数:wmic cpu get NumberOfCores
    //获取cpu线程数:wmic cpu get NumberOfLogicalProcessors
    //查询cpu序列号:wmic cpu get processorid
    //查询主板序列号:wmic baseboard get serialnumber
    //查询BIOS序列号:wmic bios get serialnumber
    //查看硬盘:wmic diskdrive get serialnumber
    QProcess p;
    p.start(cmd);
    p.waitForFinished();
    QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
    QStringList list = cmd.split(" ");
    result = result.remove(list.last(), Qt::CaseInsensitive);
    result = result.replace("\r", "");
    result = result.replace("\n", "");
    result = result.simplified();
    return result;
}

QString Widget::getCpuId() //获取CPU序列号
{
    return getWMIC("wmic cpu get processorid");
}

QString Widget::getDiskNum() //获取硬盘序列号
{
    return getWMIC("wmic diskdrive where index=0 get serialnumber");
}

QString Widget::Encode(QString row)
{
    QByteArray byteArray = row.toUtf8();
    byteArray = byteArray.toBase64();
    return  byteArray;
}
QString Widget::Decode(QString passwd)
{
    QByteArray byteArray = passwd.toUtf8();
    byteArray = QByteArray::fromBase64(byteArray);
    return byteArray;
}

QString Widget::getInfoFromIni(QString str)
{
    QString info;
    QFile file(str);
    if(!file.exists()) { //如果文件不存在
        QString times_str = "RemainTime:"+time;
        WriteInfo2Ini(str, times_str);
    }
    file.open(QFile::ReadWrite | QFile::Text);
    info = file.readAll(); //读取信息
    file.close();
    return info;
}

void Widget::WriteInfo2Ini(QString str, QString info_text)
{
    QFile file(str);
    file.open(QFile::ReadWrite | QFile::Text | QFile::Truncate);
    file.write(Encode(info_text).toUtf8()); //写入信息
    file.close();
}

void Widget::WriteInfo2Registry(QString str)
{
    //写入注册表
    QSettings settings("HKEY_CURRENT_USER\\Software\\Code_Encryption\\Settings",QSettings::NativeFormat);
    settings.setValue("remain_times",Encode(str).toUtf8());
}

QString Widget::getInfoFromRegistry()
{
    QString info;
    //通过写入注册表来判断
    QSettings settings("HKEY_CURRENT_USER\\Software\\Code_Encryption\\Settings",QSettings::NativeFormat);
    info = settings.value("remain_times").toString();
    return info;
}

void Widget::Judge_Authorize_times(int type)
{
    QString times_info;
    if(type == 0)
    {
        //通过ini配置文件进行判断
        times_info = getInfoFromIni("System.ini");
    }
    else
    {
        //通过写入注册表来判断
        times_info = getInfoFromRegistry();
    }

    if(times_info.isEmpty())
    {
        QMessageBox::about(this,"提示","授权信息为空,请检查!");
        exit(0);
    }
    else
    {
        QString info = Decode(times_info); //解码
        if(info.contains(':')) {	//信息正确
            QStringList list = info.split(':');
            if(list.length()>=1) {
                if(list[1].toInt() <= 0) {	//程序剩余使用次数不足
                    QMessageBox::about(this,"提示","请注册后再使用!");
                    exit(0); //程序退出
                }else {	//程序还有剩余使用次数
                    QString time_remain = QString::number(list[1].toInt()-1); //程序剩余使用次数减1
                    QString str = "RemainTime:"+time_remain;
                    if(type == 0) WriteInfo2Ini("System.ini", str);
                    else {
                        //写入注册表
                        WriteInfo2Registry(str);
                    }

                    QMessageBox::about(this,"提示","程序剩余使用次数:"+time_remain+"次");
                }
            }
        }

    }

}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QFile>
#include <QMessageBox>
#include <QProcess>
#include <QDebug>
#include <QSettings>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;

    QString getWMIC(const QString &cmd);
    QString getCpuId();
    QString getDiskNum();
    //加密
    QString Encode(QString row);
    //解密
    QString Decode(QString passwd);
    //判断授权信息  0:使用ini方法判断;1:使用注册表方法判断
    void Judge_Authorize_times(int type);
    //从ini获取授权信息
    QString getInfoFromIni(QString str);
    //写入授权信息到ini
    void WriteInfo2Ini(QString str, QString info_text);
    //从注册表获取授权信息
    QString getInfoFromRegistry();
    //写入授权信息到注册表
    void WriteInfo2Registry(QString str);
    //授权程序使用次数为2次
    QString time = "2";

};

#endif // WIDGET_H

4、效果展示

在这里插入图片描述

[5] Qt–探讨.exe程序加密

原文链接:https://blog.csdn.net/Mr_robot_strange/article/details/108776517

一、前言

程序员随着代码写的多,难免会接到一些私活。但是又怕对方白嫖,困难总比办法多,哦不,错了,办法总比困难多。为了避免被别人白嫖,我们可以给自己的程序留后手,网上查阅资料,大概有以下两种:

1、采用远程控制:UDP指令远程锁死程序;

2、采用本地加密:提取CPU和硬盘序列号,加密生成注册码;

以上两种方法各有利弊,方法1可以本人自由控制,但是一旦设备没网,就GG了;方法2则不依赖网络,且每台设备的注册码唯一,但是本人无法直接控制。个人认为还是方法2简单有效,所以下面就方法2进行具体分析。

二、分析

采用注册码机制,我们首先要生成注册码,Qt下获取CPU和硬盘等系统信息(针对windows系统)的方法如下:

windows下执行命令除了用cmd之外,还有个东西叫WMIC,非常强大,可以通过他获取很多信息,包括硬件信息。

QString Widget::getWMIC(const QString &cmd)
{
    //获取cpu名称:wmic cpu get Name
    //获取cpu核心数:wmic cpu get NumberOfCores
    //获取cpu线程数:wmic cpu get NumberOfLogicalProcessors
    //查询cpu序列号:wmic cpu get processorid
    //查询主板序列号:wmic baseboard get serialnumber
    //查询BIOS序列号:wmic bios get serialnumber
    //查看硬盘:wmic diskdrive get serialnumber
    QProcess p;
    p.start(cmd);
    p.waitForFinished();
    QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
    QStringList list = cmd.split(" ");
    result = result.remove(list.last(), Qt::CaseInsensitive);
    result = result.replace("\r", "");
    result = result.replace("\n", "");
    result = result.simplified();
    return result;
}
 
QString Widget::getCpuName()
{
    return getWMIC("wmic cpu get name");
}
 
QString Widget::getCpuId()
{
    return getWMIC("wmic cpu get processorid");
}
 
QString Widget::getDiskNum()
{
    return getWMIC("wmic diskdrive where index=0 get serialnumber");
}

获取注册码之后,就可以着手程序的加密了,我的策略是这样的:

如果程序没有注册,默认可以使用3次;
如果程序注册了,使用次数无限制;
那怎么限制程序的使用次数呢?我的策略是这样的:

生成一个System.ini配置文件,里面存放程序的剩余运行次数RemainTime:3;
但是RemainTime:3当然不能直接存在System.ini中,不然一眼看出来就可以自己修改次数了;
所以在对System.ini写之前,进行加密;对System.ini读之后,进行解密;
加/解密算法可以自行选取,但是要采用可逆算法;
然后判断剩余运行次数,如果小于等于0,则程序提示需注册后使用,并退出;
否则,剩余运行次数减1,程序正常运行;

三、实现(核心代码)

QString Widget::getWMIC(const QString &cmd)
{
    //获取cpu名称:wmic cpu get Name
    //获取cpu核心数:wmic cpu get NumberOfCores
    //获取cpu线程数:wmic cpu get NumberOfLogicalProcessors
    //查询cpu序列号:wmic cpu get processorid
    //查询主板序列号:wmic baseboard get serialnumber
    //查询BIOS序列号:wmic bios get serialnumber
    //查看硬盘:wmic diskdrive get serialnumber
    QProcess p;
    p.start(cmd);
    p.waitForFinished();
    QString result = QString::fromLocal8Bit(p.readAllStandardOutput());
    QStringList list = cmd.split(" ");
    result = result.remove(list.last(), Qt::CaseInsensitive);
    result = result.replace("\r", "");
    result = result.replace("\n", "");
    result = result.simplified();
    return result;
}

QString Widget::getCpuId() //获取CPU序列号
{
    return getWMIC("wmic cpu get processorid");
}

QString Widget::getDiskNum() //获取硬盘序列号
{
    return getWMIC("wmic diskdrive where index=0 get serialnumber");
}

QString Widget::Encode(QString row) //加密,由于加/解密不是本文重点,故简单处理一下
{
    QByteArray byteArray = row.toUtf8();
    byteArray = byteArray.toBase64();
    return  byteArray;
}
QString Widget::Decode(QString passwd) //解密
{
    QByteArray byteArray = passwd.toUtf8();
    byteArray = QByteArray::fromBase64(byteArray);
    return byteArray;
}

void Widget::Judge_Valid() //判断程序合法性
{
    QString filePath = "System.ini";
    QFile file(filePath);

    if(!file.exists()) { //如果文件不存在
        file.open(QIODevice::ReadWrite | QIODevice::Text); //新建文件
        QString info = "RemainTime:"+time; //time是全局变量,QString time = "3";
        file.write(Encode(info).toUtf8()); //写入信息
        file.close();
         goto Here;
    }else {	//如果文件存在
        Here:if(file.open(QFile::ReadWrite | QFile::Text)) { //打开文件
            QString info = file.readAll(); //读取信息
            if(info.isEmpty()) { //如果文件为空
                QString time_temp = "1";
                QString info = "RemainTime:"+time_temp;
                file.write(Encode(info).toUtf8()); //写入信息
                info = file.readAll();
            }
            info = Decode(info); //解码
            if(info.contains(':')) {	//信息正确
                QStringList list = info.split(':');
                if(list.length()>=1) {
                    if(list[1].toInt() <= 0) {	//程序剩余使用次数不足
                        QMessageBox::about(this,"提示","请注册后再使用!");
                        exit(0); //程序退出
                    }else {	//程序还有剩余使用次数
                        file.close();
                        file.open(QFile::ReadWrite | QFile::Text | QFile::Truncate); //清空文件内容
                        QString time_remain = QString::number(list[1].toInt()-1); //程序剩余使用次数减1
                        QString info = "RemainTime:"+time_remain;
                        file.write(Encode(info).toUtf8()); //更新程序剩余使用次数
                        QMessageBox::about(this,"提示","程序剩余使用次数:"+time_remain+"次");
                    }
                }
            }
      }//Here
      file.close();

   }//如果文件存在
}

四、效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

附:MD5加密注册码

//获取设备信息字符串
const QString get_SerialNumber()
{
    QString cpu_id = "";
    QProcess p(0);
    p.start("wmic CPU get ProcessorID");  //其它信息也类似
    p.waitForStarted();
    p.waitForFinished();
    cpu_id = QString::fromLocal8Bit(p.readAllStandardOutput());
    cpu_id = cpu_id.remove("ProcessorId").trimmed();

    QString lpRootPathName = "C:\\";
    LPTSTR lpVolumeNameBuffer=new TCHAR[12];//磁盘卷标
    DWORD nVolumeNameSize=12;// 卷标的字符串长度
    DWORD VolumeSerialNumber;//硬盘序列号
    DWORD MaximumComponentLength;// 最大的文件长度
    LPTSTR lpFileSystemNameBuffer=new TCHAR[10];// 存储所在盘符的分区类型的长指针变量
    DWORD nFileSystemNameSize=10;// 分区类型的长指针变量所指向的字符串长度
    DWORD FileSystemFlags;// 文件系统的一此标志
    GetVolumeInformation((LPTSTR)lpRootPathName.utf16(),
                         lpVolumeNameBuffer, nVolumeNameSize,
                         &VolumeSerialNumber, &MaximumComponentLength,
                         &FileSystemFlags,
                         lpFileSystemNameBuffer, nFileSystemNameSize);
    return (cpu_id.mid(0,4) + "D-"+ cpu_id.mid(4,4) + "R-" +
            cpu_id.mid(8,4) + "E-" + cpu_id.mid(12,4) + "A-" +
            QString::number(VolumeSerialNumber,10).mid(0,4)+"M");
}

//使用MD5对设备信息字符串进行加密
const QString hash_Encryption(const QString temp)
{
    QByteArray byte_array;
    byte_array.append(temp);
    QByteArray hash_byte_array = QCryptographicHash::hash(byte_array,QCryptographicHash::Md5);
    return hash_byte_array.toHex().toUpper();
}

//将加密后的字符串序列化为注册码形式
const QString format_HASHString(const QString hashtemp)
{
    QString retemp = "";
    for(int i = 0; i < 7; i++)
    {
        retemp += hashtemp.mid(4*i,4) + "-";
    }
    retemp += hashtemp.mid(28,4);
    return retemp;
}

//去除注册码格式,转化为MD5加密后的字符串
const QString remove_Format(const QString formathash)
{
    QString temp = "";
    for(int i = 0; i < 8; i++)
    {
        temp += formathash.mid(5*i,4);
    }
    return temp;
}

[6] Qt之Base64编解码

原文链接

编码

QByteArray QByteArray::toBase64() const
QByteArray QByteArray::toBase64(QByteArray::Base64Options options) const

示例

QByteArray text("Hello world");
text.toBase64(); 
/* 输出: SGVsbG8gd29ybGQ= */

解码

[static] QByteArray QByteArray::fromBase64(const QByteArray &base64)
[static] QByteArray QByteArray::fromBase64(const QByteArray &base64, 
                                           QByteArray::Base64Options options)

示例

QByteArray::fromBase64("SGVsbG8gd29ybGQ="); 
/* 输出: Hello world */

在这里插入图片描述

CTK Plugin Framework插件框架学习1–Qt编译CTK

https://wangjichuan.blog.csdn.net/article/details/128547331?spm=1001.2014.3001.5502

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

目前可用的ChatGPT网站

本文意在整理可用gpt-3.5、gpt-4.0等网站。 本文主要是方便自己翻阅&#xff0c;如对您也有所帮助&#xff0c;不胜荣幸~ 文章目录 chatgpt.qdymys.cngpttalkchatgpt-cn.cobing.comchat机器人wuguokai.cn总结 chatgpt.qdymys.cn 网址&#xff1a;https://chatgpt.qdymys.cn/限…

SpringCloud —— eureka

目录 1.认识微服务 1.0.学习目标 1.1.单体架构 1.2.分布式架构 1.3.微服务 1.4.SpringCloud 1.5.总结 2.服务拆分和远程调用 2.1.服务拆分原则 2.2.服务拆分示例 2.2.1.导入Sql语句 2.2.2.导入demo工程 2.3.实现远程调用案例 2.3.1.案例需求&#xff1a; 2.3.2.注…

mysql进阶-查询优化-慢查询日志

文章目录 一、什么是慢查询日志二、慢查询日志能干什么2.1 性能分析和优化2.2 诊断和排查问题2.3 数据分析和探索 三、慢查询日志实战3.1 永久开启开启慢查询日志3.2 临时开启慢查询日志3.4 常用命令 四、如何分析慢查询日志五、优化慢查询语句五、总结 一、什么是慢查询日志 …

观察者设计模式(Observer Design Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

文章目录 概念组成角色相关图示示例代码框架中的运用适用场景 概念 观察者设计模式&#xff08;Observer Design Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一种对象间的一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象&#xff0c;当…

SpringBoot 配置文件

前言&#xff1a; 本篇主要介绍两种配置文件格式&#xff0c;分别为properties与yml(yaml)。 需要注意的是&#xff1a; 两个配置文件从功能上来讲是可以同时存在的&#xff0c;但是企业中通常会规定使用某一种格式的配置文件。如果同一个配置出现在两种格式的配置文件中的话&a…

微波方向有哪些SCI期刊推荐? - 易智编译EaseEditing

微波方向的SCI期刊推荐包括&#xff1a; IEEE Transactions on Microwave Theory and Technology&#xff1a; 该期刊是电磁场与微波技术领域的著名期刊&#xff0c;被世界上许多研究机构和大学广泛引用。 IEEE Transactions on Antennas and Propagation&#xff1a; 该期刊…

English Learning - L3 作业打卡 Lesson1 Day5 2023.5.9 周二

English Learning - L3 作业打卡 Lesson1 Day5 2023.5.9 周二 引言&#x1f349;句1: Fast loud music is popular with many people .成分划分爆破语调 &#x1f349;句2: They may say the music is red hot, especially the kind called Dixieland jazz.成分划分爆破语调 &a…

AI孙燕姿项目实现

最近在b站刷到很多关于ai孙笑川唱的歌曲&#xff0c;加上最近大火的ai孙燕姿&#xff0c; 这下“冷门歌手”整成热门歌手了 于是写下一篇文章&#xff0c; 如何实现属于的ai歌手。 注意滥用ai&#xff0c;侵犯他人的名誉是要承担法律责任的 下面是一些所需的文件链接&#xff…

低代码信创开发核心技术(一):基于Vue.js的描述依赖渲染DDR实现模型驱动的组件

前言 随着数字化转型的不断发展&#xff0c;低代码开发平台已成为企业快速建立自己的应用程序的首选方案。然而&#xff0c;实现这样一个平台需要具备高效、灵活和可定制化的能力。这正是基于描述依赖渲染&#xff08;Description dependency rendering&#xff09;所实现的。…

C语言CRC-16 XMODEM格式校验函数

C语言CRC-16 XMODEM格式校验函数 CRC-16校验产生2个字节长度的数据校验码&#xff0c;通过计算得到的校验码和获得的校验码比较&#xff0c;用于验证获得的数据的正确性。基本的CRC-16校验算法实现&#xff0c;参考&#xff1a; C语言标准CRC-16校验函数。 不同应用规范通过对…

三分钟阿里云服务器u1通用算力型性能、使用限制及费用说明

阿里云服务器u1是通用算力型云服务器&#xff0c;CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器&#xff0c;通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)&#xff0c…

C/C++每日一练(20230512) 成绩打印、补齐数组、水仙花数

目录 1. 成绩打印 ※ 2. 按要求补齐数组 &#x1f31f;&#x1f31f;&#x1f31f; 3. 水仙花数 ※ &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 成绩打印 一个班有10个同学&am…

隐语v0.8.2版本更新,首次发布TEEU

隐语v0.8.2版本更新&#x1f31f; 应用层 机器学习&#xff1a; - MPC 纵向 LR &#xff08;SSRegression&#xff09;新增 Policy SGD 优化器和 Early Stopping 支持&#xff0c;减少调参成本&#xff0c;加快收敛速度&#xff1b; - WOE 分箱进行了若干优化&#xff0c;性…

本地搭建wamp服务器并内网穿透实现无公网IP远程访问

文章目录 前言1.Wamp服务器搭建1.1 Wamp下载和安装1.2 Wamp网页测试 2. Cpolar内网穿透的安装和注册2.1 本地网页发布2.2 Cpolar云端设置2.3 Cpolar本地设置 3. 公网访问测试4. 结语 转载自cpolar极点云的文章&#xff1a;无公网IP&#xff1f;教你在外远程访问本地Wamp服务器「…

前端CSS学习(三)

1、盒子模型 盒子的概念1、页面中的每一个标签&#xff0c;都可看做是一 个“盒子” &#xff0c;通过盒子的视角更方便的进行布局2、浏览器在渲染 (显示)网页时&#xff0c;会将网页中的元素看做是一个个的矩形区域&#xff0c;我们也形象的称之为盒子CSS中规定每个盒子分别由…

Postman安装及入门接口测试使用步骤

前言 在软件测试行业中&#xff0c;作为一款比jemter更便捷更好用的软件测试工具&#xff0c;postman以其便捷灵活性首当其冲&#xff0c;成为当今测试行业领域使用较广泛的主流系统软件接口测试工具。今天Darren洋为大家讲解postman这款软件测试工具的下载安装及入门接口测试步…

Linux权限 - 概念与管理 | 文件权限的修改与转让 【详解】

目录 Linux权限 Linux权限的概念 Linux权限的基础操作 (1).实现用户账号的切换 (2).仅提升当前指令的权限 Linux权限管理 1、文件访问者的分类&#xff08;人&#xff09; 2、文件类型和访问权限&#xff08;事物属性&#xff09; 3、文件权限值的表示方法 4、文件访…

刷题刷题。

自然数拆分 利用step记录组合情况&#xff0c;只用sum不能判断组合情况 1.选择dfs原因&#xff1a;产生排列组合&#xff0c;和为7&#xff0c;step为8&#xff0c;其中7个空位&#xff0c;第8个step为输出&#xff1b; 参量的设置sum&#xff0c;step (进入下一层&#xff09;…

ThingsBoard教程(四十):规则节点解析 计算增量节点 Calculate delta

本篇文章介绍一个ThingsBoard 规则引擎中的一个节点,Calculate delta Calculate delta 计算增量 该节点可以在规则中获取上一次遥测的值,以此可以实现二次遥测的差。比如一个设备,一天上传一次数据,如果你要对比今天和昨天的数据,并将两者数据差保存到数据库,就能够使用…

Spring MVC

目录 什么是Spring MVC MVC定义 MVC和Spring MVC的关系 怎么学Spring MVC 创建Spring MVC项目 0.使用Spring Boot来创建Spring MVC项目 1.实现连接 2.获取参数 获取单个参数 获取多个参数 获取对象 后端参数重命名 获取JSON对象 从基础的URL中获取参数 上传文件Re…