【Spring Boot】Spring Boot 中常见的加密方案

Spring Boot 中常见的加密方案

  • MD5
    • [MD5 基本概念](#MD5 基本概念)
    • [MD5 的核心思想](#MD5 的核心思想)
    • [MD5 使用方法](#MD5 使用方法)
  • [SHA 系列](#SHA 系列)
    • [SHA 系列概述](#SHA 系列概述)
    • [SHA 的工作原理(通用流程)](#SHA 的工作原理(通用流程))
    • [SHA 使用方法](#SHA 使用方法)
  • BCrypt
    • [BCrypt 概念](#BCrypt 概念)
    • [BCrypt 的工作原理(内部流程)](#BCrypt 的工作原理(内部流程))
    • [BCrypt 使用方法](#BCrypt 使用方法)
  • Argon2
    • [Argon2 概念](#Argon2 概念)
    • [Argon2 设计思想](#Argon2 设计思想)
    • [Argon2 使用方法](#Argon2 使用方法)
  • [Spring Boot 项目使用](#Spring Boot 项目使用)
  • 总结

MD5

MD5 基本概念

MD5 全称是 Message Digest Algorithm 5 (信息摘要算法第 5 版),由密码学家 Ron Rivest 在 1991 年提出。

它的作用是:

把任意长度的数据(字符串、文件等)"压缩"成一个固定长度的 128 位(16 字节)摘要值

这个摘要值通常用 32 位十六进制字符串表示。

示例

复制代码
输入: "hello"
输出: 5d41402abc4b2a76b9719d911017c592

即使只改变一个字符:

复制代码
输入: "Hello"
输出: 8b1a9953c4611296a827abf8c47804d7

可以看到:输入微小变化,输出完全不同

MD5 的核心思想

MD5 并不是"加密",而是一种哈希算法(Hash Function)

即:

  • 不可逆(你无法从 MD5 值反推出原文)
  • 定长输出(无论输入多长,输出始终是 128 位)
  • 雪崩效应(输入改动一位,输出几乎全变)
  • 高速计算(适合快速校验)

原理简述

MD5 的内部逻辑大致如下:

步骤 描述
填充(Padding) 将输入填充到长度 ≡ 448 mod 512,确保数据能被分为 512 位的块。
附加长度 在数据末尾追加原始长度(64 位)。
初始化缓冲区 定义 4 个 32 位寄存器:A、B、C、D(初始常量)。
迭代运算 每个 512 位块通过一系列非线性函数和位运算(如 AND、OR、XOR、左移)混合处理。
输出结果 最终拼接 A、B、C、D 的值 → 128 位摘要。

简单来说:MD5 把输入"分块 → 混合 → 扰乱 → 压缩"成固定长度摘要。

MD5 的特点

特性 说明
输出长度固定 128 位(16 字节),常以 32 个十六进制字符表示。
不可逆 无法解密回原始内容。
雪崩效应 输入变化 1 bit,输出变化约 50%。
快速计算 算法效率高。
碰撞风险 不同的输入可能生成相同的输出(已被证明)。

MD5 的常见用途

应用场景 说明
文件完整性校验 下载软件时验证文件未被篡改。
数据校验码 快速比较数据内容是否一致。
用户密码加密(旧系统) 曾经常用于存储密码(但已不安全)。
数字签名 在安全性较低场景中生成签名摘要。

MD5 使用方法

使用 Spring 自带工具类

Spring 框架提供了简单的 MD5 工具:

java 复制代码
import org.springframework.util.DigestUtils;

public class MD5Example {
    public static void main(String[] args) {
        String input = "hello";
        String md5 = DigestUtils.md5DigestAsHex(input.getBytes());
        System.out.println(md5);
    }
}

输出:

复制代码
5d41402abc4b2a76b9719d911017c592

使用 Java 原生 API

java 复制代码
import java.security.MessageDigest;

public class MD5Example {
    public static void main(String[] args) throws Exception {
        String input = "hello";
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] hashBytes = md.digest(input.getBytes("UTF-8"));
        StringBuilder hex = new StringBuilder();
        for (byte b : hashBytes) {
            hex.append(String.format("%02x", b));
        }
        System.out.println(hex.toString());
    }
}

给密码加盐(增强安全)

加盐(Salt)可以防止彩虹表攻击。

java 复制代码
import java.security.MessageDigest;

public class SaltedMD5 {
    public static void main(String[] args) throws Exception {
        String password = "123456";
        String salt = "MyApp#2025";
        String input = password + salt;

        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] bytes = md.digest(input.getBytes("UTF-8"));

        StringBuilder hex = new StringBuilder();
        for (byte b : bytes) hex.append(String.format("%02x", b));
        System.out.println(hex.toString());
    }
}

MD5 的安全性问题

MD5 已不安全,不推荐用于密码或安全签名。

原因如下:

问题 描述
碰撞攻击 不同输入可得相同 MD5 值。2004 年被正式破解。
彩虹表攻击 攻击者用预计算表快速反查 MD5 值。
暴力破解 由于算法速度太快,适合 GPU 暴力破解。

SHA 系列

SHA 系列概述

SHA(Secure Hash Algorithm) 是由美国 NSA(国家安全局) 设计、NIST(国家标准与技术研究院) 发布的加密哈希家族。

它的作用与 MD5 类似:将任意长度的数据映射为固定长度的"摘要"(digest),用于校验完整性、签名、认证等。

SHA 家族主要分为以下几代:

系列 代表算法 输出长度(bit) 状态 说明
SHA-0 SHA-0 160 已废弃 原版算法(1993),发现安全漏洞,被迅速弃用
SHA-1 SHA-1 160 已被破解 曾广泛用于 SSL、Git、证书签名等,现在不安全
SHA-2 SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256 224~512 主流标准 当前主流使用的安全哈希算法族(JWT、TLS、密码哈希)
SHA-3 SHA3-224、SHA3-256、SHA3-384、SHA3-512 224~512 新一代标准 与 SHA-2 完全不同,基于 Keccak 算法,更抗攻击

SHA 的工作原理(通用流程)

SHA 的计算过程与 MD5 类似,但逻辑更复杂、更安全:

阶段 说明
预处理 填充数据到 512 位的整数倍,附加长度信息
分块 每个 512 位分块单独处理
初始化变量 设定若干 32 位或 64 位寄存器(A、B、C、D...)
循环压缩 通过逻辑函数、位移、模加等运算混合数据
拼接结果 输出固定长度摘要(如 256 位 = 32 字节)

SHA 的核心是"不可逆的数学混合"。

输入稍有改动,输出完全不同(雪崩效应)。

SHA 使用方法

SHA-1(Secure Hash Algorithm 1)

  • 输出长度:160 位(20 字节)
  • 常见输出格式:40 位十六进制字符串
  • 算法速度:快
  • 安全性:已被破解
java 复制代码
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] result = md.digest("hello".getBytes());

曾用于:

  • SSL/TLS 证书签名(已弃用)
  • Git 文件版本校验(正在过渡到 SHA-256)

已被 Google 和荷兰CWI研究所于 2017 年展示 实际碰撞攻击(SHAttered)

SHA-2 系列(主流标准)

SHA-2 实际是多个算法族的统称:

算法 输出长度 常见用途
SHA-224 224 位 嵌入式、低功耗设备
SHA-256 256 位 最常用(JWT、文件校验)
SHA-384 384 位 高强度安全
SHA-512 512 位 适合 64 位系统

SHA-256 是当前最推荐的通用版本。
SHA-512 性能更高(在 64 位机器上),更安全。

Java 实现示例(SHA-256)

java 复制代码
import java.security.MessageDigest;

public class SHA256Example {
    public static void main(String[] args) throws Exception {
        String input = "hello world";
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(input.getBytes("UTF-8"));

        StringBuilder hex = new StringBuilder();
        for (byte b : hash) {
            hex.append(String.format("%02x", b));
        }
        System.out.println(hex.toString());
    }
}

输出(固定 64 位十六进制串):

复制代码
b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

Spring Boot 工具类实现(SHA-512)

java 复制代码
import org.apache.commons.codec.digest.DigestUtils;

String sha512 = DigestUtils.sha512Hex("password123");
System.out.println(sha512);

文件校验场景

java 复制代码
import java.io.*;
import java.security.MessageDigest;

public static String getFileSHA256(File file) throws Exception {
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    try (InputStream fis = new FileInputStream(file)) {
        byte[] buffer = new byte[8192];
        int n;
        while ((n = fis.read(buffer)) > 0) {
            digest.update(buffer, 0, n);
        }
    }
    byte[] hash = digest.digest();
    StringBuilder sb = new StringBuilder();
    for (byte b : hash) sb.append(String.format("%02x", b));
    return sb.toString();
}

SHA-3 系列(Keccak)

  • 发布年份:2015(NIST 新标准)
  • 算法基础:基于海绵结构(Sponge Construction)
  • 代表算法:SHA3-224、SHA3-256、SHA3-384、SHA3-512
  • 区别:与 SHA-2 完全不同的内部结构,更抗攻击。
java 复制代码
MessageDigest sha3 = MessageDigest.getInstance("SHA3-256");
byte[] hash = sha3.digest("Hello SHA3".getBytes());

特点

  • 不与 SHA-2 兼容;
  • 可抗长度扩展攻击;
  • 设计为长期替代 SHA-2。

补充说明:

概念 说明
SHA-2 并不是单一算法 它是一整套算法族(不同输出长度的变种)。例如 SHA-256SHA-512 都属于 SHA-2 家族。
SHA-3 并不是 SHA-2 的改进版 它是全新设计(Keccak 结构),没有继承关系。
输出长度 对应输出摘要长度(bit 位数),例如:SHA-256 输出 256 位(32 字节)。
安全状态 SHA-1 已可被构造碰撞,SHA-2 目前仍安全,SHA-3 为未来标准。

正确理解层级关系

mathematica 复制代码
SHA(安全哈希算法家族)
 ├── SHA-0(不安全,废弃)
 ├── SHA-1(不安全,已被破解)
 ├── SHA-2(主流安全标准)
 │     ├── SHA-224
 │     ├── SHA-256
 │     ├── SHA-384
 │     └── SHA-512
 └── SHA-3(新标准,基于 Keccak)
       ├── SHA3-224
       ├── SHA3-256
       ├── SHA3-384
       └── SHA3-512

BCrypt

BCrypt 概念

BCrypt 是什么?

BCrypt 是一种基于 Blowfish 加密算法 的密码哈希函数,由 Niels Provos 和 David Mazières 在 1999 年设计,最初出现在 OpenBSD 系统中。

它属于 单向加密算法(Hashing Algorithm),常用于存储用户密码。

BCrypt 的核心特点

特点 说明
单向不可逆 无法从哈希值反推明文密码。
自动加盐(Salt) 每次加密自动生成随机盐,避免彩虹表攻击。
可调"复杂度因子"(Cost Factor) 可以调整计算强度,防止暴力破解。
输出固定长度(60字符) 无论输入多长,输出总是 60 个字符。
跨语言支持 在 Java、Python、PHP、Go 等语言中都有官方或成熟实现。

BCrypt 的工作原理(内部流程)

BCrypt 的计算过程大致如下:

复制代码
1. 生成随机盐(Salt)
   ↓
2. 将盐与明文密码结合
   ↓
3. 使用 Blowfish 加密算法多轮加密(2^cost 次)
   ↓
4. 输出最终的哈希字符串(包含盐和成本信息)

BCrypt 哈希的格式如下:

mathematica 复制代码
$2a$10$EIXCh1l6Z7CzWIKQ0s1t8u8mvjU7qg3sK9fRf6RPSZ6bEJ3iRzZ6G
│ │ │ │                      └───────────────────────────── 密文部分(Base64编码)
│ │ │ └── 22字符的盐(Base64编码)
│ │ └──── 10 表示成本(2^10 = 1024 次加密)
│ └─────── 算法版本(2a/2b)
└───────── 起始符号 $

成本因子(Cost Factor)

BCrypt 的强度主要取决于 cost 参数(也叫 work factor)。

默认一般是 10,表示进行 2^10 = 1024 轮加密。

Cost 大约耗时(现代 CPU)
8 < 100ms
10 ~300ms
12 ~1s
14 ~4s

建议值:

Web 应用中推荐使用 10~12 ,兼顾安全与性能。

越高越安全,但登录时耗时也更长。

BCrypt 的安全机制详解

  1. 自动加盐

    每次加密都会自动生成 随机盐(16字节)

    因此即使两个人使用相同密码,哈希值也完全不同。

    复制代码
    $2a$10$abc123...   ← 盐不一样
    $2a$10$xyz987...   ← 哈希也不一样
  2. 自带盐与成本参数

    BCrypt 生成的字符串内部就包含盐和 cost,因此不需要单独存储盐。

BCrypt 使用方法

Spring Security 内置了 BCryptPasswordEncoder,使用极其方便。

示例一:生成密码哈希

java 复制代码
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

public class BCryptExample {
    public static void main(String[] args) {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String rawPassword = "mySecret123";
        String hashedPassword = encoder.encode(rawPassword);

        System.out.println("原始密码: " + rawPassword);
        System.out.println("加密后: " + hashedPassword);
    }
}

输出示例:

复制代码
原始密码: mySecret123
加密后: $2a$10$e0NR9ZnPS2D2X4xDJH5lBO8xL61jSwB1KkzIUVwFovYCKNH4I5C.O

示例二:验证密码是否匹配

java 复制代码
String inputPassword = "mySecret123";
boolean matches = encoder.matches(inputPassword, hashedPassword);

System.out.println(matches ? "密码正确" : "密码错误");

Argon2

Argon2 概念

什么是 Argon2?

Argon2 是一种用于**密码哈希(Password Hashing)**的算法,诞生于 2015 年,由 Alex Biryukov、Daniel Dinu、Dmitry Khovratovich 等密码学家设计。

它在 2015 年赢得了 Password Hashing Competition (PHC),成为国际标准密码哈希算法。

目标

抵抗暴力破解、GPU 攻击、ASIC 硬件攻击 ------ 并提供可调的计算复杂度与内存占用。

Argon2 的三个变种

版本 主要特征 推荐用途
Argon2d 使用数据相关内存访问(速度快) 抵御 GPU 攻击(不适合并行攻击)
Argon2i 使用数据独立访问(更安全) 防止侧信道攻击(如时间推测)
Argon2id 混合模式(先 i 后 d) 最推荐,兼顾两者优点

在实际项目中:

Argon2id 是目前密码存储的官方推荐版本(RFC 9106 标准)

Argon2 设计思想

传统算法(如 BCrypt)仅考虑"计算耗时",

Argon2 同时考虑 CPU + 内存消耗,让暴力破解更难:

因素 含义 攻击难度影响
Time Cost 运算迭代次数 增加计算量
Memory Cost 占用内存(KB/MB) 降低 GPU 并行破解效率
Parallelism 并行线程数 提升合法加密速度

工作原理(简化流程)

  1. 生成随机盐(16字节或更长)
  2. 结合明文密码 + 盐 + 参数(内存/时间/并行度)
  3. 进行多轮基于内存的哈希计算
  4. 输出哈希字符串(包含所有参数)

输出结果示例:

mathematica 复制代码
$argon2id$v=19$m=65536,t=3,p=4$QWERTYasdfgh1234$NqM6cN6Lk5mZtP4xGVg4xg
│───────││───── 参数说明 ─────││─── Base64盐 ───││────── 哈希结果 ──────│
│  算法  ││版本│内存=64MB,迭代3次,4线程│ 

Argon2 参数详解

参数 含义 推荐值(Web 应用)
t (Time Cost) 迭代次数 2~4
m (Memory Cost) 使用内存大小(KB) 65536 (≈64MB)
p (Parallelism) 并行线程数 1~4
salt length 盐长度 ≥16字节
hash length 输出哈希长度 32字节或更长

安全建议:

  • 盐必须随机且唯一
  • 增加 m(内存)比增加 t(次数)更能防 GPU 攻击
  • 建议使用 Argon2id 模式

为什么 Argon2 比 BCrypt 更安全?

特性 BCrypt Argon2
加盐机制 自动加盐 自动加盐
可调复杂度 cost time + memory + parallel
GPU 防御 强(高内存占用)
并行支持
性能 中等
安全标准 无官方标准 RFC 9106 标准

Argon2 使用方法

Spring Security 从 5.0 版本开始原生支持 Argon2

使用方式与 BCrypt 类似。

添加依赖

在 Spring Boot 项目中引入 Spring Security:

xml 复制代码
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-crypto</artifactId>
</dependency>

创建 Argon2PasswordEncoder

java 复制代码
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

public class Argon2Example {
    public static void main(String[] args) {
        // 参数:saltLength, hashLength, parallelism, memoryCost, iterations
        PasswordEncoder encoder = new Argon2PasswordEncoder(16, 32, 1, 65536, 3);

        String rawPassword = "mySecret123";
        String encoded = encoder.encode(rawPassword);

        System.out.println("原始密码: " + rawPassword);
        System.out.println("加密后: " + encoded);

        boolean match = encoder.matches("mySecret123", encoded);
        System.out.println("匹配结果: " + match);
    }
}

输出示例:

复制代码
原始密码: mySecret123
加密后: $argon2id$v=19$m=65536,t=3,p=1$xA4xv2x4lQv4a7g3xA$F6xK3v2n8dQOpxV1u+3Bfw
匹配结果: true

Spring Boot 项目使用

MD5

  • 性质 :哈希算法(不可逆),Spring 不提供原生封装,只是工具类(DigestUtils

  • 使用方式:直接调用工具方法即可

    java 复制代码
    import org.springframework.util.DigestUtils;
    
    String md5 = DigestUtils.md5DigestAsHex("password".getBytes());
  • 配置类不需要

  • 注意事项

    • MD5 已不安全,不建议用作密码存储
    • 可以用于文件校验、数据完整性等场景

SHA 系列(SHA-1、SHA-256、SHA-512、SHA3 等)

  • 性质:哈希算法(不可逆)

  • 使用方式

    • Java 原生:

      java 复制代码
      MessageDigest md = MessageDigest.getInstance("SHA-256");
      byte[] hash = md.digest("password".getBytes());
    • 或 Apache Commons Codec / Spring DigestUtils

  • 配置类不需要,直接在业务代码中调用即可

  • 注意事项

    • 如果用于密码存储,必须加盐 + 多轮迭代

BCrypt

  • 性质:单向加密(哈希 + 自动加盐 + 可调复杂度)

  • Spring Boot 支持 :原生提供 BCryptPasswordEncoder

  • 使用方式

    • 可以直接在业务中 new 一个对象用:

      复制代码
      BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
      String hash = encoder.encode("password");
      boolean match = encoder.matches("password", hash);
    • 推荐写配置类注入 PasswordEncoder,方便 Spring Security 集成:

      java 复制代码
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
      import org.springframework.security.crypto.password.PasswordEncoder;
      
      @Configuration
      public class PasswordConfig {
      
          /**
           * BCryptPasswordEncoder 默认 cost = 10
           * cost 越大,计算越慢,安全性越高
           */
          @Bean
          public PasswordEncoder bCryptPasswordEncoder() {
              return new BCryptPasswordEncoder(10); // 可以根据性能调整
          }
      }

      使用示例

      java 复制代码
      @Autowired
      private PasswordEncoder passwordEncoder;
      
      public void register(String rawPassword) {
          String encoded = passwordEncoder.encode(rawPassword);
          // 保存 encoded 到数据库
      }
      
      public boolean login(String rawPassword, String storedHash) {
          return passwordEncoder.matches(rawPassword, storedHash);
      }
  • 配置类推荐,但不是必须

    • 如果项目不使用 Spring Security,也可以直接 new BCryptPasswordEncoder()

Argon2(Argon2id)

  • 性质:现代密码哈希(内存硬化 + 自动加盐 + 可调复杂度)

  • Spring Boot 支持 :Spring Security 5+ 原生提供 Argon2PasswordEncoder

  • 使用方式

    • 直接 new 使用:

      java 复制代码
      Argon2PasswordEncoder encoder = new Argon2PasswordEncoder();
      String hash = encoder.encode("password");
      boolean match = encoder.matches("password", hash);
    • 推荐写配置类注入 PasswordEncoder

      java 复制代码
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
      import org.springframework.security.crypto.password.PasswordEncoder;
      
      @Configuration
      public class PasswordConfig {
      
          /**
           * Argon2PasswordEncoder 参数说明:
           * saltLength: 盐长度(字节)
           * hashLength: 输出哈希长度(字节)
           * parallelism: 并行线程数
           * memory: 内存消耗 (KB)
           * iterations: 哈希迭代次数
           */
          @Bean
          public PasswordEncoder argon2PasswordEncoder() {
              return new Argon2PasswordEncoder(
                      16,       // salt length
                      32,       // hash length
                      1,        // parallelism
                      65536,    // memory cost (64 MB)
                      3         // iterations
              );
          }
      }

      使用示例

      java 复制代码
      @Autowired
      private PasswordEncoder passwordEncoder;
      
      public void register(String rawPassword) {
          String encoded = passwordEncoder.encode(rawPassword);
          // 保存 encoded 到数据库
      }
      
      public boolean login(String rawPassword, String storedHash) {
          return passwordEncoder.matches(rawPassword, storedHash);
      }
  • 配置类推荐

    • 方便全局统一使用,尤其是结合 Spring Security

总结

Spring Boot 项目 中,选择合适的哈希/加密算法主要取决于用途安全性需求

算法 类型 输出长度 安全性 特点与适用场景 Spring Boot 使用方式
MD5 哈希算法 128 位(16 字节) 已不安全 快速计算、雪崩效应强;适合文件校验、数据完整性检测 DigestUtils.md5DigestAsHex() 调用即可,无需配置类
SHA 系列 哈希算法 160~512 位 SHA-1 已不安全,SHA-2/3 安全 可靠的消息摘要算法;文件校验、签名、JWT、加密辅助 Java MessageDigest 或 Apache DigestUtils调用,无需配置类;用于密码需加盐+多轮
BCrypt 密码哈希 60 字符 安全 自动加盐、可调成本(cost)、不可逆;适合用户密码存储 推荐创建配置类 PasswordEncoderBean;可直接 new BCryptPasswordEncoder()
Argon2 密码哈希 可变(Base64) 高安全 自动加盐、可调时间/内存/并行度;防 GPU/ASIC 攻击,现代推荐算法 推荐创建配置类 PasswordEncoderBean,使用 Argon2PasswordEncoder,参数可自定义

建议

  1. 简单数据完整性 (如文件校验、数据摘要)
    • 使用 MD5 或 SHA-2/3 即可
    • 不需要配置类,直接工具类调用
  2. 用户密码存储
    • 强烈建议 使用 BCryptArgon2id
    • MD5、SHA-1、SHA-256 不安全,即使加盐也难抵抗 GPU 彩虹表攻击
    • 在 Spring Boot 项目中,建议通过 配置类统一注入 PasswordEncoder Bean,方便全局使用和与 Spring Security 集成
  3. 性能与安全平衡
    • BCrypt:成本因子(cost)调整计算复杂度
    • Argon2:可调 timeCostmemoryCostparallelism,更安全且支持并行

总结一句话

文件校验用 MD5/SHA,密码存储用 BCrypt/Argon2(推荐 Argon2id),密码算法最好通过配置类统一注入 PasswordEncoder,保证安全性与可维护性。

相关推荐
Lilian6 小时前
Trae通过ssh远程访问服务器linux系统不兼容问题
后端·trae
十碗饭吃不饱6 小时前
sql报错:java.sql.SQLSyntaxErrorException: Unknown column ‘as0‘ in ‘where clause‘
java·数据库·sql
12344526 小时前
Spring Boot 启动流程全解析:从 SpringApplication.run() 到 Bean 初始化与自动配置
后端
饼干吖6 小时前
记一次滑动数组解题
java·算法
ss2737 小时前
手写MyBatis第96弹:异常断点精准捕获MyBatis深层BUG
java·开发语言·bug·mybatis
Java中文社群7 小时前
我的网站被攻击了!
后端
程序定小飞7 小时前
基于springboot的在线商城系统设计与开发
java·数据库·vue.js·spring boot·后端
shengjk17 小时前
一文搞懂 java 中 POJO 和 bean 区别
后端
LL_break7 小时前
Mysql数据库
java·数据库·mysql