使用graalVM,gradle,micronaut 开发一个简单的web请求,同时发布成一个单独的二进制文件。 感谢: 入门教程1 和 国内java资源下载 2:
安装
安装graalVM
由于暂时sdkman还没有对graalVM进行版本维护,因此手动下载graalvm-ce-java11-[os]-amd64.tar.gz
安装包并解压缩。
环境配置
设置环境变量~/.bashrc
export GRAALVM_HOME="$HOME/graalvm-ce-java11"
export JAVA_HOME="$GRAALVM_HOME"
export PATH="$JAVA_HOME/bin:$PATH"
$ source ~/.bashrc
设置完毕后,检查java环境
安装native-image插件
注意: graalvm无法交叉编译,在win/mac下打包的二进制文件无法运行于linux,一般采用docker pull镜像的方式解决
native-image
现在变为了graalVM
的一个插件,需要额外安装
# gu: graalvm update
$ gu install native-image
会自动安装于$GRAALVM_HOME/bin
目录下,设置完毕后,检查native-image
环境
安装gradle
使用sdkman
安装gradle
$ sdk insall gradle 6.5.1
这里大概率您会遇到网络环境问题,因此建议手动下载gradle
安装包,解压
$ sdk install gradle 6.5.1-local /your/pathof/gradle-6.5.1-bin
环境配置
设置环境变量~/.bashrc
export GRADLE_HOME="$HOME/.sdkman/candidates/gradle/current"
export GRADLE_USER_HOME="/your/pathof/gradleUser"
$ source ~/.bashrc
设置完毕后,检查gradle环境
$ gradle -v
设置aliyun源
创建文件~/.sdkman/candidates/gradle/6.5.1/init.d/build.gradle
allprojects {
repositories {
maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/google/' }
all { ArtifactRepository repo ->
if (repo instanceof MavenArtifactRepository) {
def url = repo.url.toString()
if (url.startsWith('https://repo.maven.apache.org/maven2/') ||
url.startsWith('https://repo.maven.org/maven2') ||
url.startsWith('https://repo1.maven.org/maven2') ||
url.startsWith('https://jcenter.bintray.com/') ||
url.startsWith('https://maven.google.com/') ||
url.startsWith('https://dl.google.com/dl/android/maven2/')) {
//project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."
remove repo
}
}
}
}
buildscript {
repositories {
maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/google/' }
all { ArtifactRepository repo ->
if (repo instanceof MavenArtifactRepository) {
def url = repo.url.toString()
if (url.startsWith('https://repo1.maven.org/maven2') ||
url.startsWith('https://jcenter.bintray.com/') ||
url.startsWith('https://dl.google.com/dl/android/maven2/')) {
//project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."
remove repo
}
}
}
}
}
}
安装Micronaut
命令行名为: mn
采用sdkman
安装,网络问题请自行解决或sdk local install的方式
$ sdk install micronaut
设置完毕后,检查mn环境
$ mn -V
至此,环境安装结束🍺
创建Micronaut项目
采用cli命令mn
,这里同样采用入门教程2的项目
$ mn create-app example.micronaut.demo
此命令会创建demo
文件夹
$ tree demo
这是一个中规中矩的java项目,build工具采用gradle,并且带了Dockerfile
部署文件,同时也一个micronaut-cli.yml
配置文件
个人习惯,不管三七二十一,先build一把,把相关的依赖包都拉取下来
$ cd demo
$ gradle clean build
Application.java
程序入口,类似springboot
的Application.java
编写一个controller
在src/main/java/example/micronaut
下创建packagecontrollers
,创建java文件controller/HelloController.java
package example.micronaut.controllers;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;
@Controller("/hello")
public class HelloController {
@Get
@Produces(MediaType.TEXT_PLAIN)
public String index() {
return "Hello Micronaut";
}
}
注解:
- @Controller: rest路径映射
- @Get: index()方法支持http get请求
- @Produces: 产生的结果类型,这里设置为普通文本型。默认为
MediaType.APPLICATION_JSON
编写单元测试
在src/test/java/example/micronaut
下创建packagecontrollers
,创建java文件controller/HelloControllerTest.java
package example.micronaut.controllers;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.client.RxHttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
@MicronautTest
public class HelloControllerTest {
@Inject
@Client("/")
RxHttpClient client;
@Test
public void testHello() {
HttpRequest<String> request = HttpRequest.GET("/hello");
String body = client.toBlocking().retrieve(request);
assertNotNull(body);
assertEquals("Hello Micronaut!", body);
}
}
注解:
- @MicronautTest: 初始化 Application Context 和 Embedded Server 内置服务
- @Inject: JSR330 标准注入注解,注入
RxHttpClient
的bean - @Client: 服务访问的根路径"/"
运行
单元测试:
$ gradle test
运行程序:
$ gradle run
默认端口:8080,访问
本地镜像Native-Image打包
again: graalVM目前不支持交叉编译
配置依赖包
项目的build.gradle
文件中增加依赖
// 注解处理器,生成 native-image 工具要使用的 reflection-config.json 元数据
annotationProcessor("io.micronaut:micronaut-graal")
// SVM(Substrate VM)虚拟机
compileOnly("org.graalvm.nativeimage:svm")
native-image相关配置
在src/main/resources
目录下创建META-INF/native-image
目录,再在其下创建目录:example/microunaut/micronautDemo
,里面创建文件native-image.properties
Args = -H:IncludeResources=logback.xml|application.yml \
-H:Name=micronautDemo \
-H:Class=example.micronaut.Application
- -H:IncludeResources: 指定允许包含的静态资源,可以使用正则表达式。这里为 logback.xml 和 application.yml。
- -H:Name: 指定生成的 Native Image 的名字,这里为 micronautDemo。
- -H:Class: 指定程序的入口(定义了 main() 方法的类)。这里为 example.micronaut.Application,即 Application.java 文件中的 main() 方法。
打包fat-jar
$ ./gradle assemble
在build/libs
下生成jar文件,我们需要那个比较大的demo-0.1-all.jar
文件
生成本地镜像
这一步时间会比较久,也比较耗资源
$ native-image --no-server -cp build/libs/demo-0.1-all.jar
生成完毕后得到
run it
$ chmod u+x ./micronautDemo
$ ./micronautDemo
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。