1. 概述

Java 18 引入了简易 Web 服务器(Simple Web Server),这是通过 JEP 408 实现的新特性。我们可以通过命令行工具和 API 两种方式使用它。

这个服务器专门用于提供静态文件服务,官方描述其适用于测试、原型开发和教学场景。它被设计得极其简单易用,不打算与 Apache Tomcat 或 Jetty 等功能完备的服务器竞争。

引入该工具的核心目标是:让开发者以最低门槛快速上手 Web 开发

本文将深入解析简易 Web 服务器的工作原理和使用方式。

2. jwebserver 命令行工具

2.1. 启动服务

最简单的启动方式就是使用内置的命令行工具 jwebserver直接执行 jwebserver 命令即可启动服务器

$ jwebserver         
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /usr and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/

⚠️ 默认情况下,服务器会提供当前目录(示例中是 /usr)的文件服务。我们可以通过 -d 参数指定其他目录:

$ jwebserver -d /opt
Binding to loopback by default. For all interfaces use "-b 0.0.0.0" or "-b ::".
Serving /opt and subdirectories on 127.0.0.1 port 8000
URL http://127.0.0.1:8000/

注意:必须使用绝对路径。

我们还可以通过 -p-b 参数修改端口和绑定地址:

$ jwebserver -b 0.0.0.0 -p 3003    
Serving / and subdirectories on 0.0.0.0 (all interfaces) port 3003
URL http://192.168.1.1:3003/

踩坑提醒:这种配置会暴露当前目录到整个网络,文件传输前务必确认安全性!

2.2. GET 请求处理

通过浏览器访问指定地址和端口即可使用服务。我们会看到启动目录下的文件和子目录列表:

目录列表

访问文件时,浏览器会显示内容,同时终端输出日志:

127.0.0.1 - - [09/Feb/2024:12:06:26 +0000] "GET /file.txt HTTP/1.1" 200 -

进入子目录时也会记录相应日志:

127.0.0.1 - - [09/Feb/2024:12:06:52 +0000] "GET /subdirectory/ HTTP/1.1" 200 -

3. API 编程接口

3.1. 定义服务器

用 API 重现命令行功能需要用到 SimpleFileServer 类。该类提供三个核心功能

  • 创建 HttpServer
  • 创建 HttpHandler
  • 创建 HttpFilter

通过 createFileServer() 快速创建服务器:

public static void main(String[] args) {
    InetSocketAddress address = new InetSocketAddress(8080);
    Path path = Path.of("/");
    HttpServer server = SimpleFileServer.createFileServer(address, path, SimpleFileServer.OutputLevel.VERBOSE);
    server.start();
}

关键参数说明:

  1. InetSocketAddress 指定监听地址和端口
  2. Path 指定服务目录
  3. 日志级别可按需调整

效果与命令行工具完全一致,可通过 127.0.0.1:8080 访问。

3.2. 请求处理器

要实现更复杂的控制,需要引入 HttpHandler通过 createFileHandler() 创建处理器

HttpHandler handler = SimpleFileServer.createFileHandler(Path.of("/Users"));
server.createContext("/test", handler);

这样所有访问 127.0.0.1:8080/test 的请求都会经过这个处理器。

进阶用法:模拟不同接口的权限控制。用 HttpHandlers.of() 创建响应:

HttpHandler allowedResponse = HttpHandlers.of(200, Headers.of("Allow", "GET"), "Welcome");
HttpHandler deniedResponse = HttpHandlers.of(401, Headers.of("Deny", "GET"), "Denied");

定义路径判断逻辑:

Predicate<Request> findAllowedPath = r -> r.getRequestURI()
  .getPath().equals("/test/allowed");

handleOrElse() 组装处理器:

HttpHandler handler = HttpHandlers.handleOrElse(findAllowedPath, allowedResponse, deniedResponse);

最终效果:

  • 访问 http://127.0.0.1:8080/test/allowed → 返回 200 和 "Welcome"
  • 其他路径 → 返回 401 和 "Denied"

3.3. 过滤器

SimpleFileServer 还支持创建 Filter 来处理日志输出。通过自定义过滤器,我们可以将日志重定向到任意 OutputStream

创建过滤器:

Filter filter = SimpleFileServer.createOutputFilter(System.out, SimpleFileServer.OutputLevel.INFO);

✅ 这里用 System.out 演示,实际可替换为日志系统等。

创建服务器时绑定过滤器:

HttpServer server = HttpServer.create(new InetSocketAddress(8080), 10, "/test", handler, filter);

参数解析:

  1. 监听地址(InetSocketAddress
  2. TCP 连接队列最大长度(10)
  3. 处理路径(/test
  4. 请求处理器(handler
  5. 日志过滤器(filter

核心优势:完全掌控日志输出流向,比命令行工具更灵活。

4. 总结

本文展示了 Java 18 简易 Web 服务器的核心能力:

✅ **命令行工具 jwebserver**:

  • 秒级启动静态文件服务
  • 支持自定义端口、目录和绑定地址
  • 适合快速原型和文件共享

编程接口

  • 通过 SimpleFileServer 实现相同功能
  • HttpHandler 实现请求路由和权限控制
  • Filter 灵活管理日志输出

适用场景

  • 本地开发测试
  • 教学演示
  • 简单静态文件服务
  • API 原型验证

⚠️ 局限性:不适合生产环境,功能远不如 Tomcat/Jetty 完备。

完整示例代码见 GitHub 仓库