可运行配置
pom.xml 的配置
重点是proguard插件需要在spring-boot打包插件之前。
<skip>${proguard.skip}</skip> 这里可选,配置一个变量方便控制是否混淆。
<proguardInclude>${project.basedir}/proguard.cfg</proguardInclude> 这里配置了具体的proguard 文件,后面给出具体内容。
xml
<plugins>
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.7.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<skip>${proguard.skip}</skip>
<injar>${project.build.finalName}.jar</injar>
<outjar>${project.build.finalName}.jar</outjar>
<obfuscate>true</obfuscate>
<proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
proguard.cfg 配置文件
和pom.xml同目录下,需要一个proguard.cfg配置文件,内容如下。
# 忽略警告和提示
-dontwarn
-dontnote
# 不做优化(Java SE 不需要)
-dontoptimize
# 保留调试信息和注解(Spring 依赖注解做组件扫描和自动装配)
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod,Record
# ============================================
# 保留 Spring 托管的 Bean(类名/方法名不能混淆)
# ============================================
-keep @org.springframework.stereotype.Component class com.company.project.** { *; }
-keep @org.springframework.core.annotation.Order class com.company.project.** { *; }
-keep @org.springframework.stereotype.Service class com.company.project.** { *; }
-keep @org.springframework.stereotype.Repository class com.company.project.** { *; }
-keep @org.springframework.context.annotation.Configuration class com.company.project.** { *; }
-keep @org.springframework.web.bind.annotation.RestController class com.company.project.** { *; }
-keep @org.springframework.web.bind.annotation.Controller class com.company.project.** { *; }
-keep @org.springframework.web.bind.annotation.RestControllerAdvice class com.company.project.** { *; }
-keep @org.springframework.web.bind.annotation.ControllerAdvice class com.company.project.** { *; }
# ============================================
# 保留 JPA Entity(Hibernate 依赖字段名和 getter/setter 映射)
# ============================================
-keep @jakarta.persistence.Entity class com.company.project.** { *; }
-keep @jakarta.persistence.Table class com.company.project.** { *; }
-keep class com.company.project.dto.** { *; }
-keep interface com.company.project.dao.repository.** { *; }
# ============================================
# 保留所有 Spring Bean 的公开构造器(依赖注入需要)
# ============================================
-keepclassmembers class com.company.project.** {
public <init>(...);
}
# ============================================
# 保留枚举
# ============================================
-keepclassmembers enum com.company.project.** {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# ============================================
# 保留主启动类
# ============================================
-keep public class com.company.project.YourApplication {
public static void main(java.lang.String[]);
}
踩的坑
运行时stackmap验证失败,虽然可以用 -noverify 参数跳过。
解决办法是:移除配置文件中的 -dontpreverify 选项
为什么如此配置
让AI进行了整理
| 分类 | 核心标识 / 注解 | 处理规则 | 核心原因 |
|---|---|---|---|
| SpringBoot 启动类 | @SpringBootApplication、main 方法 |
保留类、main 方法 | 程序入口,Spring 反射加载启动类,混淆后无法找到入口 |
| 控制器层 | @RestController/@Controller、@RequestMapping 等请求注解 |
保留类、公共方法、参数 | SpringMVC 反射解析请求映射,混淆后请求 404 |
| Service 业务层 | @Service、@Autowired |
保留类、方法、注入字段 | Spring 依赖注入基于反射,混淆后 Bean 无法注入 |
| JPA 持久层 | @Repository、JpaRepository/CrudRepository、@Query |
保留接口、所有方法 | JPA 动态代理生成实现类,方法名是查询规则,混淆后代理 / 查询失效 |
| JPA 实体类 | @Entity/@Table/@Id/@Column(JPA 映射注解) |
保留类、所有字段、getter/setter | JPA 反射映射实体与数据库,混淆后 ORM 映射失败、数据库操作报错 |
| Spring 配置类 | @Configuration/@Bean/@Component |
保留类、@Bean 方法 |
Spring 反射加载配置类,混淆后配置失效、Bean 无法创建 |
| 数据传输对象 | DTO/VO/BO、@JsonProperty(Jackson 序列化) |
保留类、所有字段 | 前后端数据序列化 / 反序列化基于反射,混淆后字段名不匹配 |
| 枚举 / 常量类 | @Enumerated(JPA 枚举)、static final 常量 |
保留类、所有枚举值 / 常量 | JPA 映射枚举、系统常量依赖固定值,混淆后数据错乱 |
| 自定义 AOP 切面 | @Aspect/@Pointcut/@Around |
保留切面类、切点方法 | Spring AOP 基于动态代理,混淆后切点无法匹配 |