起因:使用SpringBoot开发项目,引用了很多依赖,最终打包成可运行的jar文件时,往往有几十M,或者更大,上传服务器要浪费很长时间。
优化方式一
1. 依赖分离
SpringBoot可运行的jar文件很大是因为,jar文件里包含了很多依赖jar,所以才会生成几十M的文件。
解决办法是在maven配置中,使用插件:
<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <!--使用该插件打包 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <manifest> <useUniqueVersions>false</useUniqueVersions> <addClasspath>true</addClasspath> <classpathPrefix>/data/server/system-demo/libs/</classpathPrefix> <mainClass>com.zh.system.SystemApplication</mainClass> </manifest> <manifestEntries> </manifestEntries> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <executions> <execution> <id>copy</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>/data/server/system-demo/libs/</outputDirectory> </configuration> </execution> </executions> </plugin> <!-- 跳过单元测试 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skipTests>true</skipTests> </configuration> </plugin> </plugins> </build>
maven-jar-plugin插件的作用是jar运行时使用的配置,属性包括:classpathPrefix指定外部jar的路径,mainClass指定jar包的启动类
maven-dependency-plugin插件的作用是打包时,指定依赖jar拷贝的目录。
/data/server/system-demo 是我准备的项目运行jar包的目录。
我这里使用的路径都是/data/server/system-demo/libs/,如果你是在windows系统下编译打包项目,你可以到项目所在的workspace的磁盘根目录下查找,会发现也生成了这样的目录,项目相关的jar包都拷贝到这里了。在服务器上创建目录/data/server/system-demo/libs/,并且把项目需要的jar包都上传到此目录。
2. 配置文件管理
我的项目中的配置文件按服务器环境配置了几套,如下图:
在application.yml的代码,使用这条命令指定加载的子配置文件:spring.profiles.active: test
这样管理配置很方便,避免多个服务器环境之间的参数切换,带来混淆的问题。但如果你修改代码之后,每个环境都要发布一遍,就会需要修改spring.profiles.active的值后,重复打包的问题。
所以,按照SpringBoot的运行加载规则,如果在运行jar统计目录有config文件夹,会被提前加载的。我们只需要在/data/server/system-demo/下创建一个config文件夹。并只上传此环境的配置文件就好了。
方法1:正常打包,这些配置文件会在jar包的config目录下,我们只要删掉这些文件,在jar包运行时,就会自动读取/data/server/system-demo/config 里面的文件了,避免了很多重复打包工作。
方法2:在打包时,是可以使用maven插件把配置文件排除的,我还没试。
3. 总结
当项目运行时,最终在system-demo目录下,会有2个文件夹,2个文件。
system-demo-1.0-SNAPSHOT.jar -------SpringBoot启动jar包
config ---------项目的配置文件
libs -----------项目的依赖jar
nohup.out ------nohup命令运行jar文件之后,生成的临时日志文件
优化方式二
1. 正常编译JAR包,解压出lib文件夹
POM文件如下:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.johnnian.App</mainClass> <layout>ZIP</layout> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugins> <build>
进入项目根目录,执行命令:mvn clean install
将编译后的Jar包解压,拷贝 BOOT-INF 目录下的lib文件夹 到目标路径;
2. 修改pom.xml配置,编译出不带 lib 文件夹的Jar包
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.johnnian.App</mainClass> <layout>ZIP</layout> <includes> <include> <groupId>nothing</groupId> <artifactId>nothing</artifactId> </include> </includes> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugins> <build>
配置完成后,再次执行编译:mvn clean install
生成的 Jar 包体积明显变小,外部的 jar 包已经不会被引入了。
3. 运行编译后的Jar包
将 步骤1 解压出来的lib文件夹、步骤2编译的jar包放在同一个目录, 运行下面命令:
java -Dloader.path=/path/to/lib -jar /path/to/springboot-jsp-0.0.1-SNAPSHOT.jar
或者在maven中输入一下命令导出需要用到的jar包
mvn dependency:copy-dependencies -DoutputDirectory=F:ideaWorkPlaceAnalysisEnginelib -DincludeScope=runtime
备注:将/path/to/改成实际的路径。-Dloader.path=lib文件夹路径
最终目录文件结构是:
├── lib #lib文件夹
└── springboot-jsp-0.0.1-SNAPSHOT.jar
说明:
1、通常,一个工程项目架构确定后,引入的jar包基本上不会变,改变的大部分是业务逻辑;
2、后面如果需要变更业务逻辑,只需要轻量地编译工程,大大提高项目部署的效率。
步骤1: 正常编译JAR包,解压出lib文件夹