深度实战:Rust交叉编译适配OpenHarmony PC——unicode_width完整适配案例

📋 目录

  • [1. 📖 背景介绍](#1. 📖 背景介绍)
  • [2. 🛠️ 环境准备](#2. 🛠️ 环境准备)
  • [3. 📁 项目结构分析](#3. 📁 项目结构分析)
  • [4. 🔍 问题诊断与解决](#4. 🔍 问题诊断与解决)
  • [5. ✏️ 详细修改步骤](#5. ✏️ 详细修改步骤)
  • [6. ✅ 构建验证](#6. ✅ 构建验证)
  • [7. 💻 使用示例](#7. 💻 使用示例)
  • [8. 📚 总结与最佳实践](#8. 📚 总结与最佳实践)

1. 📖 背景介绍

1.1 🌐 unicode_width工具简介

unicode-width 是一个用Rust编写的Unicode字符宽度计算库,用于根据Unicode标准附录#11(UAX #11)和其他Unicode标准规则确定charstr类型的显示宽度。本项目基于unicode-width库创建了一个命令行工具,用于演示和测试Unicode字符宽度计算功能。

核心功能

  • 📏 字符宽度计算: 计算单个Unicode字符的显示宽度
  • 📐 字符串宽度计算: 计算Unicode字符串的显示宽度
  • 🌏 CJK支持: 支持中日韩(CJK)字符的宽度计算
  • 🎯 标准兼容: 遵循Unicode Standard Annex #11规则
  • 高性能: 纯Rust实现,无外部依赖,性能优异
  • 🔒 no_std支持: 支持no_std环境

应用场景

  • 📊 终端文本格式化工具(如lstree等)
  • 🎨 终端UI布局和表格输出
  • 📝 文本对齐和排版工具
  • 🌐 国际化(i18n)应用开发
  • 📋 日志格式化工具
  • 🔍 文本处理工具

1.2 🎯 适配目标

将unicode_width命令行工具适配到鸿蒙PC(OpenHarmony PC)平台,实现:

  • 🦀 Rust项目交叉编译支持
  • 🏗️ 支持aarch64-linux-ohos架构
  • 🔧 使用OHOS SDK工具链进行编译
  • 📦 生成HNP格式的安装包
  • 📦 生成tar.gz格式的发布包
  • 💻 提供可执行的unicode_width命令

1.3 🔧 技术栈

  • 语言: 🦀 Rust 2021 Edition
  • 构建系统: Cargo
  • 目标平台: 🎯 aarch64-linux-ohos
  • 打包格式: 📦 HNP (HarmonyOS Native Package)
  • 编译工具链: OHOS SDK Native LLVM (clang/ld.lld)
  • 依赖: 无外部依赖(纯Rust实现)

1.4 💡 工具优势

相比手动计算字符宽度,unicode_width提供了:

  • 标准兼容: 遵循Unicode Standard Annex #11规则
  • 类型安全: Rust类型系统保证计算的正确性
  • 零成本抽象: 编译时优化,运行时性能优异
  • 易于使用 : 简洁的API,UnicodeWidthCharUnicodeWidthStr traits
  • CJK支持: 支持中日韩字符的特殊宽度计算
  • 无依赖: 纯Rust实现,无外部依赖

2. 🛠️ 环境准备

2.1 💻 系统要求

  • 开发环境: 💻 macOS / 🐧 Linux / 🪟 Windows (WSL)
  • Python: 🐍 Python 3.x
  • Rust: 🦀 Rust 1.66.0+(unicode-width最低要求)
  • Cargo: 📦 Rust包管理器(随Rust安装)
  • 鸿蒙SDK: 📦 OHOS SDK (包含native工具链和hnpcli打包工具)

2.2 📥 SDK安装

  1. 📥 下载SDK
bash 复制代码
# 下载鸿蒙SDK
cd ~
wget https://cidownload.openharmony.cn/version/Master_Version/ohos-sdk-full_ohos/20250819_020817/version-Master_Version-ohos-sdk-full_ohos-20250819_020817-ohos-sdk-full_ohos.tar.gz

# 解压SDK
tar -zvxf version-Master_Version-ohos-sdk-full_ohos-20250819_020817-ohos-sdk-full_ohos.tar.gz
  1. 📁 SDK目录结构

    ohos-sdk/
    ├── native/
    │ ├── llvm/bin/ # 🔧 编译器工具链
    │ ├── sysroot/ # 📚 系统根目录(头文件和库)
    │ └── build-tools/ # 🛠️ 构建工具
    └── toolchains/
    └── hnpcli # 📦 HNP打包工具

2.3 🦀 Rust环境配置

安装Rust

bash 复制代码
# 使用rustup安装Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

安装musl target

bash 复制代码
# 安装aarch64-unknown-linux-musl target(用于OpenHarmony交叉编译)
rustup target add aarch64-unknown-linux-musl

验证安装

bash 复制代码
rustc --version  # 应显示 rustc 1.66.0 或更高版本
cargo --version  # 应显示 cargo 1.66.0 或更高版本
rustup target list --installed | grep aarch64-unknown-linux-musl  # 应显示已安装

3. 📁 项目结构分析

3.1 📂 目录结构

复制代码
unicode-width4oh/
├── Cargo.toml              # Rust项目配置
├── Cargo.lock              # 依赖版本锁定文件
├── build_ohos.sh           # OpenHarmony构建脚本
├── hnp.json                # HNP包配置
├── README.md               # 项目说明
├── LICENSE-APACHE          # Apache-2.0许可证
├── LICENSE-MIT             # MIT许可证
├── COPYRIGHT               # 版权信息
├── src/                    # 源代码目录
│   ├── lib.rs             # 库代码(unicode_width库)
│   ├── main.rs            # 命令行工具主程序 ⭐
│   └── tables.rs          # Unicode宽度表
├── tests/                  # 测试代码
│   ├── tests.rs           # 单元测试
│   └── emoji-test.txt     # Emoji测试数据
├── benches/                # 性能基准测试
│   └── benches.rs         # 基准测试代码
└── .cargo/                 # Cargo配置目录
    └── config.toml         # 交叉编译配置

3.2 🔧 Cargo.toml关键配置

toml 复制代码
[package]
name = "unicode-width"
version = "0.2.2"
edition = "2021"
rust-version = "1.66"

[lib]
name = "unicode_width"

[[bin]]
name = "unicode_width"
path = "src/main.rs"  # ⭐ 命令行工具入口

[features]
cjk = []
default = ["cjk"]

关键配置说明

  • ⚠️ Edition 2021: 使用Rust 2021版本
  • Binary配置 : 添加了[[bin]]配置,定义命令行工具入口
  • 📦 无外部依赖: 纯Rust实现,无外部依赖
  • 🎯 CJK特性: 默认启用CJK字符支持

3.3 📝 命令行工具设计

main.rs核心功能

rust 复制代码
// 支持的命令
- char <char>        - 计算单个字符的宽度
- char-cjk <char>    - 计算单个字符的CJK宽度
- str <string>       - 计算字符串的宽度
- str-cjk <string>   - 计算字符串的CJK宽度
- demo               - 显示演示示例
- help               - 显示帮助信息

设计特点

  • ✅ 模块化设计,每个功能独立函数
  • ✅ 友好的命令行界面
  • ✅ 支持标准宽度和CJK宽度计算
  • ✅ 丰富的演示功能

4. 🔍 问题诊断与解决

4.1 🔍 问题1:缺少命令行工具入口

问题描述

unicode-width是一个库项目,没有命令行工具入口点。

解决方案

创建src/main.rs文件,实现命令行工具功能。

4.2 🔍 问题2:Cargo.toml缺少binary配置

问题描述

Cargo.toml中没有定义binary目标,无法构建可执行文件。

解决方案

Cargo.toml中添加[[bin]]配置:

toml 复制代码
[[bin]]
name = "unicode_width"
path = "src/main.rs"

4.3 🔍 问题3:缺少交叉编译配置

问题描述

需要配置Cargo使用OpenHarmony SDK的工具链进行交叉编译。

解决方案

创建.cargo/config.toml文件,配置交叉编译参数。


5. ✏️ 详细修改步骤

5.1 📝 步骤1:创建命令行工具入口

创建src/main.rs文件:

rust 复制代码
//! unicode_width command-line tool
//! 
//! A command-line tool for calculating Unicode character and string widths.

use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};

fn print_usage() {
    println!("unicode_width - Calculate Unicode character and string widths");
    println!();
    println!("Usage:");
    println!("  unicode_width [command] [arguments...]");
    println!();
    println!("Commands:");
    println!("  char <char>           - Calculate width of a single character");
    println!("  char-cjk <char>       - Calculate CJK width of a single character");
    println!("  str <string>          - Calculate width of a string");
    println!("  str-cjk <string>      - Calculate CJK width of a string");
    println!("  demo                  - Display demonstration examples");
    println!("  help                  - Show this help message");
    println!();
    println!("Examples:");
    println!("  unicode_width char A              # Calculate width of 'A'");
    println!("  unicode_width char 中              # Calculate width of '中'");
    println!("  unicode_width str \"Hello\"         # Calculate width of string");
    println!("  unicode_width str \"Hello\"     # Calculate width of full-width string");
    println!("  unicode_width demo                # Show demonstration");
}

fn demo() {
    println!("Unicode Width Calculation Demonstration");
    println!("======================================");
    println!();
    
    // Single character examples
    println!("Single Character Width:");
    println!("------------------------");
    let chars = vec![
        ('A', "Latin letter"),
        ('中', "Chinese character"),
        ('あ', "Hiragana"),
        ('😀', "Emoji"),
        (' ', "Space"),
        ('\t', "Tab"),
    ];
    
    for (ch, desc) in chars {
        let width = ch.width().unwrap_or(0);
        let width_cjk = ch.width_cjk().unwrap_or(0);
        println!("  '{}' ({}) - width: {}, width_cjk: {}", ch, desc, width, width_cjk);
    }
    
    println!();
    println!("String Width:");
    println!("-------------");
    let strings = vec![
        ("Hello", "Latin string"),
        ("Hello", "Full-width string"),
        ("Hello, 世界!", "Mixed string"),
        ("こんにちは", "Japanese string"),
        ("안녕하세요", "Korean string"),
        ("你好世界", "Chinese string"),
        ("😀😃😄", "Emoji string"),
    ];
    
    for (s, desc) in strings {
        let width = s.width();
        let width_cjk = s.width_cjk();
        println!("  \"{}\" ({})", s, desc);
        println!("    width: {}, width_cjk: {}", width, width_cjk);
    }
    
    println!();
    println!("Special Cases:");
    println!("--------------");
    println!("  \"\\r\\n\" width: {}", "\r\n".width());
    println!("  \"\\n\" width: {}", "\n".width());
    println!("  \"\\t\" width: {}", "\t".width());
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    
    if args.len() < 2 {
        print_usage();
        return;
    }
    
    let command = args[1].as_str();
    
    match command {
        "char" => {
            if args.len() < 3 {
                eprintln!("Error: 'char' command requires a character argument");
                println!();
                print_usage();
                std::process::exit(1);
            }
            let ch_str = &args[2];
            if let Some(ch) = ch_str.chars().next() {
                let width = ch.width().unwrap_or(0);
                println!("Character: '{}'", ch);
                println!("Width: {}", width);
                if ch_str.chars().count() > 1 {
                    println!("Warning: Only the first character was processed");
                }
            } else {
                eprintln!("Error: Invalid character");
                std::process::exit(1);
            }
        }
        "char-cjk" => {
            if args.len() < 3 {
                eprintln!("Error: 'char-cjk' command requires a character argument");
                println!();
                print_usage();
                std::process::exit(1);
            }
            let ch_str = &args[2];
            if let Some(ch) = ch_str.chars().next() {
                let width = ch.width_cjk().unwrap_or(0);
                println!("Character: '{}'", ch);
                println!("Width (CJK): {}", width);
                if ch_str.chars().count() > 1 {
                    println!("Warning: Only the first character was processed");
                }
            } else {
                eprintln!("Error: Invalid character");
                std::process::exit(1);
            }
        }
        "str" => {
            if args.len() < 3 {
                eprintln!("Error: 'str' command requires a string argument");
                println!();
                print_usage();
                std::process::exit(1);
            }
            let s = &args[2];
            let width = s.width();
            println!("String: \"{}\"", s);
            println!("Width: {}", width);
        }
        "str-cjk" => {
            if args.len() < 3 {
                eprintln!("Error: 'str-cjk' command requires a string argument");
                println!();
                print_usage();
                std::process::exit(1);
            }
            let s = &args[2];
            let width = s.width_cjk();
            println!("String: \"{}\"", s);
            println!("Width (CJK): {}", width);
        }
        "demo" => {
            demo();
        }
        "help" | "-h" | "--help" => {
            print_usage();
        }
        _ => {
            eprintln!("Unknown command: {}", command);
            println!();
            print_usage();
            std::process::exit(1);
        }
    }
}

关键实现

  • ✅ 使用UnicodeWidthChar trait计算字符宽度
  • ✅ 使用UnicodeWidthStr trait计算字符串宽度
  • ✅ 支持标准宽度和CJK宽度计算
  • ✅ 完善的错误处理和帮助信息

5.2 📝 步骤2:更新Cargo.toml

Cargo.toml中添加binary配置:

toml 复制代码
[lib]
name = "unicode_width"

[[bin]]
name = "unicode_width"
path = "src/main.rs"

配置说明

  • [lib]: 定义库目标
  • [[bin]]: 定义二进制目标,指定入口文件为src/main.rs

5.3 📝 步骤3:创建交叉编译配置

创建.cargo/config.toml文件:

toml 复制代码
[target.aarch64-unknown-linux-musl]
linker = "clang"
ar = "llvm-ar"
rustflags = [
    "-C", "link-arg=--target=aarch64-linux-ohos",
    "-C", "link-arg=--sysroot=${SYSROOT}",
    "-C", "link-arg=-fuse-ld=lld",
]

配置说明

  • linker: 使用clang作为链接器
  • ar: 使用llvm-ar作为归档工具
  • rustflags: 传递链接参数,指定目标平台和sysroot

5.4 📝 步骤4:更新build_ohos.sh

build_ohos.sh脚本已经配置好,关键部分:

bash 复制代码
#!/bin/bash
# unicode_width OpenHarmony build script

set -e
export UNICODE_WIDTH_INSTALL_HNP_PATH=${HNP_PUBLIC_PATH}/unicode_width.org/unicode_width_0.2.3

# 创建安装目录
mkdir -p ${UNICODE_WIDTH_INSTALL_HNP_PATH}/bin

# 安装musl target(如果未安装)
if ! rustup target list --installed | grep -q "aarch64-unknown-linux-musl"; then
    echo "Installing aarch64-unknown-linux-musl target..."
    rustup target add aarch64-unknown-linux-musl
fi

# 配置交叉编译环境变量
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER="${CC}"
export RUSTFLAGS="-Clink-arg=--target=${TARGET_PLATFORM} -Clink-arg=--sysroot=${SYSROOT} -Clink-arg=-fuse-ld=lld"

# 构建unicode_width命令行工具
cargo build --release --target aarch64-unknown-linux-musl
BIN=target/aarch64-unknown-linux-musl/release/unicode_width
cp "$BIN" ${UNICODE_WIDTH_INSTALL_HNP_PATH}/bin/

# 复制HNP配置文件
cp hnp.json ${UNICODE_WIDTH_INSTALL_HNP_PATH}/

# 打包HNP和tar.gz
${HNP_TOOL} pack -i ${UNICODE_WIDTH_INSTALL_HNP_PATH} -o ${ARCHIVE_PATH}/
tar -zvcf ${ARCHIVE_PATH}/ohos_unicode_width_0.2.3.tar.gz unicode_width_0.2.3/

关键步骤

  1. ✅ 设置安装路径
  2. ✅ 安装musl target
  3. ✅ 配置交叉编译环境变量
  4. ✅ 构建二进制文件
  5. ✅ 复制文件到HNP目录
  6. ✅ 打包HNP和tar.gz

6. ✅ 构建验证

6.1 🚀 执行构建

bash 复制代码
cd /Users/baixm/HarmonyOSPC/build
./build.sh --sdk /Users/baixm/ohos-sdk --module unicode-width4oh

6.2 ✅ 构建输出

6.3 🔍 验证要点

  • ✅ 编译成功,无错误
  • ✅ 二进制文件格式正确(ELF 64-bit LSB executable, ARM aarch64)
  • ✅ 静态链接(statically linked)
  • ✅ HNP包生成成功
  • ✅ tar.gz包生成成功

7. 💻 使用示例

7.1 🚀 基本使用

📏 计算单个字符宽度
bash 复制代码
# 在鸿蒙PC终端执行
unicode_width char A

# 输出示例:
# Character: 'A'
# Width: 1
📏 计算中文字符宽度
bash 复制代码
# 在鸿蒙PC终端执行
unicode_width char 中

# 输出示例:
# Character: '中'
# Width: 2
📏 计算CJK字符宽度
bash 复制代码
# 在鸿蒙PC终端执行
unicode_width char-cjk 中

# 输出示例:
# Character: '中'
# Width (CJK): 2

7.2 📐 字符串宽度计算

📐 计算拉丁字符串宽度
bash 复制代码
# 在鸿蒙PC终端执行
unicode_width str "Hello"

# 输出示例:
# String: "Hello"
# Width: 5
📐 计算全角字符串宽度
bash 复制代码
# 在鸿蒙PC终端执行
unicode_width str "Hello"

# 输出示例:
# String: "Hello"
# Width: 9
📐 计算混合字符串宽度
bash 复制代码
# 在鸿蒙PC终端执行
unicode_width str "Hello, 世界!"

# 输出示例:
# String: "Hello, 世界!"
# Width: 11
📐 计算CJK字符串宽度
bash 复制代码
# 在鸿蒙PC终端执行
unicode_width str-cjk "你好世界"

# 输出示例:
# String: "你好世界"
# Width (CJK): 8

7.3 🎨 演示功能

bash 复制代码
# 在鸿蒙PC终端执行
unicode_width demo

# 输出示例:
# Unicode Width Calculation Demonstration
# ======================================
# 
# Single Character Width:
# ------------------------
#   'A' (Latin letter) - width: 1, width_cjk: 1
#   '中' (Chinese character) - width: 2, width_cjk: 2
#   'あ' (Hiragana) - width: 2, width_cjk: 2
#   '😀' (Emoji) - width: 2, width_cjk: 2
#   ' ' (Space) - width: 1, width_cjk: 1
#   '	' (Tab) - width: 0, width_cjk: 0
# 
# String Width:
# -------------
#   "Hello" (Latin string)
#     width: 5, width_cjk: 5
#   "Hello" (Full-width string)
#     width: 10, width_cjk: 10
#   "Hello, 世界!" (Mixed string)
#     width: 11, width_cjk: 11
#   "こんにちは" (Japanese string)
#     width: 10, width_cjk: 10
#   "안녕하세요" (Korean string)
#     width: 10, width_cjk: 10
#   "你好世界" (Chinese string)
#     width: 8, width_cjk: 8
#   "😀😃😄" (Emoji string)
#     width: 6, width_cjk: 6
# 
# Special Cases:
# --------------
#   "\r\n" width: 1
#   "\n" width: 1
#   "\t" width: 0

7.4 ❓ 显示帮助信息

bash 复制代码
# 在鸿蒙PC终端执行
unicode_width help

# 或
unicode_width -h
unicode_width --help

# 输出示例:
# unicode_width - Calculate Unicode character and string widths
# 
# Usage:
#   unicode_width [command] [arguments...]
# 
# Commands:
#   char <char>           - Calculate width of a single character
#   char-cjk <char>       - Calculate CJK width of a single character
#   str <string>          - Calculate width of a string
#   str-cjk <string>      - Calculate CJK width of a string
#   demo                  - Display demonstration examples
#   help                  - Show this help message

7.5 🔧 实际应用场景

📊 在脚本中使用
bash 复制代码
#!/bin/bash
# 计算字符串宽度并格式化输出

WIDTH=$(unicode_width str "Hello, 世界!")
echo "String width: $WIDTH"

# 根据宽度调整输出格式
if [ $WIDTH -gt 20 ]; then
    echo "String is too long!"
else
    echo "String length is acceptable."
fi
📋 在Rust程序中使用
rust 复制代码
use unicode_width::UnicodeWidthStr;

fn main() {
    let text = "Hello, 世界!";
    let width = text.width();
    println!("Text: {}", text);
    println!("Width: {}", width);
    
    // 根据宽度调整输出格式
    if width > 20 {
        println!("Text is too long!");
    } else {
        println!("Text length is acceptable.");
    }
}

8. 📚 总结与最佳实践

8.1 ✅ 适配总结

本次适配成功实现了unicode_width命令行工具在OpenHarmony PC平台上的部署:

  1. 命令行工具创建 : 创建了src/main.rs,实现了完整的命令行工具功能
  2. 交叉编译配置 : 配置了.cargo/config.toml,使用musl target进行交叉编译
  3. 构建脚本优化 : build_ohos.sh脚本自动处理musl target安装和交叉编译
  4. HNP打包: 成功生成HNP格式的安装包和tar.gz发布包
  5. 功能验证: 命令行工具功能完整,支持多种使用方式

8.2 🎯 关键技术点

  1. Rust 2021 Edition: unicode-width使用Rust 2021版本,API更现代
  2. 无外部依赖: 纯Rust实现,无外部依赖,交叉编译简单
  3. musl target : 使用aarch64-unknown-linux-musl target进行静态链接
  4. 交叉编译 : 通过.cargo/config.tomlRUSTFLAGS配置交叉编译
  5. HNP打包 : 使用hnpcli工具打包成HNP格式

8.3 💡 最佳实践

  1. 命令行工具设计:

    • ✅ 提供清晰的帮助信息
    • ✅ 支持多种计算模式(标准宽度和CJK宽度)
    • ✅ 完善的错误处理
    • ✅ 友好的用户界面
  2. 交叉编译配置:

    • ✅ 使用标准的musl target
    • ✅ 配置正确的链接器和sysroot
    • ✅ 自动安装musl target
    • ✅ 验证二进制文件格式
  3. 构建脚本:

    • ✅ 设置set -e确保错误时退出
    • ✅ 创建必要的目录结构
    • ✅ 验证安装结果
    • ✅ 提供清晰的日志输出

8.4 🚀 未来改进方向

  1. 功能增强:

    • 📊 支持更多输出格式(如JSON、YAML)
    • 🔄 支持批量处理多个字符串
    • 📈 支持统计和报告功能
  2. 性能优化:

    • ⚡ 优化字符串处理性能
    • 🎯 优化CJK字符计算性能
  3. 文档完善:

    • 📖 添加更多使用示例
    • 🔍 添加故障排除指南
    • 📚 添加API文档

📚 附录

A. 相关资源

B. 常见问题

Q1: 为什么unicode-width返回Option类型?

A: 某些字符(如控制字符)可能没有明确的宽度,返回Option类型可以表示这种情况。对于大多数字符,width()会返回Some(width)

Q2: 标准宽度和CJK宽度有什么区别?

A: 标准宽度遵循Unicode Standard Annex #11规则,而CJK宽度针对中日韩字符进行了特殊处理,在某些情况下可能返回不同的宽度值。

Q3: 如何判断字符宽度是否可用?

A: 检查width()的返回值,如果是Some(width)则表示成功计算,如果是None则表示无法计算。

Q4: 为什么emoji字符宽度是2?

A: 根据Unicode标准,大多数emoji字符在终端中占用2个字符宽度,这是为了正确显示emoji。


🎉 结语

unicode_width工具为终端应用开发提供了便捷的Unicode字符宽度计算能力,是开发国际化终端应用的重要基础工具。通过本次适配,unicode_width成功运行在OpenHarmony PC平台上,为鸿蒙生态的终端应用开发提供了支持。

希望本文档能够帮助开发者:

  • 🌐 理解Unicode字符宽度计算的原理和使用方法
  • 🔧 掌握Rust项目适配OpenHarmony的方法
  • 📦 了解HNP包的构建和打包流程
  • 💻 学习命令行工具的开发实践

💬 如有问题或建议,欢迎反馈!

相关推荐
漫漫求2 小时前
Java内存模型【JMM】、JVM内存模型
java·开发语言·jvm
田姐姐tmner2 小时前
Python 全面语法指南
开发语言·python
white-persist2 小时前
【攻防世界】reverse | simple-check-100 详细题解 WP
c语言·开发语言·汇编·数据结构·c++·python·算法
wuguan_2 小时前
C#中的静态成员、常量和只读变量
开发语言·c#
Java水解2 小时前
MySQL必备基础
后端·mysql
Java水解2 小时前
Spring AOP原理深度解析:代理模式、JDK动态代理与CGLIB
后端·spring
张人玉2 小时前
C# 与西门子 PLC 通信:地址相关核心知识点
开发语言·microsoft·c#·plc
Gomiko2 小时前
JavaScript DOM 原生部分(五):事件绑定
开发语言·前端·javascript
无限大62 小时前
为什么显示器分辨率越高越清晰?——从像素到 4K/8K 的视觉革命
后端