maven混淆打包的實(shí)現(xiàn)步驟
項(xiàng)目混淆
ProGuard 是一個混淆代碼的開源項(xiàng)目,它的主要作用是混淆代碼,ProGuard 包括以下 4 個功能:
- 壓縮(Shrink):檢測并移除代碼中無用的類、字段、方法和特性(Attribute)
- 優(yōu)化(Optimize):對字節(jié)碼進(jìn)行優(yōu)化,移除無用的指令
- 混淆(Obfuscate):使用 a,b,c,d 這樣簡短而無意義的名稱,對類、字段和方法進(jìn)行重命名
- 預(yù)檢(Preveirfy):在 Java 平臺上對處理后的代碼進(jìn)行預(yù)檢,確保加載的 class 文件是可執(zhí)行的
使用 proguard 混淆代碼只能增加閱讀和理解的難度, 并不能百分百保證代碼安全。常用的應(yīng)用場景是項(xiàng)目需要部署到客戶機(jī)器上,一定程度上防止代碼泄露
具體實(shí)現(xiàn)
1.在原本的SpringBoot項(xiàng)目的pom.xml文件里面加上以下配置
<!--經(jīng)過修改后,能夠混淆的build段-->
<build>
<plugins>
<!--maven打包插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mmg.Main</mainClass> <!-- 此處為主入口-->
</manifest>
</archive>
</configuration>
</plugin>
<!--proguard混淆插件-->
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.5.3</version>
<executions>
<execution>
<!--打包的時候開始混淆-->
<phase>package</phase>
</execution>
</executions>
<configuration>
<proguardVersion>${proguard.version}</proguardVersion>
<injar>${project.build.finalName}.jar</injar>
<!--輸出的jar-->
<outjar>${project.build.finalName}.jar</outjar>
<!--是否混淆-->
<obfuscate>true</obfuscate>
<proguardInclude>${basedir}/proguard.cfg</proguardInclude>
<options>
<!--默認(rèn)開啟,不做收縮(刪除注釋、未被引用代碼)-->
<option>-dontshrink</option>
<!--默認(rèn)是開啟的,這里關(guān)閉字節(jié)碼級別的優(yōu)化-->
<option>-dontoptimize</option>
<!--對于類成員的命名的混淆采取唯一策略-->
<option>-useuniqueclassmembernames</option>
<!--混淆時不生成大小寫混合的類名,默認(rèn)是可以大小寫混合-->
<option>-dontusemixedcaseclassnames</option>
<!--混淆類名之后,對使用Class.forName('className')之類的地方進(jìn)行相應(yīng)替代-->
<option>-adaptclassstrings</option>
<!--對異常、注解信息在runtime予以保留,不然影響springboot啟動-->
<option>-keepattributes
Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
</option>
<!--此選項(xiàng)將保存接口中的所有原始名稱(不混淆)-->
<option>-keepnames interface ** { *; }</option>
<!--此選項(xiàng)將保存所有軟件包中的所有原始接口文件(不進(jìn)行混淆)-->
<!--<option>-keep interface * extends * { *; }</option>-->
<!--此選項(xiàng)將保留所有原始方法參數(shù),controller如果參數(shù)也混淆會導(dǎo)致傳參映射不上 -->
<option>-keepparameternames</option>
<!--保留枚舉成員及方法-->
<option>-keepclassmembers enum * { *; }</option>
<!--不混淆所有類,保存原始定義的注釋-->
<!--<option>-keepclassmembers class * {
@org.springframework.context.annotation.Bean *;
@org.springframework.beans.factory.annotation.Autowired *;
@org.springframework.beans.factory.annotation.Value *;
@org.springframework.stereotype.Service *;
@org.springframework.stereotype.Component *;
}
</option>-->
<!--忽略warn消息-->
<option>-ignorewarnings</option>
<!--忽略note消息-->
<option>-dontnote</option>
</options>
<!--java 11-->
<libs>
<lib>${java.home}/jmods/</lib>
</libs>
<!--java 8-->
<!-- <libs>
<lib>${java.home}/lib/rt.jar</lib>
<lib>${java.home}/lib/jsse.jar</lib>
</libs>-->
</configuration>
<dependencies>
<dependency>
<groupId>com.guardsquare</groupId>
<artifactId>proguard-base</artifactId>
<version>7.2.1</version>
</dependency>
</dependencies>
</plugin>
<!--將自己加入的jar也打包插件 可加可不加-->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.mmg.Main</mainClass>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path>
</manifestEntries>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>2.在與pom.xml文件同級目錄下新建一個proguard.cfg文件,這個文件是混淆的核心配置文件,根據(jù)需求進(jìn)行配置

#所有類(包括接口)的方法參數(shù)不混淆(包括沒被keep的),如果參數(shù)混淆了,mybatis的mapper參數(shù)綁定會出錯(如#{id})
-keepattributes MethodParameters
#入口程序類不能混淆,混淆會導(dǎo)致springboot啟動不了
-keep class com.langyastudio.edu.admin.Application {
public static void main(java.lang.String[]);
}
#mybatis的mapper/實(shí)體類不混淆,否則會導(dǎo)致xml配置的mapper找不到
-keep class com.langyastudio.edu.admin.dao.*
-keeppackagenames com.langyastudio.edu.admin.dao
#考慮到scanBasePackages,需要包名不被修改
-keeppackagenames com.langyastudio.edu
-keeppackagenames com.langyastudio.edu.admin.common
#一些配置類比如datasource,aopconfig如果混淆會導(dǎo)致各種啟動報錯
# 比如用@Pointcut("execution(public * com.langyastudio.edu.*.controller..*.*(..))")
# 指定webLog方法對應(yīng)的@Pointcut作為切入點(diǎn),所以包的名字不能修改
-keeppackagenames com.langyastudio.edu.*.controller.**
-keep class com.langyastudio.edu.admin.config.*
#保留Serializable序列化的類不被混淆
#例如傳入/輸出的Bean屬性
-keepclassmembers class * implements java.io.Serializable {*;}
#保留空的構(gòu)造函數(shù)
#-keepclassmembers class com.hacfin.* {
# public <init>(...);
#}3.點(diǎn)擊maven生命周期中的package將項(xiàng)目進(jìn)行打包,然后點(diǎn)擊maven插件中的proguard插件對打出來的jar進(jìn)行混淆。值得注意的是,如果你使用將自己加入的jar也打包插件,他會把加入自己jar包的命名為xxxxx-jar-with-dependencies.jar,而混淆只能混淆原jar包,這時候需要你把xxxxx-jar-with-dependencies.jar修改為正常打包出來的jar名字(xxx-1.0-SNAPSHOT),不然會混淆不了



項(xiàng)目瘦身
什么是瘦身?
瘦身: thin Body 又稱 "減肥"、"減重"。 就是合理、科學(xué)的減輕自身重量的。SpringBoot 應(yīng)用瘦身顧名思議:就是將 SpringBoot 應(yīng)用打包的 jar 利用合理的方式、方法減小體積。
為什么要瘦身?
場景: 現(xiàn)有的應(yīng)用開發(fā)中,不論是單體架構(gòu)、微服務(wù)架構(gòu),如果項(xiàng)目采用的是 springboot、springcloud 來作為底層框架,打包時最終都會以jar包的方式打包、部署。這是就會面臨一個問題,就是 jar 包非常大,單體應(yīng)用還好,但是如果是微服務(wù)就非常痛苦,幾十個微服務(wù)就要拆分打包幾十個 jar 包,每個 jar 包都很大(幾百M(fèi)),合起來就好幾個 GB,非常占用空間。如果是內(nèi)網(wǎng)部署,遇到動輒GB的升級包還能勉強(qiáng)接受,最多就是運(yùn)維心里默默地吐槽一下,但是如果在外網(wǎng)云環(huán)境、或者客戶現(xiàn)場,那令人痛不欲生的帶寬加上各種網(wǎng)絡(luò)轉(zhuǎn)換限制,運(yùn)維心里各種??。因?yàn)檫@個你的領(lǐng)導(dǎo)又給你各種批頭蓋臉一頓。
如何瘦身?
瘦身思路:
其實(shí)就是將你自己寫的代碼和引入依賴包進(jìn)行分離操作,它并不能改變項(xiàng)目總體的大小,但是它方便你日后對項(xiàng)目進(jìn)行升級操作,日后只需要換jar就可以了,不需要動固定引入依賴jar包文件夾。

具體實(shí)現(xiàn)
1.在原本的SpringBoot項(xiàng)目的pom.xml文件里面加上以下配置
<!--經(jīng)過修改后,能夠瘦身的build段-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<finalName>${project.build.finalName}</finalName>
<!--解決windows命令行窗口中文亂碼-->
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
<layout>ZIP</layout>
<includes>
<!--這里是填寫需要包含進(jìn)去的jar,
必須項(xiàng)目中的某些模塊,會經(jīng)常變動,那么就應(yīng)該將其坐標(biāo)寫進(jìn)來
如果沒有則non-exists ,表示不打包依賴
-->
<include>
<groupId>non-exists</groupId>
<artifactId>non-exists</artifactId>
</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 此插件用于將依賴包抽出-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!--抽出到哪個目錄,${project.build.directory}表示當(dāng)前項(xiàng)目構(gòu)建的目錄-->
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<!--是否排除傳遞性-->
<excludeTransitive>false</excludeTransitive>
<!--是否去掉 jar 包版本信息-->
<stripVersion>false</stripVersion>
<!--包含范圍-->
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>2.經(jīng)過以上操作你再進(jìn)行項(xiàng)目打包后,你的項(xiàng)目將會分為自己寫的代碼jar包和分離出來的jar包目錄,到這還沒結(jié)束,需要配合以下參數(shù)啟動項(xiàng)目才行。
java -Dloader.path=./lib -jar xxx.jar
項(xiàng)目打包exe
可以使我們的項(xiàng)目直接由jar包打包成exe可執(zhí)行程序
具體實(shí)現(xiàn)
第一種實(shí)現(xiàn)方式
正常將我們的項(xiàng)目打成jar包,打包好以后先打開看一下確??梢哉_執(zhí)行

2.在當(dāng)前目錄加入以下腳本對jar包進(jìn)行打包,根據(jù)自己的jar包名稱對以下腳本進(jìn)行修改即可!全部修改完成,雙擊此bat腳本即可
@echo off echo package current jar to exe set USE_JAR=PackageExe-1.0-SNAPSHOT.jar set USE_CONFIG=config set APP_CLASS= set APP_NAME="SpringBootTest" set OUT_FILE="SpringBootTest" set TITLE="SpringBootTestDemo" javapackager -deploy -native -outdir packages -outfile %OUT_FILE% -srcfiles %USE_JAR% -appclass org.springframework.boot.loader.JarLauncher -name %APP_NAME% -title %TITLE% pause



第二種實(shí)現(xiàn)方式
1.在原本的SpringBoot項(xiàng)目的pom.xml文件里面加上以下配置,一樣的道理根據(jù)自己的情況進(jìn)行修改!
2.雙擊package打包按鈕,他就會根據(jù)你的配置生成對應(yīng)的目錄,目錄內(nèi)含有exe文件和jdk運(yùn)行環(huán)境



總結(jié)
1.代碼混淆使用的是ProGuard開源項(xiàng)目的插件
2.項(xiàng)目瘦身采用的是將jar包和依賴項(xiàng)分離
3.打成exe可執(zhí)行文件使用的是javapackager
到此這篇關(guān)于maven混淆打包的實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)maven混淆打包內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Fluent MyBatis實(shí)現(xiàn)動態(tài)SQL
MyBatis 令人喜歡的一大特性就是動態(tài) SQL。本文主要介紹了Fluent MyBatis實(shí)現(xiàn)動態(tài)SQL,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08
Java實(shí)現(xiàn)默認(rèn)目錄查看與修改的方法
本項(xiàng)目介紹了Java如何獲取和修改默認(rèn)目錄,并通過示例代碼展示了如何在默認(rèn)目錄下創(chuàng)建和操作文件,盡管Java無法直接更改全局默認(rèn)目錄,但可以通過System.setProperty間接影響部分API的默認(rèn)行為,需要的朋友可以參考下2025-03-03
RocketMQ producer同步發(fā)送單向發(fā)送源碼解析
這篇文章主要為大家介紹了RocketMQ producer同步發(fā)送單向發(fā)送源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
java數(shù)據(jù)結(jié)構(gòu)基礎(chǔ):單鏈表與雙向鏈表
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)單鏈表、雙向鏈表的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-08-08
Java矩陣連乘問題(動態(tài)規(guī)劃)算法實(shí)例分析
這篇文章主要介紹了Java矩陣連乘問題(動態(tài)規(guī)劃)算法,結(jié)合實(shí)例形式分析了java實(shí)現(xiàn)矩陣連乘的算法原理與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-11-11
java中ImageReader和BufferedImage獲取圖片尺寸實(shí)例
這篇文章主要介紹了java中ImageReader和BufferedImage獲取圖片尺寸實(shí)例,具有一定借鑒價值,需要的朋友可以參考下2018-01-01

