添加 Maven、MobaXterm、Scoop、SpringBoot 打包体积优化相关文档
This commit is contained in:
parent
771306f57c
commit
fbfcfcaae2
37
src/programming/java/工具箱/Maven.md
Normal file
37
src/programming/java/工具箱/Maven.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
icon: bi:arrows-expand
|
||||||
|
date: 2025-05-08
|
||||||
|
category:
|
||||||
|
- 实用工具
|
||||||
|
- JAVA
|
||||||
|
tag:
|
||||||
|
- maven
|
||||||
|
title: maven常用配置
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
maven常用配置
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
# 阿里云镜像
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<mirror>
|
||||||
|
<id>aliyunmaven</id>
|
||||||
|
<mirrorOf>central</mirrorOf>
|
||||||
|
<name>阿里云公共仓库</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
|
</mirror>
|
||||||
|
```
|
||||||
|
|
||||||
|
# 配置代理
|
||||||
|
```xml
|
||||||
|
<proxy>
|
||||||
|
<id>http-proxy</id>
|
||||||
|
<active>true</active>
|
||||||
|
<protocol>http</protocol>
|
||||||
|
<host>10.6.212.9</host>
|
||||||
|
<port>7897</port>
|
||||||
|
<nonProxyHosts>localhost|127.0.0.1|*.local</nonProxyHosts>
|
||||||
|
</proxy>
|
||||||
|
```
|
18
src/programming/java/工具箱/MobaXterm.md
Normal file
18
src/programming/java/工具箱/MobaXterm.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
icon: bi:arrows-expand
|
||||||
|
date: 2025-05-08
|
||||||
|
category:
|
||||||
|
- 实用工具
|
||||||
|
tag:
|
||||||
|
- MobaXterm
|
||||||
|
title: MobaXterm
|
||||||
|
---
|
||||||
|
|
||||||
|
MobaXterm工具实用教程
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
1. 去官网安装正版软件,比如23.6版本的:[MobaXterm free Xserver and tabbed SSH client for Windows](https://mobaxterm.mobatek.net/)
|
||||||
|
2. 打开这个网站,输入信息:[MobaXterm Keygen](https://inused.github.io/pages/file/tool/MobaXtermKeygen.html)
|
||||||
|
3. 将自动下载的Custom.mxtpro文件放入到[mobaxterm]的目录下
|
||||||
|
4. [重启软件]即已完成注册
|
||||||
|
|
288
src/programming/java/工具箱/Scoop.md
Normal file
288
src/programming/java/工具箱/Scoop.md
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
---
|
||||||
|
icon: bi:arrows-expand
|
||||||
|
date: 2025-05-09
|
||||||
|
category:
|
||||||
|
- 实用工具
|
||||||
|
tag:
|
||||||
|
- Scoop
|
||||||
|
title: Scoop
|
||||||
|
---
|
||||||
|
|
||||||
|
# Scoop
|
||||||
|
|
||||||
|
欢迎体验 **Scoop** —— Windows 的命令行包管理神器!本文将带你全面了解 Scoop 的功能、安装方法、使用技巧以及常见问题解决方法。如果你厌倦了繁琐的软件安装流程,Scoop 绝对是你的最佳选择!🚀
|
||||||
|
<!-- more -->
|
||||||
|
------
|
||||||
|
|
||||||
|
## 什么是 Scoop?
|
||||||
|
|
||||||
|
[Scoop](https://github.com/ScoopInstaller/Scoop?tab=readme-ov-file#installatio) 是一个专为 Windows 设计的命令行包管理工具,旨在简化软件的安装与管理。无论是开发者还是普通用户,Scoop 都能让你通过几行命令快速安装和管理应用程序,省去繁琐的图形界面操作。
|
||||||
|
|
||||||
|
> **Scoop 核心优势**:轻量、快速、无需管理员权限、环境整洁!
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
## Scoop 的核心功能
|
||||||
|
|
||||||
|
Scoop 的设计理念是简化和自动化,以下是它的主要功能:
|
||||||
|
|
||||||
|
- **消除 UAC 提示**:无需频繁点击“允许”弹窗。
|
||||||
|
- **隐藏 GUI 安装向导**:告别繁琐的下一步、下一步。
|
||||||
|
- **保持 PATH 环境整洁**:避免 PATH 变量被杂乱无章的路径污染。
|
||||||
|
- **无副作用安装/卸载**:安装和删除软件时不会影响系统其他部分。
|
||||||
|
- **自动解析依赖**:自动安装软件所需的依赖项。
|
||||||
|
- **一键配置环境**:通过脚本快速配置开发环境,例如:
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
## 安装 Scoop
|
||||||
|
|
||||||
|
### 1. 安装PowerShell并配置权限
|
||||||
|
|
||||||
|
确保你的系统满足以下要求:
|
||||||
|
|
||||||
|
- **PowerShell**:安装最新版本的 [PowerShell](https://aka.ms/powershell) 或 [Windows PowerShell 5.1](https://aka.ms/wmf5download)。然后执行以下指令:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
|
||||||
|
```
|
||||||
|
|
||||||
|
这是一条用于配置 PowerShell 执行策略的命令。具体含义如下:
|
||||||
|
|
||||||
|
- `Set-ExecutionPolicy`:这是 PowerShell 的一个 cmdlet,用于设置执行策略,控制脚本的运行方式。
|
||||||
|
- `ExecutionPolicy RemoteSigned`:将执行策略设置为 `RemoteSigned` 模式。在这种模式下,允许本地创建的脚本无限制运行,但任何从互联网下载的脚本都必须具有受信任的签名才能执行。
|
||||||
|
- `Scope CurrentUser`:指定此执行策略的更改仅适用于当前用户,而不会影响系统中的其他用户或其他范围(如整个计算机)。
|
||||||
|
|
||||||
|
### 2. 安装
|
||||||
|
|
||||||
|
以**非管理员身份**运行以下命令,Scoop 将默认安装到 `C:\Users\<YOUR USERNAME>\scoop`:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 查看 PowerShell 版本
|
||||||
|
Get-Host | Select-Object Version
|
||||||
|
# 标准安装
|
||||||
|
irm get.scoop.sh | iex
|
||||||
|
# 使用代理安装(若无法访问 GitHub)
|
||||||
|
irm https://get.scoop.sh -Proxy '127.0.0.1:7890' | iex
|
||||||
|
```
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
## 加速下载:Aria2 配置
|
||||||
|
|
||||||
|
Scoop 支持 [aria2](https://github.com/aria2/aria2) 来实现多连接下载,提升下载速度。只需安装 aria2 即可:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop install aria2
|
||||||
|
scoop config aria2-warning-enabled false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Aria2 配置项
|
||||||
|
|
||||||
|
通过 `scoop config` 调整 aria2 设置:
|
||||||
|
|
||||||
|
1. **aria2-enabled**(默认:true):启用/禁用 aria2。
|
||||||
|
2. **aria2-warning-enabled**(默认:true):显示/隐藏 aria2 警告。
|
||||||
|
3. **aria2-retry-wait**(默认:2):重试等待时间(秒)。
|
||||||
|
4. **aria2-split**(默认:5):文件分段数。
|
||||||
|
5. **aria2-max-connection-per-server**(默认:5):单服务器最大连接数。
|
||||||
|
6. **aria2-min-split-size**(默认:5M):最小分段大小。
|
||||||
|
7. **aria2-options**:自定义 aria2 参数。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop config aria2-split 10
|
||||||
|
scoop config aria2-max-connection-per-server 8
|
||||||
|
```
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
## 软件仓库推荐
|
||||||
|
|
||||||
|
Scoop 的软件来源于“桶(bucket)”,分为官方和第三方仓库。
|
||||||
|
|
||||||
|
### 官方仓库
|
||||||
|
|
||||||
|
- **[Main](https://github.com/ScoopInstaller/Main)**:常用非 GUI 应用。
|
||||||
|
- **[Extras](https://github.com/ScoopInstaller/Extras)**:不符合 Main 标准的应用。
|
||||||
|
- **[Games](https://github.com/Calinou/scoop-games)**:开源/免费游戏及工具。
|
||||||
|
- **[Nerd-fonts](https://github.com/matthewjberger/scoop-nerd-fonts)**:Nerd 字体。
|
||||||
|
- **[Nirsoft](https://github.com/ScoopInstaller/Nirsoft)**:Nirsoft 工具集。
|
||||||
|
- **[Sysinternals](https://github.com/niheaven/scoop-sysinternals)**:Sysinternals 套件。
|
||||||
|
- **[Java](https://github.com/ScoopInstaller/Java)**:JDK/JRE 相关。
|
||||||
|
- **[Nonportable](https://github.com/ScoopInstaller/Nonportable)**:不可移植应用。
|
||||||
|
- **[PHP](https://github.com/ScoopInstaller/PHP)**:PHP 安装包。
|
||||||
|
- **[Versions](https://github.com/ScoopInstaller/Versions)**:应用的替代版本。
|
||||||
|
|
||||||
|
### 第三方仓库
|
||||||
|
|
||||||
|
- **[scoopcn](https://github.com/scoopcn/scoopcn)**:国内应用为主。
|
||||||
|
- **[dorado](https://github.com/chawyehsu/dorado)**:优质应用集合。
|
||||||
|
- **[Cluttered-bucket](https://github.com/Paxxs/Cluttered-bucket)**:绿色软件及独立开发者应用。
|
||||||
|
- **[scoopet](https://github.com/ivaquero/scoopet)**:学术研究相关工具。
|
||||||
|
- **[scoop-zapps](https://github.com/kkzzhizhou/scoop-zapps)**:自动化更新仓库。
|
||||||
|
- **[aki-apps](https://github.com/akirco/aki-apps)**:个人维护的 bucket。
|
||||||
|
- **[siku](https://github.com/amorphobia/siku)**:个性化应用集合。
|
||||||
|
- **[scoop-bear](https://github.com/AStupidBear/scoop-bear)**:包含 Navicat 等。
|
||||||
|
- **[echo-scoop](https://github.com/echoiron/echo-scoop)**:包含 IDM 等。
|
||||||
|
- **[abgo_bucket](https://github.com/abgox/abgo_bucket)**:包含 123pan 等。
|
||||||
|
- **[diklios-scoop-bucket](https://github.com/diklios5768/diklios-scoop-bucket)**:包含 CooDesker 等。
|
||||||
|
|
||||||
|
添加第三方仓库示例:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop bucket add scoopcn https://github.com/scoopcn/scoopcn
|
||||||
|
```
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
## 常用命令速查
|
||||||
|
|
||||||
|
### 1. 获取帮助
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop help
|
||||||
|
scoop help install
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 安装应用
|
||||||
|
|
||||||
|
- **当前用户安装**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop install nano
|
||||||
|
```
|
||||||
|
|
||||||
|
- **全局安装(需管理员权限)**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop install nano -g
|
||||||
|
```
|
||||||
|
|
||||||
|
- **高级选项**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop install git -g --no-cache --skip
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 卸载应用
|
||||||
|
|
||||||
|
- **卸载程序**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop uninstall nano
|
||||||
|
```
|
||||||
|
|
||||||
|
- **卸载并移除配置文件**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop uninstall nano -p
|
||||||
|
```
|
||||||
|
|
||||||
|
- **卸载全局程序**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop uninstall nano -g
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 更新操作
|
||||||
|
|
||||||
|
- **更新 Scoop 和 bucket**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop update
|
||||||
|
```
|
||||||
|
|
||||||
|
- **更新指定应用**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop update nano
|
||||||
|
```
|
||||||
|
|
||||||
|
- **更新所有**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop update *
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 其他实用命令
|
||||||
|
|
||||||
|
- **查看已安装应用**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop list
|
||||||
|
```
|
||||||
|
|
||||||
|
- **检查可更新应用**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop status
|
||||||
|
```
|
||||||
|
|
||||||
|
- **打开应用主页**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop home nano
|
||||||
|
```
|
||||||
|
|
||||||
|
- **管理 bucket**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop bucket known
|
||||||
|
scoop bucket add extras
|
||||||
|
scoop bucket list
|
||||||
|
scoop bucket rm extras
|
||||||
|
```
|
||||||
|
|
||||||
|
- **清理旧版本和缓存**:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop cleanup *
|
||||||
|
scoop cache rm *
|
||||||
|
```
|
||||||
|
|
||||||
|
- 配置代理
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 配置代理
|
||||||
|
scoop config proxy '127.0.0.1:7890'
|
||||||
|
# 移除代理
|
||||||
|
scoop config rm proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
## 常见问题及解决
|
||||||
|
|
||||||
|
### 问题:Inno Setup 错误
|
||||||
|
|
||||||
|
错误信息:
|
||||||
|
|
||||||
|
```
|
||||||
|
Signature detected: Inno Setup Setup Data (6.3.0)
|
||||||
|
This is not directly supported, but i'll try to unpack it as version 5602; Version detected: 6300
|
||||||
|
Critical error: The setup files are corrupted. Please obtain a new copy of the program.
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方法**:
|
||||||
|
|
||||||
|
安装 `innounp-unicode` 版本:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scoop uninstall innounp
|
||||||
|
scoop bucket add versions
|
||||||
|
scoop install versions/innounp-unicode
|
||||||
|
```
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
## 进阶学习
|
||||||
|
|
||||||
|
想深入了解 Scoop?查看 [官方文档](https://github.com/ScoopInstaller/Scoop/wiki) 获取更多高级用法和技巧!
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
Scoop 是一个强大而优雅的工具,让 Windows 软件管理变得轻松高效。无论是快速安装开发工具,还是管理日常应用,Scoop 都能让你事半功倍。快来试试吧,打造属于你的高效环境!💻
|
616
src/programming/java/工具箱/SpringBoot打包体积优化.md
Normal file
616
src/programming/java/工具箱/SpringBoot打包体积优化.md
Normal file
@ -0,0 +1,616 @@
|
|||||||
|
---
|
||||||
|
icon: bi:arrows-expand
|
||||||
|
date: 2025-05-13
|
||||||
|
category:
|
||||||
|
- 实用工具
|
||||||
|
- JAVA
|
||||||
|
- SpringBoot
|
||||||
|
- JAR
|
||||||
|
tag:
|
||||||
|
- JAR包瘦身
|
||||||
|
title: SpringBoot打包体积优化.md
|
||||||
|
---
|
||||||
|
|
||||||
|
SpringBoot打包体积优化
|
||||||
|
<!-- more -->
|
||||||
|
|
||||||
|
# Spring Boot JAR 瘦身与加密:构建安全高效的部署方案
|
||||||
|
|
||||||
|
在 Spring Boot 应用程序部署过程中,我们常常面临两个主要挑战:
|
||||||
|
|
||||||
|
1. **JAR 包体积过大**:Spring Boot 应用打包时会将所有依赖一起打包,导致最终 JAR 文件臃肿
|
||||||
|
2. **代码安全性问题**:部署到客户环境或公开场合的 JAR 包可能被反编译,造成核心业务逻辑泄露
|
||||||
|
|
||||||
|
为了解决这些问题,本文将介绍一套完整的解决方案,包括 JAR 包瘦身和 JAR 包加密两部分,以及配套的自定义类加载器,实现高效安全的
|
||||||
|
Spring Boot 应用部署。
|
||||||
|
|
||||||
|
## 整体方案设计
|
||||||
|
|
||||||
|
该方案由两个主要项目组成:
|
||||||
|
|
||||||
|
1. **spring-boot-jar-slim-encrypt**:用于将 Spring Boot 应用 JAR 包瘦身和加密
|
||||||
|
2. **spring-boot-custom-classloader**:用于加载瘦身和加密后的 JAR 包
|
||||||
|
|
||||||
|
### 工作流程
|
||||||
|
|
||||||
|
```
|
||||||
|
┌────────────────────┐
|
||||||
|
│ 原始Spring Boot │
|
||||||
|
│ JAR包 │
|
||||||
|
└──────────┬─────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────┐ ┌────────────────────┐
|
||||||
|
│ spring-boot-jar- │ │ │
|
||||||
|
│ slim-encrypt工具 ├───►│ 提取依赖到libs目录 │
|
||||||
|
└──────────┬─────────┘ └────────────────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────┐
|
||||||
|
│ 瘦身后的JAR包 │
|
||||||
|
└──────────┬─────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────┐
|
||||||
|
│ XJar加密处理 │
|
||||||
|
└──────────┬─────────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌────────────────────┐
|
||||||
|
│ 加密后的JAR包 │
|
||||||
|
│ (.xjar) │
|
||||||
|
└──────────┬─────────┘
|
||||||
|
│
|
||||||
|
│ 部署
|
||||||
|
▼
|
||||||
|
┌─────────────────────────────────────────┐
|
||||||
|
│ 运行时环境 │
|
||||||
|
│ ┌─────────────────┐ ┌───────────────┐ │
|
||||||
|
│ │ 加密JAR (.xjar) │ │ 提取的依赖库 │ │
|
||||||
|
│ └────────┬────────┘ └───────┬───────┘ │
|
||||||
|
│ │ │ │
|
||||||
|
│ │ │ │
|
||||||
|
│ ▼ ▼ │
|
||||||
|
│ ┌─────────────────────────────────┐ │
|
||||||
|
│ │ PlainTextClassLoader │ │
|
||||||
|
│ │ (自定义类加载器) │ │
|
||||||
|
│ └─────────────┬─────────────┬─────┘ │
|
||||||
|
│ │ │ │
|
||||||
|
│ ▼ ▼ │
|
||||||
|
│ ┌─────────────────┐ ┌───────────────┐ │
|
||||||
|
│ │ 解密JAR内容 │ │ 加载外部依赖 │ │
|
||||||
|
│ └─────────────────┘ └───────────────┘ │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
1. 使用 spring-boot-jar-slim-encrypt 工具提取原始 JAR 包中的依赖
|
||||||
|
2. 将依赖库单独存储在 libs 目录
|
||||||
|
3. 对精简后的 JAR 包进行加密
|
||||||
|
4. 使用自定义类加载器加载外部依赖和解密 JAR 包
|
||||||
|
|
||||||
|
## 项目一:spring-boot-custom-classloader
|
||||||
|
|
||||||
|
这是一个自定义类加载器项目,它实现了两种类加载器:
|
||||||
|
|
||||||
|
### 1. JarClassLoader 接口
|
||||||
|
|
||||||
|
```java
|
||||||
|
package com.mangmang;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public interface JarClassLoader {
|
||||||
|
String JAR_EXTENSION = ".jar";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从指定目录加载所有JAR文件
|
||||||
|
*
|
||||||
|
* @param jarDir 包含要加载的JAR文件的目录路径
|
||||||
|
* @throws IllegalArgumentException 如果jarDir为null或不存在
|
||||||
|
*/
|
||||||
|
default void loadJar(String jarDir) {
|
||||||
|
if (jarDir == null || jarDir.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("JAR目录路径不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
File directory = new File(jarDir);
|
||||||
|
if (!directory.exists() || !directory.isDirectory()) {
|
||||||
|
throw new IllegalArgumentException("指定路径不是有效目录: " + jarDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] jarFiles = directory.listFiles(this::isJarFile);
|
||||||
|
if (jarFiles == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File jarFile : jarFiles) {
|
||||||
|
System.out.println("加载 》" + jarFile.getName());
|
||||||
|
scanJarFile(jarFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归扫描文件或目录以查找JAR文件
|
||||||
|
*
|
||||||
|
* @param file 要扫描的文件或目录
|
||||||
|
* @throws IllegalArgumentException 如果file为null
|
||||||
|
*/
|
||||||
|
default void scanJarFile(File file) {
|
||||||
|
if (file == null) {
|
||||||
|
throw new IllegalArgumentException("文件不能为null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file.exists()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isJarFile(file)) {
|
||||||
|
addJARFile(file);
|
||||||
|
} else if (file.isDirectory()) {
|
||||||
|
File[] files = file.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (File f : files) {
|
||||||
|
scanJarFile(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查文件是否为JAR文件
|
||||||
|
*/
|
||||||
|
default boolean isJarFile(File file) {
|
||||||
|
return file.isFile() && file.getName().endsWith(JAR_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将JAR文件添加到类加载器
|
||||||
|
*
|
||||||
|
* @param jar 要添加的JAR文件
|
||||||
|
* @throws IllegalArgumentException 如果jar为null或不是有效的JAR文件
|
||||||
|
*/
|
||||||
|
void addJARFile(File jar);
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
这是一个接口,定义了 JAR 文件加载的核心方法:
|
||||||
|
|
||||||
|
- `loadJar(String jarDir)`: 从指定目录加载所有 JAR 文件
|
||||||
|
- `scanJarFile(File file)`: 递归扫描文件或目录查找 JAR 文件
|
||||||
|
- `isJarFile(File file)`: 检查文件是否为 JAR 文件
|
||||||
|
- `addJARFile(File jar)`: 将 JAR 文件添加到类加载器
|
||||||
|
|
||||||
|
### 2. PlainTextClassLoader 实现
|
||||||
|
|
||||||
|
```java
|
||||||
|
package com.mangmang;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 明文类加载器
|
||||||
|
* <p>
|
||||||
|
* 该类实现了自定义类加载器接口和Spring应用启动事件监听器接口。
|
||||||
|
* 主要功能是在应用启动时,从JVM启动参数中查找指定路径的JAR文件并加载。
|
||||||
|
* 通过反射机制将JAR文件动态添加到当前线程的类加载器中,实现运行时加载额外的类库。
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* 使用方法:
|
||||||
|
* 1. 在JVM启动参数中添加 -Dexternal.jars.path=你的JAR文件目录路径
|
||||||
|
* 2. 系统将自动加载该目录下所有的JAR文件
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* 示例:
|
||||||
|
* java -Dexternal.jars.path.path=/path/to/jars -jar your-application.jar
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class PlainTextClassLoader implements JarClassLoader, ApplicationListener<ApplicationStartingEvent> {
|
||||||
|
|
||||||
|
private final String findPath = "external.jars.path"; // 查找路径的键名
|
||||||
|
private final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // 获取当前线程的类加载器
|
||||||
|
private final List<File> jarFiles = new ArrayList<>(); // 存储已加载的JAR文件列表
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造函数
|
||||||
|
* <p>
|
||||||
|
* 在初始化时执行以下操作:
|
||||||
|
* 1. 设置当前线程的类加载器
|
||||||
|
* 2. 输出启动日志信息
|
||||||
|
* 3. 从JVM启动参数中检索包含"external.jars.path.path"的参数
|
||||||
|
* 4. 提取路径值并调用loadJar方法加载指定目录下的JAR文件
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public PlainTextClassLoader() {
|
||||||
|
// 设置当前线程的类加载器
|
||||||
|
Thread.currentThread().setContextClassLoader(classLoader);
|
||||||
|
|
||||||
|
// 打印启动信息
|
||||||
|
System.out.println("启动自定义明文类加载器");
|
||||||
|
|
||||||
|
// 查找并加载外部JAR文件
|
||||||
|
loadExternalJarsFromSystemProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从系统属性中查找并加载外部JAR文件
|
||||||
|
*/
|
||||||
|
private void loadExternalJarsFromSystemProperties() {
|
||||||
|
List<String> inputArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
|
||||||
|
|
||||||
|
// 查找包含指定路径参数的启动参数
|
||||||
|
inputArguments.stream()
|
||||||
|
.filter(arg -> arg.contains(findPath))
|
||||||
|
.map(this::extractPathFromArgument)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.forEach(this::loadJar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从JVM参数中提取路径值
|
||||||
|
*
|
||||||
|
* @param argument JVM启动参数
|
||||||
|
* @return 提取的路径值,如果提取失败则返回null
|
||||||
|
*/
|
||||||
|
private String extractPathFromArgument(String argument) {
|
||||||
|
String prefix = "-D" + findPath + "=";
|
||||||
|
if (argument.startsWith(prefix)) {
|
||||||
|
String path = argument.replace(prefix, "");
|
||||||
|
if (!path.isEmpty()) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理应用程序启动事件
|
||||||
|
* <p>
|
||||||
|
* 当Spring应用启动时会触发此方法。
|
||||||
|
* 目前该方法为空实现,可以在此添加应用启动时需要执行的代码。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param event Spring应用启动事件对象
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onApplicationEvent(@NonNull ApplicationStartingEvent event) {
|
||||||
|
// 应用程序启动事件的处理方法,目前为空
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将JAR文件添加到类加载器
|
||||||
|
* <p>
|
||||||
|
* 通过反射机制调用URLClassLoader的addURL方法,将指定的JAR文件URL添加到当前类加载器。
|
||||||
|
* 添加成功后,JAR文件中的类可以被当前JVM加载和使用。
|
||||||
|
* 同时将已加载的JAR文件记录到jarFiles列表中。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param jar 要添加到类加载器的JAR文件对象
|
||||||
|
* @throws RuntimeException 如果添加过程中发生任何异常,将抛出RuntimeException
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void addJARFile(File jar) {
|
||||||
|
if (jar == null) {
|
||||||
|
throw new IllegalArgumentException("JAR文件不能为null");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
addUrlToClassLoader(jar);
|
||||||
|
jarFiles.add(jar);
|
||||||
|
System.out.println(jarFiles);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("添加JAR文件到类加载器失败: " + jar.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过反射将JAR文件URL添加到类加载器
|
||||||
|
*
|
||||||
|
* @param jar 要添加的JAR文件
|
||||||
|
* @throws Exception 如果反射操作失败
|
||||||
|
*/
|
||||||
|
private void addUrlToClassLoader(File jar) throws Exception {
|
||||||
|
Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
|
||||||
|
if (!addUrlMethod.isAccessible()) {
|
||||||
|
addUrlMethod.setAccessible(true);
|
||||||
|
}
|
||||||
|
URL jarUrl = jar.toURI().toURL();
|
||||||
|
addUrlMethod.invoke(classLoader, jarUrl);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
这是一个明文类加载器,实现了 `JarClassLoader` 接口和 Spring 的 `ApplicationListener<ApplicationStartingEvent>` 接口,用于在
|
||||||
|
Spring Boot 应用启动时加载外部 JAR 文件:
|
||||||
|
|
||||||
|
主要特点:
|
||||||
|
|
||||||
|
- 在 Spring Boot 应用启动时自动执行
|
||||||
|
- 通过 JVM 参数 `-Dexternal.jars.path=你的JAR文件目录路径` 指定外部 JAR 文件目录
|
||||||
|
- 使用反射机制将 JAR 文件 URL 添加到当前线程的类加载器中
|
||||||
|
|
||||||
|
使用示例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
java -Dexternal.jars.path=/path/to/jars -jar your-application.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
## 项目二:spring-boot-jar-slim-encrypt
|
||||||
|
|
||||||
|
这个工具用于压缩和加密 Spring Boot JAR 文件,主要包含以下两个核心类:
|
||||||
|
|
||||||
|
### 1. JarUtil 工具类
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 路径:spring-boot-jar-slim-encrypt/src/main/java/com/mangmang/JarUtil.java
|
||||||
|
package com.sunri;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import io.xjar.XCryptos;
|
||||||
|
import io.xjar.XEncryption;
|
||||||
|
import org.apache.commons.compress.utils.IOUtils;
|
||||||
|
import org.apache.commons.compress.utils.Sets;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.jar.JarOutputStream;
|
||||||
|
|
||||||
|
public class JarUtil {
|
||||||
|
/**
|
||||||
|
* 表示UTF-8字符编码的常量。
|
||||||
|
* 该变量用于在各种文件操作中强制使用UTF-8编码,
|
||||||
|
* 确保在整个应用程序中一致地处理文本数据。
|
||||||
|
*/
|
||||||
|
private static final String UTF_8 = "UTF-8";
|
||||||
|
/**
|
||||||
|
* 常量BOOT_INF_LIB表示JAR文件中通常存储依赖库的默认目录路径。
|
||||||
|
* 该路径主要用于在压缩或排除等操作中识别和处理库文件。
|
||||||
|
*/
|
||||||
|
private static final String BOOT_INF_LIB = "BOOT-INF/lib";
|
||||||
|
/**
|
||||||
|
* 用于标识JAR(Java归档)文件的文件扩展名。
|
||||||
|
* 该常量表示JAR文件的标准扩展名,通常用于
|
||||||
|
* 文件过滤、命名或在目录或归档中识别JAR文件的操作。
|
||||||
|
*/
|
||||||
|
private static final String JAR_EXTENSION = ".jar";
|
||||||
|
/**
|
||||||
|
* 定义在管理JAR过程中生成的需求文件的后缀,
|
||||||
|
* 特别是在处理依赖项或排除项时使用。
|
||||||
|
* 该字符串用作特定的文件名模式,用于保存与特定服务
|
||||||
|
* 相关的排除依赖项或其他需求的列表。
|
||||||
|
* 默认值为"-requirements.txt"。
|
||||||
|
*/
|
||||||
|
private static final String REQUIREMENTS_SUFFIX = "-requirements.txt";
|
||||||
|
/**
|
||||||
|
* 预定义的、不可修改的特定jar文件名集合,被视为
|
||||||
|
* "安全"或"始终包含"的文件。这些jar文件通常在
|
||||||
|
* 处理或压缩操作中免于排除过滤。
|
||||||
|
* 该集合包含以下jar标识符:
|
||||||
|
* - "spring"
|
||||||
|
* - "logback-core"
|
||||||
|
* - "tomcat"
|
||||||
|
* 该变量用于根据jar文件名决定是否包含特定jar文件的操作中。
|
||||||
|
* 它作为应用程序关键或必要jar的白名单。
|
||||||
|
*/
|
||||||
|
private static final Set<String> WHITE_LIST_JARS = Sets.newHashSet("spring", "logback-core", "tomcat");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过排除和包含指定的条目来压缩给定的源JAR文件,并将结果写入目标JAR文件。
|
||||||
|
* 它处理源JAR的条目,应用排除和包含规则,还可以将某些条目提取到指定的目录中。
|
||||||
|
* 在此过程中创建一个临时文件,成功完成后将其重命名为目标JAR文件。
|
||||||
|
*
|
||||||
|
* @param serviceName 正在处理的服务名称,主要用于日志记录和创建其他相关文件。
|
||||||
|
* @param sourceJar 要压缩的源JAR文件。
|
||||||
|
* @param includes 指定应保留哪些条目的包含模式集合。可能会自动添加额外的默认包含项。
|
||||||
|
* @param exclusions 指定应排除哪些条目的排除模式集合。
|
||||||
|
* @param targetJar 将写入压缩JAR的文件。
|
||||||
|
* @param libDir 某些被排除的条目可能被提取到的目录(如适用)。
|
||||||
|
*/
|
||||||
|
public static void compress(String serviceName, File sourceJar, Set<String> includes, Set<String> exclusions, File targetJar, String libDir) {
|
||||||
|
includes.addAll(WHITE_LIST_JARS);
|
||||||
|
File tempJar = new File(targetJar.getAbsolutePath() + ".tmp");
|
||||||
|
Set<String> excludedJars = new HashSet<>();
|
||||||
|
|
||||||
|
if (processJarEntries(sourceJar, tempJar, includes, exclusions, libDir, excludedJars)) {
|
||||||
|
finalizeCompression(serviceName, targetJar, tempJar, excludedJars, libDir);
|
||||||
|
} else {
|
||||||
|
boolean delete = tempJar.delete();
|
||||||
|
System.out.println("删除临时文件:{" + delete + "}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理源JAR文件中的条目以生成临时JAR文件,
|
||||||
|
* 同时根据包含和排除规则过滤条目。如果需要,
|
||||||
|
* 还会将指定的JAR条目提取到库目录中。
|
||||||
|
*
|
||||||
|
* @param sourceJar 要处理的源JAR文件
|
||||||
|
* @param tempJar
|
||||||
|
```
|
||||||
|
|
||||||
|
这个工具类提供了两个主要功能:
|
||||||
|
|
||||||
|
#### JAR 包压缩功能
|
||||||
|
|
||||||
|
`compress` 方法实现了 JAR 瘦身功能:
|
||||||
|
|
||||||
|
- 根据包含列表和排除列表过滤 JAR 中的依赖
|
||||||
|
- 将被排除的依赖提取到指定的库目录
|
||||||
|
- 生成一个记录排除依赖的需求文件
|
||||||
|
- 创建一个只包含必要依赖的精简 JAR 文件
|
||||||
|
|
||||||
|
#### JAR 包加密功能
|
||||||
|
|
||||||
|
`encrypt` 方法利用 XJar 库实现了 JAR 加密:
|
||||||
|
|
||||||
|
- 支持指定加密密码
|
||||||
|
- 通过包含和排除模式选择性地加密 JAR 中的内容
|
||||||
|
- 生成加密后的 XJar 文件
|
||||||
|
|
||||||
|
### 2. SpringBootJarSlimEncryptApplication 主应用
|
||||||
|
|
||||||
|
```java
|
||||||
|
// 路径:spring-boot-jar-slim-encrypt/src/main/java/com/mangmang/SpringBootJarSlimEncryptApplication.java
|
||||||
|
```
|
||||||
|
|
||||||
|
这是工具的主应用类,提供了完整的命令行接口来处理 JAR 文件的压缩和加密:
|
||||||
|
|
||||||
|
主要功能:
|
||||||
|
|
||||||
|
- 通过配置常量定义输入/输出目录、加密设置等
|
||||||
|
- 支持从 XML 配置文件加载要包含和排除的依赖项
|
||||||
|
- 批量处理多个 JAR 文件
|
||||||
|
- 支持通过系统属性覆盖默认配置
|
||||||
|
|
||||||
|
主要配置参数:
|
||||||
|
|
||||||
|
- `xml.dir`: 依赖项 XML 文件目录(默认: `./config/xml/`)
|
||||||
|
- `raw.dir`: 原始 JAR 文件目录(默认: `./config/rawJars/`)
|
||||||
|
- `compress.dir`: 压缩后 JAR 文件目录(默认: `./config/compressJars/`)
|
||||||
|
- `libs.dir`: 提取的库文件目录(默认: `./config/libs/`)
|
||||||
|
- `xjar.dir`: 加密后的 XJar 文件目录(默认: `./config/xJars/`)
|
||||||
|
- `compress.enable`: 是否启用压缩功能(默认: `true`)
|
||||||
|
|
||||||
|
## 使用步骤
|
||||||
|
|
||||||
|
### 步骤 1: 集成自定义类加载器
|
||||||
|
|
||||||
|
在你的 Spring Boot 项目中添加自定义类加载器依赖:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.mangmang</groupId>
|
||||||
|
<artifactId>spring-boot-custom-classloader</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 2: 构建 Spring Boot 应用
|
||||||
|
|
||||||
|
正常构建你的 Spring Boot 应用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn clean package
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 3: 配置依赖排除和包含规则
|
||||||
|
|
||||||
|
创建两个 XML 文件以定义要排除和包含的依赖项:
|
||||||
|
|
||||||
|
**exclusions.xml**(要排除的依赖):
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<version>2.7.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 其他要排除的依赖 -->
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
|
||||||
|
**includes.xml**(要保留的依赖):
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<artifactId>spring-boot-custom-classloader</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 其他要保留的依赖 -->
|
||||||
|
</dependencies>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 4: 执行 JAR 瘦身和加密工具
|
||||||
|
|
||||||
|
将你的 Spring Boot JAR 文件放入 `./config/rawJars/` 目录,然后运行瘦身加密工具:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
java -jar spring-boot-jar-slim-encrypt.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
你可以通过系统属性覆盖默认配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
java -Dcompress.enable=true -Dlibs.dir=/custom/libs/path -jar spring-boot-jar-slim-encrypt.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 5: 部署和运行
|
||||||
|
|
||||||
|
部署加密后的 JAR 文件和提取的库文件:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
java -Dexternal.jars.path=/path/to/libs -jar your-application.xjar
|
||||||
|
```
|
||||||
|
|
||||||
|
## 技术原理解析
|
||||||
|
|
||||||
|
### JAR 瘦身原理
|
||||||
|
|
||||||
|
1. 扫描 Spring Boot JAR 中的 `BOOT-INF/lib` 目录
|
||||||
|
2. 根据配置的排除和包含规则过滤依赖
|
||||||
|
3. 将被排除的依赖提取到外部目录
|
||||||
|
4. 创建一个不包含被排除依赖的新 JAR 文件
|
||||||
|
|
||||||
|
### JAR 加密原理
|
||||||
|
|
||||||
|
1. 使用 XJar 库实现 JAR 文件内容的加密
|
||||||
|
2. 只加密指定的文件模式(如 Java 类文件、配置文件等)
|
||||||
|
3. 避免加密某些需要保持明文的资源
|
||||||
|
|
||||||
|
### 自定义类加载器原理
|
||||||
|
|
||||||
|
1. 在 Spring Boot 应用启动时初始化自定义类加载器
|
||||||
|
2. 扫描指定目录下的 JAR 文件
|
||||||
|
3. 使用反射机制将 JAR 文件 URL 添加到当前类加载器
|
||||||
|
|
||||||
|
## 方案优势
|
||||||
|
|
||||||
|
1. **减小 JAR 体积**:将大型依赖库外置,显著减小主 JAR 文件体积
|
||||||
|
2. **提高安全性**:通过加密保护核心业务逻辑和敏感配置
|
||||||
|
3. **灵活配置**:支持通过 XML 配置和系统属性灵活控制瘦身和加密过程
|
||||||
|
4. **无缝集成**:与 Spring Boot 应用无缝集成,无需修改应用代码
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 确保加密密码安全保存,丢失密码将导致无法运行加密的 JAR
|
||||||
|
2. 测试瘦身后的应用,确保所有需要的依赖都能正确加载
|
||||||
|
3. 部署时必须将提取的依赖库和加密后的 JAR 一起部署
|
||||||
|
4. 启动应用时必须指定外部库路径参数
|
||||||
|
|
||||||
|
## 结论
|
||||||
|
|
||||||
|
通过结合 JAR 瘦身、JAR 加密和自定义类加载器,我们成功构建了一套完整的 Spring Boot 应用优化和保护方案。这不仅有效减小了部署包的体积,还提高了应用的安全性,为企业级
|
||||||
|
Spring Boot 应用的部署提供了一种实用的解决方案。
|
||||||
|
|
||||||
|
在实际应用中,可以根据具体需求调整配置参数,以达到最佳的平衡点。例如,可以根据应用规模和安全需求调整要排除的依赖和加密的文件模式。
|
||||||
|
|
||||||
|
这套工具实现了将原本臃肿的 Spring Boot 应用拆分为核心加密 JAR 和外部依赖库的方案,使得应用部署更加灵活,也为应用分发和更新提供了更多可能性。
|
||||||
|
|
||||||
|
------
|
||||||
|
|
||||||
|
*注:本方案适用于需要保护核心业务逻辑或减小部署包体积的 Spring Boot
|
||||||
|
应用。对于简单应用或开源项目,可能不必使用这么复杂的方案。*
|
@ -7,6 +7,7 @@ category:
|
|||||||
tag:
|
tag:
|
||||||
- websocket
|
- websocket
|
||||||
- http
|
- http
|
||||||
|
title: WebSocket和HTTP关系
|
||||||
---
|
---
|
||||||
|
|
||||||
# WebSocket和HTTP关系
|
# WebSocket和HTTP关系
|
||||||
@ -14,7 +15,7 @@ tag:
|
|||||||
## 1. WebSocket简介
|
## 1. WebSocket简介
|
||||||
|
|
||||||
WebSocket 是 HTML5 提供的一种在单个 TCP 连接上进行全双工通讯的协议。它使客户端和服务器之间的数据交换变得更加简单高效,并允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需完成一次握手,便可创建持久性的连接,实现双向数据传输。
|
WebSocket 是 HTML5 提供的一种在单个 TCP 连接上进行全双工通讯的协议。它使客户端和服务器之间的数据交换变得更加简单高效,并允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需完成一次握手,便可创建持久性的连接,实现双向数据传输。
|
||||||
<!-- more -->
|
|
||||||
## 2. WebSocket与HTTP的关系
|
## 2. WebSocket与HTTP的关系
|
||||||
|
|
||||||
### 2.1 协议转换过程
|
### 2.1 协议转换过程
|
||||||
|
230
src/programming/java/工具箱/XJar.md
Normal file
230
src/programming/java/工具箱/XJar.md
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
---
|
||||||
|
icon: bi:arrows-expand
|
||||||
|
date: 2025-05-13
|
||||||
|
category:
|
||||||
|
- JAVA
|
||||||
|
- 加密
|
||||||
|
tag:
|
||||||
|
- xjar
|
||||||
|
title: XJar
|
||||||
|
---
|
||||||
|
|
||||||
|
XJar:保护您的Java应用程序免受反编译和源码泄露
|
||||||
|
<!-- more -->
|
||||||
|
# XJar:保护您的Java应用程序免受反编译和源码泄露
|
||||||
|
|
||||||
|
介绍一个强大且实用的工具——**XJar**。它专为Spring Boot JAR和原生JAR提供安全加密运行支持,能够有效防止源码泄露和反编译的风险。无论你是想保护个人项目还是企业级应用,XJar都能为你提供一个简单而高效的解决方案。
|
||||||
|
|
||||||
|
GitHub: https://github.com/core-lib/xjar
|
||||||
|
|
||||||
|
## 什么是XJar?
|
||||||
|
|
||||||
|
XJar是一个开源工具,通过对JAR包内的资源进行加密,并结合扩展的ClassLoader,构建了一套程序加密启动和动态解密运行的机制。它特别适合Spring Boot项目,同时也支持原生JAR,旨在帮助开发者保护Java应用程序的安全性。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
XJar提供了以下核心功能,让它在加密工具中脱颖而出:
|
||||||
|
|
||||||
|
- **无代码侵入**:无需修改源代码,只需对编译好的JAR包进行加密即可。
|
||||||
|
- **完全内存解密**:资源在运行时动态解密,减少源码或字节码泄露的风险。
|
||||||
|
- **支持所有JDK内置加解密算法**:灵活选择适合你的加密算法。
|
||||||
|
- **资源加密灵活性**:支持选择需要加密的字节码或其他资源文件。
|
||||||
|
- **Maven插件支持**:集成到构建流程,加密更便捷。
|
||||||
|
- **Go启动器**:动态生成Go语言启动器,保护密码不泄露。
|
||||||
|
|
||||||
|
## 环境依赖
|
||||||
|
|
||||||
|
- **JDK版本**:1.7及以上
|
||||||
|
|
||||||
|
## 使用步骤
|
||||||
|
|
||||||
|
下面我将详细介绍如何使用XJar加密你的JAR包,步骤清晰易懂。
|
||||||
|
|
||||||
|
### 1. 添加依赖
|
||||||
|
|
||||||
|
首先,在你的Maven项目中添加XJar依赖,并配置jitpack.io仓库:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<project>
|
||||||
|
<!-- 设置jitpack.io仓库 -->
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>jitpack.io</id>
|
||||||
|
<url>https://jitpack.io</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<!-- 添加XJar依赖 -->
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.core-lib</groupId>
|
||||||
|
<artifactId>xjar</artifactId>
|
||||||
|
<version>4.0.2</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
```
|
||||||
|
|
||||||
|
> **小贴士**:如果只是用JUnit测试加密过程,可以将`<scope>`设置为`test`。
|
||||||
|
|
||||||
|
### 2. 加密源码
|
||||||
|
|
||||||
|
使用XJar提供的`XCryptos.encryption()`方法对JAR包进行加密:
|
||||||
|
|
||||||
|
```java
|
||||||
|
XCryptos.encryption()
|
||||||
|
.from("/path/to/read/plaintext.jar") // 待加密JAR包路径
|
||||||
|
.use("io.xjar") // 加密密码
|
||||||
|
.include("/io/xjar/**/*.class") // 需要加密的字节码
|
||||||
|
.include("/mapper/**/*Mapper.xml") // 需要加密的资源文件
|
||||||
|
.exclude("/static/**/*") // 排除静态文件
|
||||||
|
.exclude("/conf/*") // 排除配置文件
|
||||||
|
.to("/path/to/save/encrypted.jar"); // 输出加密后的JAR包
|
||||||
|
```
|
||||||
|
|
||||||
|
- `include`和`exclude`支持ANT表达式或正则表达式,灵活控制加密范围。
|
||||||
|
- 当两者同时使用时,加密范围为`include`内排除`exclude`后的资源。
|
||||||
|
|
||||||
|
### 3. 编译脚本
|
||||||
|
|
||||||
|
加密完成后,XJar会在输出目录生成一个`xjar.go`文件。这是Go语言编写的启动器源码,需要编译为可执行文件:
|
||||||
|
|
||||||
|
- **Windows**:编译后生成`xjar.exe`
|
||||||
|
- **Linux**:编译后生成`xjar`
|
||||||
|
|
||||||
|
编译需要Go环境,但运行时无需Go支持。注意:启动器带有防篡改校验,无法通用。
|
||||||
|
|
||||||
|
### 4. 启动运行
|
||||||
|
|
||||||
|
使用编译好的启动器运行加密后的JAR包:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./xjar java -Xms256m -Xmx1024m -jar /path/to/encrypted.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
- 启动器需放在Java命令之前。
|
||||||
|
- 仅支持`-jar`方式启动,不支持`-cp`或`-classpath`。
|
||||||
|
- 使用`nohup`时,需写为:`nohup ./xjar java -jar /path/to/encrypted.jar`。
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
在使用XJar时,以下问题可能影响你的体验,我整理了解决方案供参考:
|
||||||
|
|
||||||
|
### 1. Spring Boot Maven插件兼容性
|
||||||
|
|
||||||
|
XJar不支持`spring-boot-maven-plugin`的`executable = true`和`embeddedLaunchScript`配置,需删除:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<!-- 删除以下配置 -->
|
||||||
|
<!-- <configuration>
|
||||||
|
<executable>true</executable>
|
||||||
|
<embeddedLaunchScript>...</embeddedLaunchScript>
|
||||||
|
</configuration> -->
|
||||||
|
</plugin>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Spring Boot + JPA(Hibernate)报错
|
||||||
|
|
||||||
|
若使用Hibernate,启动可能报错。解决方法:
|
||||||
|
|
||||||
|
1. 克隆[XJar-Agent-Hibernate](https://github.com/core-lib/xjar-agent-hibernate),编译生成`xjar-agent-hibernate-${version}.jar`。
|
||||||
|
|
||||||
|
2. 启动命令添加代理:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./xjar java -javaagent:xjar-agent-hibernate-${version}.jar -jar your-app.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 静态文件加载问题
|
||||||
|
|
||||||
|
加密静态文件可能导致浏览器加载失败,建议排除加密:
|
||||||
|
|
||||||
|
```java
|
||||||
|
.exclude("/static/**/*")
|
||||||
|
.exclude("/META-INF/resources/**/*")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. JDK 9+模块化问题
|
||||||
|
|
||||||
|
在JDK 9及以上版本,需添加参数:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./xjar java --add-opens java.base/jdk.internal.loader=ALL-UNNAMED -jar /path/to/encrypted.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 阿里云Maven镜像问题
|
||||||
|
|
||||||
|
使用阿里云镜像时,需在`mirrorOf`中排除jitpack.io:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<mirror>
|
||||||
|
<id>alimaven</id>
|
||||||
|
<mirrorOf>central,!jitpack.io</mirrorOf>
|
||||||
|
<url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
|
||||||
|
</mirror>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 插件集成
|
||||||
|
|
||||||
|
XJar提供了[xjar-maven-plugin](https://github.com/core-lib/xjar-maven-plugin),可自动完成加密过程。
|
||||||
|
|
||||||
|
### 配置示例
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<project>
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>jitpack.io</id>
|
||||||
|
<url>https://jitpack.io</url>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.github.core-lib</groupId>
|
||||||
|
<artifactId>xjar-maven-plugin</artifactId>
|
||||||
|
<version>4.0.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>build</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>package</phase>
|
||||||
|
<configuration>
|
||||||
|
<password>io.xjar</password>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 执行方式
|
||||||
|
|
||||||
|
- **自动构建**:`mvn clean package -Dxjar.password=io.xjar`
|
||||||
|
- **手动执行**:`mvn xjar:build -Dxjar.password=io.xjar`
|
||||||
|
|
||||||
|
> **强烈建议**:不要在`pom.xml`中写死密码,通过命令行传递更安全!
|
||||||
|
|
||||||
|
## 参数说明
|
||||||
|
|
||||||
|
以下是`xjar-maven-plugin`的主要参数:
|
||||||
|
|
||||||
|
| 参数名称 | 命令参数 | 参数说明 | 参数类型 | 缺省值 |
|
||||||
|
| --------- | ---------------- | ------------ | -------- | -------------------------- |
|
||||||
|
| password | -Dxjar.password | 密码字符串 | String | 必须 |
|
||||||
|
| algorithm | -Dxjar.algorithm | 加密算法名称 | String | AES/CBC/PKCS5Padding |
|
||||||
|
| keySize | -Dxjar.keySize | 密钥长度 | int | 128 |
|
||||||
|
| ivSize | -Dxjar.ivSize | 密钥向量长度 | int | 128 |
|
||||||
|
| sourceDir | -Dxjar.sourceDir | 源JAR目录 | File | ${project.build.directory} |
|
||||||
|
| targetDir | -Dxjar.targetDir | 目标JAR目录 | File | ${project.build.directory} |
|
||||||
|
|
||||||
|
更多详情见:[xjar-maven-plugin](https://github.com/core-lib/xjar-maven-plugin)。
|
||||||
|
|
||||||
|
## 结尾
|
||||||
|
|
||||||
|
XJar以其无侵入性、灵活性和高效性,成为保护Java应用的绝佳选择。无论是个人项目还是商业产品,它都能帮你轻松加密JAR包,确保代码安全。赶快试试吧!
|
Loading…
Reference in New Issue
Block a user