有时我们需要做一个很简单的Http Rest API,但是不想使用Spring Boot过重的框架,其依赖包太多,这里展示在在Docker中使用Java运行API端点其实并不需要这些框架,只要一个依赖包就好,非常轻量。
实际上,我们只使用单个库作为依赖:HttpMate核心。对于此示例,我们将使用HttpMate的LowLevel构建器和单个HTTP处理程序。
本例中使用的环境
- Java 11+
- Maven 3.5+
- Java友好的IDE
- Docker版本18+
- 基本了解HTTP / bash / Java
最终结果可以在这个git repo中找到。
组织项目
让我们创建我们的初始项目结构:
mkdir -p simple-java-http-docker/src/main/java/com/envimate/examples/http
|
pom文件:
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <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>
|
在这里:
- 我们项目的标准groupId / artifactId / version定义
- 对HttpMate核心库的单一依赖
这足以在选择的IDE中开始开发我们的API端点。其中大多数都支持基于Maven的Java项目。
应用程序入口点
要启动我们的小服务器,我们将使用一个简单的main方法。让我们将应用程序的条目创建为Application.java目录src/main/java/com/envimate/examples/http中的文件,现在只需将时间输出到控制台。
public final class Application { public static void main(String[] args) { final LocalDateTime time = LocalDateTime.now(); final String dateFormatted = time.format(DateTimeFormatter.ISO_TIME); System.out.println("current time is " + dateFormatted); } }
|
尝试运行此类,您将看到打印的当前时间。
将打印出时间的部分分离成一个没有参数的lambda函数:Supplier
public final class Application { public static void main(String[] args) { Supplier handler = () -> { final LocalDateTime time = LocalDateTime.now(); final String dateFormatted = time.format(DateTimeFormatter.ISO_TIME); return "current time is " + dateFormatted; };
System.out.println(handler.get()); } }
|
低级HttpMate提供的便利界面看起来并没有太大的不同,除了返回一个String,String设置为响应,以及一切顺利的指示(也就是响应代码200)。
final HttpHandler httpHandler = (request, response) -> { final LocalDateTime time = LocalDateTime.now(); final String dateFormatted = time.format(DateTimeFormatter.ISO_TIME);
response.setStatus(200); response.setBody("current time is " + dateFormatted); };
|
HttpMate还提供了一个简单的Java HttpServer包装器 - PureJavaEndpoint它允许您在没有任何进一步依赖的情况下启动端点。
我们需要做的就是给它HttpMate的实例:
import com.envimate.httpmate.HttpMate; import com.envimate.httpmate.convenience.endpoints.PureJavaEndpoint; import com.envimate.httpmate.convenience.handler.HttpHandler;
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter;
import static com.envimate.httpmate.HttpMate.anHttpMateConfiguredAs; import static com.envimate.httpmate.LowLevelBuilder.LOW_LEVEL;
public final class Application { public static void main(String[] args) { final HttpHandler httpHandler = (request, response) -> { final LocalDateTime time = LocalDateTime.now(); final String dateFormatted = time.format(DateTimeFormatter.ISO_TIME);
response.setStatus(200); response.setBody("current time is " + dateFormatted); };
final HttpMate httpMate = anHttpMateConfiguredAs(LOW_LEVEL) .get("/time", httpHandler) .build(); PureJavaEndpoint.pureJavaEndpointFor(httpMate).listeningOnThePort(1337); } }
|
请注意/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="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <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>package</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>
|
构建我们的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
|
它指定
- FROM:用作基础的图像。我们将使用openjdk图像。
- ADD:我们想要的jar我们想要的目录
- EXPOSE:我们正在收听的端口
- ENTRYPOINT:对于命令,我们要执行
要构建和标记我们的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的基本用法。