使用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环境
image.png

安装native-image插件

注意: graalvm无法交叉编译,在win/mac下打包的二进制文件无法运行于linux,一般采用docker pull镜像的方式解决

native-image现在变为了graalVM的一个插件,需要额外安装

# gu: graalvm update
$ gu install native-image

会自动安装于$GRAALVM_HOME/bin目录下,设置完毕后,检查native-image环境
image.png

安装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

image.png
这是一个中规中矩的java项目,build工具采用gradle,并且带了Dockerfile部署文件,同时也一个micronaut-cli.yml配置文件
个人习惯,不管三七二十一,先build一把,把相关的依赖包都拉取下来

$ cd demo
$ gradle clean build

Application.java

程序入口,类似springbootApplication.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,访问
image.png

本地镜像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
image.png

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文件
image.png

生成本地镜像

这一步时间会比较久,也比较耗资源

$ native-image --no-server -cp build/libs/demo-0.1-all.jar

生成完毕后得到

run it

$ chmod u+x ./micronautDemo
$ ./micronautDemo

image.png


  1. 给新手看的 Micronaut 入门教程
  2. 爪哇我话你知

李绍川
1 声望0 粉丝