springboot 数据传输的加密解密方式一: AES(对称加密)

全文目录,一步到位

  • 1.加密/解密方式一: `AES`
    • 1.1 AES`加密`简介
    • 1.2 AES`解密`简介
    • 1.3 AES细致介绍(`外链`)
  • 2. AES加密解密使用
    • 2.1 应用场景
      • 2.2 工具包使用方式
      • 2.2.0 (关键)生成一个`秘钥`(16位)
      • 2.2.1 AES加密文本
      • 2.2.2 AES解密文本
      • 2.2.3 AES加密文件(源)
      • 2.2.4 AES解密文件(源)
      • 2.2.5 文件AES加密并输出(终)
      • 2.2.6 文件AES解密并输出(终)
      • 2.2.7 使用(测试)方式一: `文本`
      • 2.2.8 使用(测试)方式二: `文件`
    • 2.3 执行结果
      • 2.3.1 控制台输出
      • 2.3.2 如图所示
    • 2.4 跳过2.2 工具包代码
      • 2.4.1 CryptoUtils密码学工具包
      • 2.4.2 测试代码完整版
      • 2.4.3 秘钥和IV随机 都是16位字符串即可 不可暴露
  • 3. 结合业务使用
    • 3.1 (`模拟`简易数据传输-收集功能)
      • 3.1.1 创建统一返回值(`叫啥都行`)
      • 3.1.2 controller层写一个demo
      • 3.1.3 数据采集注解(标记是否采集和加密)
      • 3.1.4 业务具体实现逻辑数据处理(略)
      • 3.1.5 测试结果(如图所示)
  • 4. 前端使用AES加密(大致流程)
    • 4.1 前端js实现方式
  • 5. 文章的总结与预告
    • 5.1 本文总结
    • 5.2 下文预告


1.加密/解密方式一: AES

本篇文章介绍的是 对称加密 AES
插一句:
非对称加密比对称加密更安全。

  • 对称加密: 安全性要求一般、且数据量较大的场景
    对称加密那样在通信之前要先同步秘钥
  • 非对称性加密: 对于安全性要求高、且数据量不大的场景
    非对称加密使用一对秘钥,一个用来加密,一个用来解密,而且公钥是公开的,秘钥是自己保存

1.1 AES加密简介

AES(Advanced Encryption Standard)是一种对称加密算法,也是目前最常用的加密方式之一。它在国际上被广泛使用,并且被应用于保护各种机密信息,如密码、信用卡信息、银行账户信息、电子邮件等。

AES加密算法使用的加密密钥和解密密钥都是相同的,并且加密和解密使用的算法方法也是相同的,因此称为对称加密算法。AES算法的密钥长度可以是128位、192位或256位,其中256位的密钥长度提供了最高的安全性,但同时也需要更高的计算能力。一般128位(bit) 即可 16字节

AES算法在加密时主要是通过替换、置换和异或等方式进行操作,具体过程包括四个步骤:密钥扩展、初始轮、重复轮和最后的输出。密钥扩展是根据输入的密钥生成相关的轮密钥,用于后续的加密过程中。初始轮是将输入数据进行基本的置换和异或操作。重复轮是将初始轮的结果进行多轮替换、置换和异或操作。最后的输出是将最后的结果输出为密文。

总体来说,AES加密算法具有可靠性高、安全性强的特点,被广泛使用于各种安全系统中。

1.2 AES解密简介

AES(Advanced Encryption Standard)解密操作是将加密过的数据使用相同的加密密钥进行解密操作,还原成原始数据的过程。AES解密算法使用的过程和加密算法相同,只是操作的顺序和方法稍有不同。

在AES解密过程中,需要使用相同的密钥才能成功解密数据。因此,需要确保密钥的安全性,防止被泄露。解密过程和加密过程是相反的,首先需要对密文进行逆向操作,还原经过置换和代换操作后的数据,然后进行逆向的轮操作,得到最终的明文。

具体的AES解密步骤如下:

  1. 密钥扩展:使用相同的加密密钥生成相应的轮密钥,用于后续的解密过程中。
  2. 逆向的输出:首先对密文进行逆向的输出,还原经过置换和代换操作后的数据。
  3. 逆向的重复轮:对还原的数据进行逆向的重复轮操作,还原初始轮和重复轮操作中的所有代换和置换操作。
  4. 最终输出:得到最终的明文,即加密前的数据。

需要注意的是,解密过程需要使用相同的密钥和相同的加密算法,否则将无法还原原始数据。同时,AES解密算法仅对数据进行加密和解密操作,不包括数据传输和存储的安全性问题。因此,在实际的应用中,还需要其他的安全机制来保障数据的安全。

1.3 AES细致介绍(外链)

介绍的相当全面(外链)

在这里插入图片描述

===> 传送门: aes加密原理及优势与劣势

2. AES加密解密使用

2.1 应用场景

应用于保护各种机密信息,如密码、信用卡信息、银行账户信息、电子邮件等

2.2 工具包使用方式

javax包下的javax.crypto.Cipher;

2.2.0 (关键)生成一个秘钥(16位)

这个密钥需要是16位 - 对应128bit
原因: 128的密钥长度是目前能对安全性和性能的一种比较理想的折中选择
可以放到nacos等配置中心中
也可以随机生成(很关键)

//示例: 
public static final String KEY_DES = "pzy0123456789pzy";

2.2.1 AES加密文本

  /**
     * AES加密文本
     *
     * @param content    明文
     * @param encryptKey 秘钥,必须为16个字符组成
     * @return 密文
     */
    public static String aesEncryptForFront(String content, String encryptKey) {
        if (StringUtils.isEmpty(content) || StringUtils.isEmpty(encryptKey)) {
            return null;
        }
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));

            byte[] encryptStr = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptStr);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

2.2.2 AES解密文本

    /**
     * AES解密文本
     *
     * @param encryptStr 密文
     * @param decryptKey 秘钥,必须为16个字符组成
     * @return 明文
     */
    public static String aesDecryptForFront(String encryptStr, String decryptKey) {
        if (StringUtils.isEmpty(encryptStr) || StringUtils.isEmpty(decryptKey)) {
            return null;
        }
        try {
            byte[] encryptByte = Base64.getDecoder().decode(encryptStr);
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
            byte[] decryptBytes = cipher.doFinal(encryptByte);
            return new String(decryptBytes);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

2.2.3 AES加密文件(源)

    /**
     * AES加密文件
     *
     * @param bytes      字节
     * @param encryptKey 秘钥key
     * @return 字节byte
     */
    public static byte[] aesEncryptForFront(byte[] bytes, String encryptKey) {
        if (StringUtils.isEmpty(bytes) || StringUtils.isEmpty(encryptKey)) {
            return null;
        }
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));

            return cipher.doFinal(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

2.2.4 AES解密文件(源)

  /**
     * AES解密文件
     *
     * @param bytes      字节
     * @param decryptKey 解密key
     * @return 解密字节
     */
    public static byte[] aesDecryptForFront(byte[] bytes, String decryptKey) {
        if (StringUtils.isEmpty(bytes) || StringUtils.isEmpty(decryptKey)) {
            return null;
        }
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"));
            return cipher.doFinal(bytes);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

2.2.5 文件AES加密并输出(终)

    /**
     * 文件AES加密并输出
     *
     * @param fileSourcePath 文件原始路径
     * @param outEncryptPath 加密数据文件路径
     * @throws IOException io异常
     */
    public static void fileAcsEncrypt(String fileSourcePath, String outEncryptPath) throws IOException {

        System.out.println("加密开始!");

        File file = new File(fileSourcePath);
        // 以 byte 的形式读取,不改变文件数据的编码格式
        byte[] bytes = Files.readAllBytes(file.toPath());

        byte[] outFile = CryptoUtils.aesEncryptForFront(bytes, CryptoUtils.KEY_DES);
        OutputStream out = new BufferedOutputStream(new FileOutputStream(outEncryptPath));
        assert outFile != null;
        out.write(outFile);
        out.flush();
    }

2.2.6 文件AES解密并输出(终)

  /**
     * 文件AES解密并输出
     *
     * @param fileEncryptPath 加密后文件路径
     * @param outDecryptPath  解密后文件路径
     * @throws IOException io异常
     */
    public static void fileAcsDecrypt(String fileEncryptPath, String outDecryptPath) throws IOException {
        File file = new File(fileEncryptPath);
        // 以 byte 的形式读取,不改变文件数据的编码格式
        byte[] outFile = CryptoUtils.aesDecryptForFront(Files.readAllBytes(file.toPath()), CryptoUtils.KEY_DES);
        OutputStream out = new BufferedOutputStream(new FileOutputStream(outDecryptPath));
        assert outFile != null;
        out.write(outFile);
        out.flush();

        System.out.println("解密结束!");
    }

2.2.7 使用(测试)方式一: 文本

main方法进行测试

 public static void main(String[] args) throws Exception {
        String old = "12345678";
        String target = "mbn/Mykb4f7xt2Zhz0xS6w=="; // 加密后的字符串

        //加密
        System.out.println(CryptoUtils.aesEncryptForFront(old, CryptoUtils.KEY_DES));

        //解密
        System.out.println(CryptoUtils.aesDecryptForFront(target, CryptoUtils.KEY_DES));
    }

2.2.8 使用(测试)方式二: 文件

举例中: pzy.txt文件需要有内容, 名称随意 后缀随意

//加密/解密(生成加密后的文件后缀可以自定义)
CryptoUtils.fileAcsEncrypt("D:\\pzy.txt", "D:\\pzy1.txt");
CryptoUtils.fileAcsDecrypt("D:\\pzy1.txt", "D:\\pzy2.txt");

2.3 执行结果

2.3.1 控制台输出

mbn/Mykb4f7xt2Zhz0xS6w==
12345678
加密开始!
解密结束!

2.3.2 如图所示

在这里插入图片描述

文件生成 beta版
在这里插入图片描述
文件内容解释

  • 第一个是原文件
  • 第二个是加密byte后文件 不重要
  • 第三个是解密后文件
    在这里插入图片描述

2.4 跳过2.2 工具包代码

2.2详细解释 2.4 完整版
后续版本中同时对上面介绍的部分代码进行调整如下:

  • 加密模式EBC-> CBC 进行调整
  1. EBC: 一种简单的加密模式,每个明文块独立加密,不需要前后的文块信息, 并且不需要IV
  2. CBC: 更安全的加密模式,它使用前一个密文块的一部分(通常是最后8个字节)作为下一个明文块的加密密钥, 需要IV
  • 增加了初始化向量(IV)
  • 使用方式没有变化, 与上面解释完全相同

2.4.1 CryptoUtils密码学工具包

/**
 * AES 加密/解密工具类 beta版
 * <p>
 * 版本更新
 * 1. 新增json串加密解密
 * 2. 新增文件加密与解密
 * 3. 增加测试用例
 *
 * @author pzy
 * @version v2.0.1
 * @description OK
 */
public class CryptoUtils {

    //这个密钥需要是16位 //对应128bit 原因: 128的密钥长度是目前能对安全性和性能的一种比较理想的折中选择
    public static final String KEY_DES = "pzyPzyPzyPzyPzyP";

    // 偏移量 16位
    private static final String iv = "0102030405060708";

    //    private static final String algorithmStr = "AES/EBC/PKCS5Padding";
    private static final String algorithmStr = "AES/CBC/PKCS5Padding";


    private static final byte[] ivByte = iv.getBytes(StandardCharsets.UTF_8);

    /**
     * AES加密文本
     *
     * @param content    明文
     * @param encryptKey 秘钥,必须为16个字符组成
     * @return 密文
     */
    public static String aesEncryptForFront(String content, String encryptKey) {
        if (StringUtils.isEmpty(content) || StringUtils.isEmpty(encryptKey)) {
            return null;
        }
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"),
                    new IvParameterSpec(ivByte));

            byte[] encryptStr = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptStr);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * AES解密文本
     *
     * @param encryptStr 密文
     * @param decryptKey 秘钥,必须为16个字符组成
     * @return 明文
     */
    public static String aesDecryptForFront(String encryptStr, String decryptKey) {
        if (StringUtils.isEmpty(encryptStr) || StringUtils.isEmpty(decryptKey)) {
            return null;
        }
        try {
            byte[] encryptByte = Base64.getDecoder().decode(encryptStr);
            Cipher cipher = Cipher.getInstance(algorithmStr);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"),
                    new IvParameterSpec(ivByte));
            byte[] decryptBytes = cipher.doFinal(encryptByte);
            return new String(decryptBytes);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * AES加密文件
     *
     * @param bytes      字节
     * @param encryptKey 秘钥key
     * @return 字节byte
     */
    public static byte[] aesEncryptForFront(byte[] bytes, String encryptKey) {
        if (StringUtils.isEmpty(bytes) || StringUtils.isEmpty(encryptKey)) {
            return null;
        }
        try {
            Cipher cipher = Cipher.getInstance(algorithmStr);
            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"),
                    new IvParameterSpec(ivByte));

            return cipher.doFinal(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * AES解密文件
     *
     * @param bytes      字节
     * @param decryptKey 解密key
     * @return 解密字节
     */
    public static byte[] aesDecryptForFront(byte[] bytes, String decryptKey) {
        if (StringUtils.isEmpty(bytes) || StringUtils.isEmpty(decryptKey)) {
            return null;
        }
        try {
            Cipher cipher = Cipher.getInstance(algorithmStr);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES"),
                    new IvParameterSpec(ivByte));
            return cipher.doFinal(bytes);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 文件AES加密并输出
     *
     * @param fileSourcePath 文件原始路径
     * @param outEncryptPath 加密数据文件路径
     * @throws IOException io异常
     */
    public static void fileAcsEncrypt(String fileSourcePath, String outEncryptPath) throws IOException {

        System.out.println("加密开始!");

        File file = new File(fileSourcePath);
        // 以 byte 的形式读取,不改变文件数据的编码格式
        byte[] bytes = Files.readAllBytes(file.toPath());

        byte[] outFile = CryptoUtils.aesEncryptForFront(bytes, CryptoUtils.KEY_DES);
        OutputStream out = new BufferedOutputStream(new FileOutputStream(outEncryptPath));
        assert outFile != null;
        out.write(outFile);
        out.flush();
    }

    /**
     * 文件AES解密并输出
     *
     * @param fileEncryptPath 加密后文件路径
     * @param outDecryptPath  解密后文件路径
     * @throws IOException io异常
     */
    public static void fileAcsDecrypt(String fileEncryptPath, String outDecryptPath) throws IOException {
        File file = new File(fileEncryptPath);
        // 以 byte 的形式读取,不改变文件数据的编码格式
        byte[] outFile = CryptoUtils.aesDecryptForFront(Files.readAllBytes(file.toPath()), CryptoUtils.KEY_DES);
        OutputStream out = new BufferedOutputStream(new FileOutputStream(outDecryptPath));
        assert outFile != null;
        out.write(outFile);
        out.flush();

        System.out.println("解密结束!");
    }

}

2.4.2 测试代码完整版

    /**
     * 提供测试方式
     *
     * @param args ...
     * @throws Exception 异常
     */
    public static void main(String[] args) throws Exception {
        String old = "pzy: 今天天气挺好";
        String target = "c882579N5IQtAGKJcgYWGhvIbNTMZb6dGugSBl3IGzU="; // 加密后的字符串
//文本------------------>
        //加密
        System.out.println(CryptoUtils.aesEncryptForFront(old, CryptoUtils.KEY_DES));

        //解密
        System.out.println(CryptoUtils.aesDecryptForFront(target, CryptoUtils.KEY_DES));

//文件 beta版------------------------>
        //加密/解密(生成加密后的文件后缀可以自定义)
        CryptoUtils.fileAcsEncrypt("D:\\pzy.txt", "D:\\pzy1.txt");

        CryptoUtils.fileAcsDecrypt("D:\\pzy1.txt", "D:\\pzy2.txt");
    }

2.4.3 秘钥和IV随机 都是16位字符串即可 不可暴露

3. 结合业务使用

java 业务中需要数据加密的地方

  1. 数据安全:在处理敏感数据如: 个人信息财务信息、或公司核心机密,这些数据在存储和传输过程中都必须保证是安全的。可以使用Java提供的加密和解密库来加密这些数据,以防止数据泄露。
  2. 网络安全:在构建网络应用时,如Web服务、或者在两个系统之间进行数据传输时,你需要保护数据的完整性。这时,你可以使用加密技术来确保数据在传输过程中不会被篡改。
  3. 保护密码和令牌:敏感密码或令牌如: 数据库密码、API的密钥等。防止被恶意用户获取, 就得使用加密技术来存储这些密码,并在需要的时候解密。
  4. 云存储和数据保护:在云存储服务中,如Amazon S3, Google Cloud Storage等,你可以使用加密技术来保护你的数据。这样即使数据被泄露,也需要有正确的密钥才能解密。
  5. 数据库保护:数据库中存储敏感数据时需要使用加密技术来保护数据。数据库被泄露,关键信息也需要正确的密钥才能解密。
  6. 物联网物联网设备中,通常会使用加密技术来保护数据的传输和存储。例如,智能家居设备传输和接收指令时, 设备的数据都会通过加密的连接发送,以确保数据的安全。

3.1 (模拟简易数据传输-收集功能)

后端返回值加密 然后获取到这个值解密
[异步处理, 解耦]

  1. 服务(1-n)取出数据进行处理(关键核心数据)
  2. 加密后交给mq(其他)去处理[省略,mq具体操作请看mq系列文章]
  3. (数据处理类)服务 接收到mq(其他)消息进行解密处理

3.1.1 创建统一返回值(叫啥都行)

ResultResponse 这个类名随意, AaaResponse都行
注意: 加密前需要将Object对象转换成json 然后再加密解密
JSON.toJSONString(data)
累加一下 加几个方法

	/**
	 * 获取数据分析data(主)解密
	 * <p>
	 * 1. 修复返回 空字符串 null 的情况(主)
	 * 2. 解密数据分析字符串
	 */
	public String getAnalyseData() throws JsonProcessingException {
		Object data = get("analyseData");
		//解密专用
		return data == null ? null : CryptoUtils.aesDecryptForFront(String.valueOf(data), CryptoUtils.KEY_DES);
//		return data == null ? null : new ObjectMapper().writeValueAsString(CryptoUtils.aesDecryptForFront(String.valueOf(data), CryptoUtils.KEY_DES));
	}

	/**
	 * 获取数据分析数据
	 *
	 * @param typeReference
	 * @param <T>
	 * @return
	 */
	public <T> T getAnalyseData(TypeReference<T> typeReference) {
		Object data = get("analyseData");

		//解密操作
		String cryptoDecodeStr = CryptoUtils.aesDecryptForFront(String.valueOf(data), CryptoUtils.KEY_DES);

//		String jsonStr = JSON.toJSONString(cryptoDecodeStr);

		return JSON.parseObject(cryptoDecodeStr, typeReference);
	}

	/**
	 * 数据分析专用(主) 加密
	 * <p>
	 * 数据完全不暴露给前端
	 * @param data
	 * @return
	 */
	public ResultResponse setAnalyseData(Object data) {

		if (data != null) {
			//加密(密钥)
			data = CryptoUtils.aesEncryptForFront(JSON.toJSONString(data), CryptoUtils.KEY_DES);
		}
		put("analyseData", data);
		return this;
	}
	//---------------------------------------->

3.1.2 controller层写一个demo

    @Analyse(analyseBaseType = 1,value = "测试")
    @ApiOperation(value = "测试1")
    @PostMapping("/addTest01")
    public ResultResponse addTest01(@RequestBody User user) {

        log.info("===> 测试1 <===");

        user.setPassword("123456");

        return ResultResponse.ok("添加成功!!!").setData(user.getAge())
                .setAnalyseData(user);
    }

3.1.3 数据采集注解(标记是否采集和加密)

如图所示,业务逻辑(加注解是采集和加密的) 细节不过多展示了

在这里插入图片描述

3.1.4 业务具体实现逻辑数据处理(略)

注解具体实现不展示了(具体业务了), 本篇主要是AES加密解密

3.1.5 测试结果(如图所示)

在这里插入图片描述

4. 前端使用AES加密(大致流程)

Java: 使用AES/CBC/PKCS5Padding加密的数据,
前端JS: 可以使用crypto库中的AES/CBC解密函数进行解密。

  • AES: 128位(bit)
  • 使用Node.js的crypto模块

如果是web端

  • 使用Web Cryptography API或其他第三方库(如crypto-js)

具体细节请查看前端AES的文档, 这里只是一个demo

4.1 前端js实现方式

const crypto = require('crypto');  
  
// 后端加密的密钥,与前端使用的密钥相同  
const key = 'your_secret_key';  
  
// 后端加密的初始化向量(IV),与前端使用的IV相同  
const iv = 'your_initialization_vector';  
  
// 后端加密后的密文  
const ciphertext = 'encrypted_data';  
  
// 创建AES解密对象,指定CBC模式、PKCS5Padding填充方式和密钥及IV  
const decipher = crypto.createDecipheriv('aes-128-cbc', key, Buffer.from(iv, 'hex'));  
decipher.setAutoPadding(true); // 自动填充PKCS5Padding  
  
// 解密数据  
const plaintext = decipher.update(ciphertext, 'hex', 'utf8');  
plaintext += decipher.final('utf8');  
  
console.log('解密后的明文:', plaintext);

5. 文章的总结与预告

5.1 本文总结

> 本文介绍了AES的定义,用法,及使用方式<

详细说明:

  • 对比了RSA(非对称性)的区别, 各自的应用场景
  • 代码实现工具类, 业务中具体使用方式
  • 最新增加了大文件加密解密功能
  • 并且在后续更新中继续修改 完善部分说明和代码

5.2 下文预告

—=> RSA(非对称性加密)的原理及代码使用方式 <=—

包括:

  • 公钥私钥的创建原理
  • 明文+公钥 = 秘钥+明文
  • 运算公式 * , %
  • java代码实现
  • 测试代码及结果
  • 分析,优化,总结

作者pingzhuyan 感谢观看

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

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

相关文章

leetcode刷题日记:168. Excel Sheet Column Title(Excel表列名称)

我不知道你看到这一道题目有什么感觉&#xff0c;我先告诉你我有什么感觉&#xff0c;在此之前我再给你写一组有相同模式的数字。 你先告诉我你有什么感觉&#xff0c;有没有感觉&#xff0c;没有感觉的话&#xff0c;那我们就来更深的了解一下&#xff1a; 我们分析最后一…

Echarts -- 实现动态加载series

一、需求说明 1.1具体说明 根据每天的订单,查询出券码(title字段)的核销情况,如下单成功,已核销,取消订单,订单失败, title字段又分大概七八种,最后数据进行整合完毕之后,前端使用Echarts进行堆叠柱状图显示每天数据。 1.2 需求拆解 根据时间范围查询出每天的订单数据后,根据…

PostgreSQL 数据类型

文章目录 PostgreSQL数据类型说明PostgreSQL数据类型使用单引号和双引号数据类型转换布尔类型数值类型整型浮点型序列数值的常见操作 字符串类型日期类型枚举类型IP类型JSON&JSONB类型复合类型数组类型 PostgreSQL数据类型说明 PGSQL支持的类型特别丰富&#xff0c;大多数…

用户运营:如何搭建用户分析体系

在运营的工作范畴中&#xff0c;用户运营是很重要的一个环节&#xff0c;甚至有公司会设置专门的“用户运营”岗位。 用户运营的价值体现在多个方面&#xff0c;不仅可以帮助引流、吸引更多用户使用产品&#xff0c;在用户正式使用产品之后的运营则更为重要。通过日常用户运营&…

深度学习到智能小车(1)深度学习框架

0.前提 最近新开了一门叫机器学习的课程&#xff0c;老师一直在跟我们讲一些有关这方面的知识&#xff0c;告诉我们一定要学好数学&#xff0c;因为数学是算法的基础。我手上的donkeycar刚好也涉及到Keras深度神经网络&#xff0c;所以出于好奇我去图书馆借回了一本叫《Keras深…

Fedora 项目近日发布了 Fedora Linux 39

导读几经推迟之后&#xff0c;Fedora 项目近日发布了 Fedora Linux 39&#xff0c;这是红帽公司赞助的面向大众的 GNU/Linux 发行版的最新稳定版本&#xff0c;采用了最新的技术和开源应用程序。 Fedora Linux 39 由 Linux 内核 6.5 支持&#xff0c;并提供了一些最新的桌面环境…

顺序表在线OJ题(详解+图解)

1&#xff1a;原地移除数组中所有的元素val&#xff08;时间复杂度为O(N)空间复杂度为O(1)&#xff09; 题目的大概意思是&#xff1a;用户自行输入一个数组&#xff0c;还要输入一个val的整形值&#xff0c;然后从数组中移除等于val的元素 我们根据题目的要求&#xff0c;时间…

处理机器学习数据集中字符串列(pandas.get_dummies)

如图&#xff0c;在数据集中week列的数据不是数值型&#xff0c;会导致我们在训练过程中难以处理。 而pandas库中有一个非常好用的函数&#xff0c;独热编码pandas.get_dummies(df) 使用此函数之后&#xff0c;会在原数据中新建各列代表Fri-Sun&#xff0c;值为0或1&#xff…

vscode调试pytorch的DistributedDataParallel代码

这里写自定义目录标题 一、查找launch.py二、修改launch.json三、特别提醒3.1 错误的写法3.2 正确的写法 一、查找launch.py 使用代码。 find / -name launch.py | grep distributed得到的结果如下 这里我们得到了两个结果&#xff0c;看目标文件的路径名&#xff0c;第二个…

系统韧性研究(5)| 常用的系统韧性技术

如果不利事件或条件导致系统无法正常运行&#xff0c;则它们可能会对有价值的资产造成各种形式的损害。正如我在本系列的前几篇文章中概述的那样&#xff0c;系统韧性很重要&#xff0c;因为没有人想要一个无法克服“不可避免的逆境”的脆弱系统。 在本系列的第一篇文章中&…

怎么为pdf加水印?

怎么为pdf加水印&#xff1f;最近很多小伙伴都有这样的疑问。你可以在浏览器上搜索一下&#xff0c;关于这方面的很多还是有很多人不是很清楚的。虽然我们自己在很多PDF文件上都看到了水印&#xff0c;那么真的到了自己这边需要进行操作的时候&#xff0c;确实还是有些这样或是…

PHPStorm PHP-CS-Fixer

我用的是brew安装&#xff1a; brew install php-cs-fixer phpstorm配置&#xff1a; setting搜索fixer 指定安装php-cs-fixer的目录&#xff1a; https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/installation.rst 图文详解PHPStorm实现自动执行代码格式化-…

如何利用TSINGSEE青犀智能分析网关算法从人员、设备、行为三大角度进行监狱智能化升级改造

监狱作为关押犯人的重要场所&#xff0c;十分需要全天候全方位无死角的监控&#xff0c;但由于狱警人力有限&#xff0c;无法达到目前的监控需求。并且在监狱中&#xff0c;犯人众多也极易发生口角冲突&#xff0c;如若没有及时处理&#xff0c;就会发生难以挽回的意外。如何更…

AnimateDiff搭配Stable diffution制作AI视频

话不多说&#xff0c;先看视频 1. AnimateDiff的技术原理 AnimateDiff可以搭配扩散模型算法&#xff08;Stable Diffusion&#xff09;来生成高质量的动态视频&#xff0c;其中动态模型&#xff08;Motion Models&#xff09;用来实时跟踪人物的动作以及画面的改变。我们使用 …

【大话Presto 】- 核心概念

文章目录 前言Operator Model And Iterator Model系统组成Connector数据模型查询执行模型StatementStageTaskSplitDriverOperatorExchangePipeLine 总结 前言 Presto&#xff08;PrestoDB&#xff09;是一个FaceBook开源的分布式MPP SQL引擎&#xff0c;旨在处理大规模数据的查…

【硬核】把一个MOS管制作成开关电路

你要是想读懂这篇文章&#xff0c;请先去了解MOS管的基础知识&#xff0c;本文是在基础之上做出的一部分扩展&#xff0c;可能有一点点深&#xff0c;请各位同学注意。 本文带你了解MOS管的开通/关断原理&#xff0c;使用PMOS做上管、NMOS做下管都是比较方便&#xff0c;使用PM…

「分享学习」SpringCloudAlibaba高并发仿斗鱼直播平台实战完结

[分享学习]SpringCloudAlibaba高并发仿斗鱼直播平台实战完结 第一段&#xff1a;简介 Spring Cloud Alibaba是基于Spring Cloud和阿里巴巴开源技术的微效劳框架&#xff0c;普遍应用于大范围高并发的互联网应用系统。本文将引见如何运用Spring Cloud Alibaba构建一个高并发的仿…

设计模式之桥接模式--连接抽象与实现(你想知道的问题都有)

目录 概述结构型设计模式桥接模式的定义桥接模式的角色和关系 版本迭代紧耦合版增加品牌两个品牌两款软件松耦合的设计版本迭代业务分析总结 问题升华抽象与实现抽象包含的一些方法或属性依赖于实现部分的接口关联关系与桥接模式桥接模式适合情况谁是实现&#xff0c;谁是抽象组…

希亦ACE和小吉内衣洗衣机选哪个?两款洗衣机对比

内衣洗衣机可以称得上是实现幸福的小家电&#xff0c;它不仅懒人的福音还是我们打工人的福音&#xff0c;在每天下班之后可以有时间休息了&#xff0c;洗完澡还有要手洗内衣裤&#xff0c;真的很痛苦&#xff0c;拥有了内衣洗衣机简直是一件非常幸福的事情&#xff0c;但现在市…

源码安装prometheus(普罗米修斯监控)

IP角色系统规格192.168.0.38Prometheus 服务端CentOS 74c8g192.168.0.25node_exporter 客户端CentOS 74c8g 普罗米修斯下载网址: Download | Prometheus 1.下载prometheus [rootprometheus opt]# wget https://github.com/prometheus/prometheus/releases/download/v2.47.2…