github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;
[Spring官方博客]于2021年03月11日宣布Spring Native的beta版本发布,借助Spring Native可以将spring应用与GraalVM集成到native image中;
native image是GraalVM的一项技术,会将java应用的字节码编译成可执行文件,还会与JDK的本地库做静态链接,运行应用时无需Java虚拟机,自身已集成了内存管理,线程调度等能力,更多信息请参考:www.graalvm.org/reference-manual/native-image/
本文以实战为主,因此不会用太多篇幅介绍Spring Native的理论和优势,这里简单小结几个重要特性:
个人的理解:Spring Native是Spring提供的、制作native image的技术方案,涉及到以下关键技术:
作为实战风格的文章,本篇主要内容是开发springboot应用再构建为native image,然后验证其功能和效果,本文由以下内容构成:
本次实战相关的环境信息如下:
| 名称 | 链接 | 备注 |
|---|---|---|
| 项目主页 | github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
| git仓库地址(https) | github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
| git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |

对Spring Native的学习不是写出helloworld就完事,因此这里先创建一个父工程,为今后所有的应用提供统一的依赖库、插件管理;
新建名为spring-native-tutorials的maven父工程,pom.xml内容如下,有几处要注意的地方稍后提到:
project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
modelVersion>4.0.0modelVersion>
modules>
module>webmvcmodule>
modules>
parent>
groupId>org.springframework.bootgroupId>
artifactId>spring-boot-starter-parentartifactId>
version>2.5.0-SNAPSHOTversion>
relativePath/>
parent>
groupId>com.bolingcavalrygroupId>
artifactId>spring-native-tutorialsartifactId>
version>1.0-SNAPSHOTversion>
packaging>pompackaging>
properties>
java.version>1.8java.version>
<!-- springboot生成jar文件的文件名后缀,用来避免Spring Boot repackaging和native-image-maven-plugin插件之间可能存在的冲突 -->
classifier/>
<!-- 构建镜像时的定制参数 -->
native.build.args/>
<!-- 指定使用dmikusa/graalvm-tiny这个镜像作为构建工具,来构建镜像 -->
builder>dmikusa/graalvm-tinybuilder>
<!-- spring cloud版本 -->
spring-cloud.version>2020.0.2spring-cloud.version>
properties>
<!-- 插件管理 -->
pluginRepositories>
pluginRepository>
id>spring-releaseid>
name>Spring releasename>
url>https://repo.spring.io/releaseurl>
snapshots>
enabled>falseenabled>
snapshots>
pluginRepository>
pluginRepository>
id>spring-milestoneid>
name>Spring milestonename>
url>https://repo.spring.io/milestoneurl>
snapshots>
enabled>falseenabled>
snapshots>
pluginRepository>
pluginRepository>
id>spring-snapshotid>
name>Spring Snapshotsname>
url>https://repo.spring.io/snapshoturl>
releases>
enabled>falseenabled>
releases>
pluginRepository>
pluginRepositories>
<!--仓库管理-->
repositories>
repository>
id>spring-releaseid>
name>Spring releasename>
url>https://repo.spring.io/releaseurl>
snapshots>
enabled>falseenabled>
snapshots>
repository>
repository>
id>spring-milestoneid>
name>Spring milestonename>
url>https://repo.spring.io/milestoneurl>
snapshots>
enabled>falseenabled>
snapshots>
repository>
repository>
id>spring-snapshotid>
name>Spring Snapshotsname>
url>https://repo.spring.io/snapshoturl>
releases>
enabled>falseenabled>
releases>
repository>
repositories>
<!--依赖包版本管理-->
dependencyManagement>
dependencies>
dependency>
groupId>org.springframework.experimentalgroupId>
artifactId>spring-nativeartifactId>
version>0.10.0-SNAPSHOTversion>
dependency>
dependency>
groupId>org.springframework.cloudgroupId>
artifactId>spring-cloud-dependenciesartifactId>
version>${spring-cloud.version}version>
type>pomtype>
scope>importscope>
dependency>
dependencies>
dependencyManagement>
<!--插件配置-->
build>
pluginManagement>
plugins>
plugin>
groupId>org.springframework.bootgroupId>
artifactId>spring-boot-maven-pluginartifactId>
configuration>
classifier>${classifier}classifier>
image>
builder>${builder}builder>
env>
BP_NATIVE_IMAGE>trueBP_NATIVE_IMAGE>
BP_NATIVE_IMAGE_BUILD_ARGUMENTS>${native.build.args}BP_NATIVE_IMAGE_BUILD_ARGUMENTS>
env>
<!--执行构建任务的镜像,如果在当前环境不存在才会远程下载-->
pullPolicy>IF_NOT_PRESENTpullPolicy>
image>
configuration>
plugin>
<!-- aot插件,ahead-of-time transformations -->
plugin>
groupId>org.springframework.experimentalgroupId>
artifactId>spring-aot-maven-pluginartifactId>
version>0.10.0-SNAPSHOTversion>
executions>
execution>
id>test-generateid>
goals>
goal>test-generategoal>
goals>
execution>
execution>
id>generateid>
goals>
goal>generategoal>
goals>
execution>
executions>
plugin>
plugins>
pluginManagement>
build>
project>
project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
parent>
artifactId>spring-native-tutorialsartifactId>
groupId>com.bolingcavalrygroupId>
version>1.0-SNAPSHOTversion>
parent>
modelVersion>4.0.0modelVersion>
artifactId>webmvcartifactId>
dependencies>
dependency>
groupId>org.springframework.experimentalgroupId>
artifactId>spring-nativeartifactId>
dependency>
dependency>
groupId>org.springframework.bootgroupId>
artifactId>spring-boot-starter-webartifactId>
exclusions>
exclusion>
groupId>org.apache.tomcat.embedgroupId>
artifactId>tomcat-embed-coreartifactId>
exclusion>
exclusion>
groupId>org.apache.tomcat.embedgroupId>
artifactId>tomcat-embed-websocketartifactId>
exclusion>
exclusions>
dependency>
dependency>
groupId>org.apache.tomcat.experimentalgroupId>
artifactId>tomcat-embed-programmaticartifactId>
version>${tomcat.version}version>
dependency>
dependency>
groupId>org.springframework.bootgroupId>
artifactId>spring-boot-starter-testartifactId>
scope>testscope>
dependency>
dependencies>
build>
plugins>
plugin>
groupId>org.springframework.experimentalgroupId>
artifactId>spring-aot-maven-pluginartifactId>
configuration>
removeSpelSupport>trueremoveSpelSupport>
configuration>
plugin>
plugin>
groupId>org.springframework.bootgroupId>
artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
package com.bolingcavalry.webmvc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
@SpringBootApplication
@RestController
public class WebmvcApplication {
public static void main(String[] args) {
SpringApplication.run(WebmvcApplication.class, args);
}
@ResponseStatus(HttpStatus.ACCEPTED)
@GetMapping("/status")
public String status() {
return "status";
}
@GetMapping("/")
public String hello() {
return "1. Hello from Spring MVC and Tomcat, " + LocalDateTime.now();
}
}
mvn clean -U -DskipTests spring-boot:build-image
...
[INFO] Successfully built image 'docker.io/library/webmvc:1.0-SNAPSHOT'
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for spring-native-tutorials 1.0-SNAPSHOT:
[INFO]
[INFO] spring-native-tutorials ............................ SUCCESS [ 1.786 s]
[INFO] webmvc ............................................. SUCCESS [04:19 min]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 04:25 min
[INFO] Finished at: 2021-05-22T16:36:44+08:00
[INFO] ------------------------------------------------------------------------
[WARNING] The requested profile "nexus" could not be activated because it does not exist.

(base) zhaoqindeMBP:~ zhaoqin$ docker history webmvc:1.0-SNAPSHOT
IMAGE CREATED CREATED BY SIZE COMMENT
b8ff54813ae0 41 years ago 69B
41 years ago 452kB
41 years ago 2.51MB
41 years ago 57.2MB
41 years ago 1.4MB
41 years ago 268B
41 years ago 17.3MB
docker run --rm -p 8080:8080 webmvc:1.0-SNAPSHOT
(base) zhaoqindeMBP:~ zhaoqin$ docker run --rm -p 8080:8080 webmvc:1.0-SNAPSHOT
2021-05-22 09:34:57.578 INFO 1 --- [ main] o.s.nativex.NativeListener : This application is bootstrapped with code generated with Spring AOT
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _
( ( )___ | '_ | '_| | '_ / _` |
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |___, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.5.0-SNAPSHOT)
2021-05-22 09:34:57.586 INFO 1 --- [ main] c.b.webmvc.WebmvcApplication : Starting WebmvcApplication using Java 1.8.0_292 on 3529ec458896 with PID 1 (/workspace/com.bolingcavalry.webmvc.WebmvcApplication started by cnb in /workspace)
2021-05-22 09:34:57.586 INFO 1 --- [ main] c.b.webmvc.WebmvcApplication : No active profile set, falling back to default profiles: default
2021-05-22 09:34:57.661 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
May 22, 2021 9:34:57 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-nio-8080"]
May 22, 2021 9:34:57 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service [Tomcat]
May 22, 2021 9:34:57 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet engine: [Apache Tomcat/9.0.46]
May 22, 2021 9:34:57 AM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring embedded WebApplicationContext
2021-05-22 09:34:57.669 INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 79 ms
May 22, 2021 9:34:57 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
2021-05-22 09:34:57.713 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-05-22 09:34:57.713 INFO 1 --- [ main] c.b.webmvc.WebmvcApplication : Started WebmvcApplication in 0.178 seconds (JVM running for 0.19)
2021-05-22 09:34:57.713 INFO 1 --- [ main] o.s.b.a.ApplicationAvailabilityBean : Application availability state LivenessState changed to CORRECT
2021-05-22 09:34:57.714 INFO 1 --- [ main] o.s.b.a.ApplicationAvailabilityBean : Application availability state ReadinessState changed to ACCEPTING_TRAFFIC

CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
6ce6c66fb4de jovial_hertz 0.11% 30.69MiB / 3.844GiB 0.78% 1.49kB / 158B 4.31MB / 0B 18
(base) zhaoqindeMacBook-Pro:~ zhaoqin$ docker run --rm -P docker.io/bolingcavalry/hellojib:0.0.1-SNAPSHOT
. ____ _ __ _ _
/\ / ___'_ __ _ _(_)_ __ __ _
( ( )___ | '_ | '_| | '_ / _` |
\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |___, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
2021-05-22 11:13:28.121 INFO 1 --- [ main] c.b.hellojib.HellojibApplication : Starting HellojibApplication on ffb32e5b68b9 with PID 1 (/app/classes started by root in /)
2021-05-22 11:13:28.128 INFO 1 --- [ main] c.b.hellojib.HellojibApplication : No active profile set, falling back to default profiles: default
2021-05-22 11:13:30.000 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2021-05-22 11:13:30.054 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2021-05-22 11:13:30.054 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.21]
2021-05-22 11:13:30.241 INFO 1 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2021-05-22 11:13:30.241 INFO 1 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2036 ms
2021-05-22 11:13:30.715 INFO 1 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2021-05-22 11:13:31.103 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2021-05-22 11:13:31.110 INFO 1 --- [ main] c.b.hellojib.HellojibApplication : Started HellojibApplication in 3.618 seconds (JVM running for 4.297)
2021-05-22 11:13:48.866 INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-05-22 11:13:48.866 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-05-22 11:13:48.880 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 14 ms
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
ffb32e5b68b9 eager_williamson 0.64% 356.3MiB / 3.844GiB 9.05% 3.46kB / 2.29kB 0B / 0B 31
6ce6c66fb4de jovial_hertz 0.11% 30.69MiB / 3.844GiB 0.78% 1.49kB / 158B 4.31MB / 0B 18
在实际操作过程中,经常会遇到maven插件或者docker镜像下载失败的情况,除了多试几次,您还可以考虑将项目放到github上去,借助github action在云端完成镜像构建
我是欣宸,期待与您一同畅游Java世界…
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/3356/viewspace-2796857/ ,如需转载,请注明出处,否则将追究法律责任。