有时我们需要做一个很简单的Http Rest API,但是不想使用Spring Boot过重的框架,其依赖包太多,这里展示在在Docker中使用Java运行API端点其实并不需要这些框架,只要一个依赖包就好,非常轻量。
实际上,我们只使用单个库作为依赖: HttpMate核心 。对于此示例,我们将使用 HttpMate的LowLevel构建器和 单个HTTP处理程序。
本例中使用的环境
最终结果可以在 这个git repo中找到 。
组织项目
让我们创建我们的初始项目结构:
mkdir -p simple-java-http-docker/src/main/java/com/envimate/examples/http
pom文件:
<project xmlns:xsi=<font>"http://www.w3.org/2001/XMLSchema-instance"</font><font> xmlns=</font><font>"http://maven.apache.org/POM/4.0.0"</font><font> xsi:schemaLocation=</font><font>"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"</font><font>> <modelVersion>4.0.0</modelVersion> <groupId>com.envimate.examples</groupId> <artifactId>simple-java-http-docker</artifactId> <version>0.0.1</version> <dependencies> <dependency> <groupId>com.envimate.httpmate</groupId> <artifactId>core</artifactId> <version>1.0.21</version> </dependency> </dependencies> </project> </font>
在这里:
这足以在选择的IDE中开始开发我们的API端点。其中大多数都支持基于Maven的Java项目。
应用程序入口点
要启动我们的小服务器,我们将使用一个简单的main方法。让我们将应用程序的条目创建为Application.java目录src/main/java/com/envimate/examples/http中的文件,现在只需将时间输出到控制台。
<b>public</b> <b>final</b> <b>class</b> Application { <b>public</b> <b>static</b> <b>void</b> main(String[] args) { <b>final</b> LocalDateTime time = LocalDateTime.now(); <b>final</b> String dateFormatted = time.format(DateTimeFormatter.ISO_TIME); System.out.println(<font>"current time is "</font><font> + dateFormatted); } } </font>
尝试运行此类,您将看到打印的当前时间。
将打印出时间的部分分离成一个没有参数的lambda函数:Supplier
<b>public</b> <b>final</b> <b>class</b> Application { <b>public</b> <b>static</b> <b>void</b> main(String[] args) { Supplier handler = () -> { <b>final</b> LocalDateTime time = LocalDateTime.now(); <b>final</b> String dateFormatted = time.format(DateTimeFormatter.ISO_TIME); <b>return</b> <font>"current time is "</font><font> + dateFormatted; }; System.out.println(handler.get()); } } </font>
低级HttpMate提供的便利界面看起来并没有太大的不同,除了返回一个String,String设置为响应,以及一切顺利的指示(也就是响应代码200)。
<b>final</b> HttpHandler httpHandler = (request, response) -> { <b>final</b> LocalDateTime time = LocalDateTime.now(); <b>final</b> String dateFormatted = time.format(DateTimeFormatter.ISO_TIME); response.setStatus(200); response.setBody(<font>"current time is "</font><font> + dateFormatted); }; </font>
HttpMate还提供了一个简单的Java HttpServer包装器 - PureJavaEndpoint它允许您在没有任何进一步依赖的情况下启动端点。
我们需要做的就是给它HttpMate的实例:
<b>import</b> com.envimate.httpmate.HttpMate; <b>import</b> com.envimate.httpmate.convenience.endpoints.PureJavaEndpoint; <b>import</b> com.envimate.httpmate.convenience.handler.HttpHandler; <b>import</b> java.time.LocalDateTime; <b>import</b> java.time.format.DateTimeFormatter; <b>import</b> <b>static</b> com.envimate.httpmate.HttpMate.anHttpMateConfiguredAs; <b>import</b> <b>static</b> com.envimate.httpmate.LowLevelBuilder.LOW_LEVEL; <b>public</b> <b>final</b> <b>class</b> Application { <b>public</b> <b>static</b> <b>void</b> main(String[] args) { <b>final</b> HttpHandler httpHandler = (request, response) -> { <b>final</b> LocalDateTime time = LocalDateTime.now(); <b>final</b> String dateFormatted = time.format(DateTimeFormatter.ISO_TIME); response.setStatus(200); response.setBody(<font>"current time is "</font><font> + dateFormatted); }; <b>final</b> HttpMate httpMate = anHttpMateConfiguredAs(LOW_LEVEL) .get(</font><font>"/time"</font><font>, httpHandler) .build(); PureJavaEndpoint.pureJavaEndpointFor(httpMate).listeningOnThePort(1337); } } </font>
请注意/time,当使用方法GET调用时,我们已将httpHandler配置为提供路径。
客户端访问测试:
curl http://localhost:1337/time
current time is 15:09:34.458756
在我们将这个全部放入Dockerfile之前,我们需要将它打包为一个jar。
建立JAR
我们需要两个maven插件: maven-compiler-plugin 和 maven-assembly-plugin 来构建可执行jar。
<?xml version=<font>"1.0"</font><font> encoding=</font><font>"UTF-8"</font><font>?> <project xmlns:xsi=</font><font>"http://www.w3.org/2001/XMLSchema-instance"</font><font> xmlns=</font><font>"http://maven.apache.org/POM/4.0.0"</font><font> xsi:schemaLocation=</font><font>"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"</font><font>> <modelVersion>4.0.0</modelVersion> <groupId>com.envimate.examples</groupId> <artifactId>simple-java-http-docker</artifactId> <version>0.0.1</version> <dependencies> <dependency> <groupId>com.envimate.httpmate</groupId> <artifactId>core</artifactId> <version>1.0.21</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <release>${java.version}</release> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <phase><b>package</b></phase> <goals> <goal>single</goal> </goals> <configuration> <archive> <manifest> <mainClass> com.envimate.examples.http.Application </mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </execution> </executions> </plugin> </plugins> </build> </project> </font>
构建我们的jar:
mvn clean verify
并运行生成的jar:
java -jar target/simple-java-http-docker-0.0.1-jar-with-dependencies.jar
放入Docker容器
Dockerfile看起来很简单:
FROM openjdk:12 ADD target/simple-java-http-docker-0.0.1-jar-with-dependencies.jar /opt/application.jar EXPOSE 1337 ENTRYPOINT exec java -jar /opt/application.jar
它指定
要构建和标记我们的docker镜像,我们从目录的根目录运行以下命令:
docker build --tag simple-java-http-docker .
这将生成我们可以运行的docker镜像:
docker run --publish 1337:1337 simple-java-http-docker
访问测试:
curl http://localhost:1337/time
current time is 15:23:04.275515
结论
当然,这是一个简化的例子,我们写的端点并不完全有用。它证明了你不需要大量的库只是为了拥有一个正在运行的HTTP端点,包装一个可运行的jar是多么容易,使用docker和你的java应用程序以及低级HttpMate的基本用法。