java 基础巩固21

2022-10-30 12:37:40

打包Spring Boot应用

(1)在Spring Boot应用中,打包更加简单,因为Spring Boot自带一个更简单的spring-boot-maven-plugin插件用来打包,我们只需要在pom.xml中加入以下配置:
在这里插入图片描述
无需任何配置,Spring Boot的这款插件会自动定位应用程序的入口Class,我们执行以下Maven命令即可打包:
$ mvn clean package
以springboot-exec-jar项目为例,打包后我们在target目录下可以看到两个jar文件:
$ ls
classes
generated-sources
maven-archiver
maven-status
springboot-exec-jar-1.0-SNAPSHOT.jar
springboot-exec-jar-1.0-SNAPSHOT.jar.original
其中,springboot-exec-jar-1.0-SNAPSHOT.jar.original是Maven标准打包插件打的jar包,它只包含我们自己的Class,不包含依赖。而spirngboot-exec-jar-1.0-SNAPSHOT.jar是SpringBoot打包插件创建的包含依赖的jar,可以直接运行:
$ java -jar springboot -exec-jar-1.0-SNAPSHOT.jar
这样,部署一个Spring Boot应用就非常简单,无需预装任何服务器,只需要上传jar包即可。在打包的时候,因为打包后的Spring Boot应用不会被修改,因此,默认情况下,spring-boot-devtools这个依赖不会被打包进去。但是要注意,使用早期的SpringBoot版本时,需要配置一下才能排除spring-boot-devtools这个依赖:
在这里插入图片描述
如果不喜欢默认的项目名+版本号作为文件名,可以加一个配置指定文件名:
在这里插入图片描述
这样打包后的文件名就是awesome-app.jar。

瘦身Spinrg Boot应用

(1)使用Spring Boot提供的spring-boot-maven-plugin打包Spring Boot应用,可以直接获得一个完整的可运行的jar包,把它上传到服务器上再运行就极其方便。但是这种方式有缺点,就是包太大了,动不动几十MB。在网速不给力的情况下,上传服务器非常耗时。并且,其中我们引用到的Tomcat、Spring和其他第三方组件,只要版本号不变,这些jar就相当于每次都重复打进去,再重复上传了一遍。真正经常的改动的代码其实就是我们自己编写的代码。如果只打包我们自己编写的代码,通常jar包也就几百KB。但是运行的时候,calsspath中没有依赖的jar包,肯定会报错。所以问题来了,如果只打包我们自己编写的代码,同时又自动把依赖包下载到某处,并自动引入到classpath中。解决方案就是使用spring-boot-thin-launcher。
(2)首先复制一份上一节的Maven项目,并命名为springboot-thin-jar:
在这里插入图片描述
然后,修改<build>-<plugins>-<plugin>,给原来的spring-boot-maven-plugin增加一个<dependency>如下:
在这里插入图片描述
不需要其他任何改动了,我们直接按照正常的流程打包,执行mvn clean package,观察target目录最终生唱的可执行awesome-app.jar,只有79KB左右。
(3)直接运行java-jar awesome-app.jar,效果和上一节完全一样。显然,79KB的jar肯定无法放下Tomcat和Spring这样的大块头。那么,运行时这个awesome-app.jar又是怎么找到它自己依赖的jar包呢?实际上spring-boot-thin-launcher这个插件改变了spring-boot-maven-plugin的默认行为。它的输出的jar包只包含我们自己代码编译后的class,一个很小的ThinJarWrapper,以及解析pom.xml后得到的所有依赖jar的列表。
(4)运行的时候,入口实际上是ThinJarWrapper,它会现在指定目录搜索看看依赖的jar包是否都存在,如果不存在,先从Maven中央仓库下载到本地,然后,在执行我们自己编写的main()入口方法。这种方式有点类似很多在线安装程序:用户下载后得到的是一个很小的exe安装程序,执行安装程序后,会首先在线下载所需要的若干巨大的文件,再进行真正的安装。这个spring-boot-thin-launcher在启动时搜索的默认目录是用户主目录的.m2,我们也可以指定下载目录,例如,将下载目录指定为当前目录:
$ java -Dthin.root= -jar.awesome-app.jar
上述命令通过环境变量thin.root传入当前目录,执行后发现当前目录下自动生成了repository目录,这和Maven的默认下载目录~/.m2/repository的结构是完全一样的,只是它仅仅包含awesome-app.jar所需要的运行期依赖项。
注意:只有首次运行时会自动下载依赖项,再次运行时由于无需下载,所以启动速度会大大加快。如果删除了repository目录,再次运行时就会触发下载。

预热

把79KB大小的awesome-app.jar直接扔到服务器上执行,上传过程非常快。但是,第一次在服务器上运行qwespme-app.jar时,仍需要从Maven中央仓库下载大量的jar包,所以,spring-boot-thin-launcher还提供了一个dryrun选项,专门用来下载依赖项而不执行实际代码:
在这里插入图片描述
执行上述代码会在当前目录创建repository目录,并且下载所有依赖项,但并不会运行我们编写的main()方法。此过程称之为“预热”(warm up)。
如果服务器由于安全限制不允许从外网下载文件,那么可以再本地预热,然后把awespme-app.jar和repository目录上传到服务器。只要依赖项没有变化,后续改动只需要上传awesome-app.jar即可。

使用Profiles

(1)Profile本身是Spring提供的功能,我们在使用条件装配中已经讲到了,Profile表示一个环境的概念,如开发、测试和生产这三个环境:
native
test
production
或者按照git分支定义master、dev这些环境。
在启动一个Spring应用程序的时候,可以传入一个或者多个环境,例如:
-Dspring.profiles.active=test, master
大多数情况下,使用一个环境就足够了。Spring Boot对Profiles的支持在于,可以再application.yml中为每个环境进行配置。下面是一个示例配置:
在这里插入图片描述
注意到分隔符—,最前面的配置是默认配置,不需要制定Profile,后面的每段配置都必须以spring.profiles: xxx开头,表示一个Proifile。上述配置默认使用8080端口,但是在text环境下,使用8000端口,在production环境下,使用80端口,并且启用Pebble的缓存。
(2)如果我们不指定任何Profile,直接启动应用程序,那么Profile实际上就是default,可以从Spirng Boot启动日志看出:
在这里插入图片描述
如果要以test环境启动,可以输入如下命令:
$ java -Dspring.profiles.active=test -jar springboot-peofiles-1.0-SNAPSHOT.jar
从日志看到活动的Profile是test,Tomcat的监听端口是8000.
(2)通过Profile可以实现一套代码在不同环境启用不同的配置和功能。假设我们需要一个存储服务,在本地开发时,直接使用文件存储即可,但是,在测试和生产环境,需要存储到云端如S3上,如何通过Profile实现改功能?
首先,我们要定义存储接口StorageService:
在这里插入图片描述
本地存储可通过LocalStorageServoce实现:
在这里插入图片描述
而云端存储可以经过CloudStorageService实现:
在这里插入图片描述
注意到LocalStorageService使用了条件装配@Profile(“default”),即默认启用LocalStorageService,而CloudStorageService使用了条件装配@Profile(“!default”),即非default环境是,自动启用CloudStorageService。这样,一套代码,就实现了不同环境启用不同的配置。

  • 作者:清和与九
  • 原文链接:https://blog.csdn.net/weixin_49131718/article/details/127209823
    更新时间:2022-10-30 12:37:40