Java 18中简单 Web 服务器

从 Java 18 开始,我们可以访问JEP 408中引入的简单 Web 服务器。我们可以通过命令行工具和 API 访问其功能。

简单 Web 服务器提供了一个提供静态文件服务的基本 Web 服务器。它被描述为对于测试、原型设计和教育很有用。该服务器有意使其设置和运行非常简单,并不旨在与Apache Tomcat或Jetty等功能更齐全的选项竞争或取代。

引入该工具的目标之一是让开发人员以尽可能少的障碍启动并运行 Web 开发。

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/

运行上述配置会将我们的当前目录公开给网络上输出中给出的 IP 地址的任何人。虽然如果我们尝试传输文件,这可能很有用,但我们应该确保我们乐意首先共享它们。

API
使用简单 Web 服务器的第二个选项是 API。通过使用它,我们可以获得更多的控制权并自定义请求的处理方式。

首先,让我们使用 API 重新创建命令行 Web 服务器。

为此,我们将使用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();
}

这里我们使用 InetSocketAddress类指定了一个地址。我们还可以更改此处地址的其余部分,而不仅仅是端口。

然后,我们设置了一个 指向我们想要服务的目录的Path对象。

接下来,我们将这些作为参数以及日志记录级别传递给createFileServer()。和以前一样,我们可以配置其中任何一个来满足我们的需求。生成的 Web 服务器与使用命令行工具创建的 Web 服务器相同,可以通过我们的浏览器访问127.0.0.1:8080。

处理程序
显然,创建上面的服务器并没有比命令行工具提供任何好处。为了开始获得一些控制权,我们需要引入一个HttpHandler。

让我们看看向我们的服务器添加一个自定义的。我们可以使用SimpleFileServer的 另一种方法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");

仅当我们尝试访问 URL /test/allowed时,才会返回true。所有其他端点均失败。

我们现在可以使用 HttpHandlers.handleOrElse(),它接受我们的 谓词和两个选项。如果谓词通过,则执行第一个,否则执行第二个:

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

最后,我们可以像以前一样使用新的 HttpHandler设置HttpServer:

HttpServer server = SimpleFileServer.createFileServer(address, path, SimpleFileServer.OutputLevel.VERBOSE);
server.createContext("/test", handler);


结果是,导航到http://127.0.0.1:8080/test/allowed显示文本“ Welcome ”以及200响应。导航到任何其他路径都会显示“拒绝”并显示401响应。我们可以根据需要使用它来设置测试环境。然而,潜在的复杂性相当低。


过滤器
SimpleFileServer类的最后一个方面 是创建 Filter 的能力。该过滤器的作用是处理日志消息。通过定义我们自己的,我们可以将消息重定向到我们选择的OutputStream 。

应用Filter时,服务器的创建有所不同 。首先,让我们使用createOutputFilter()创建过滤器:

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


我们在这里使用 System.out作为OutputStream的简单示例 ,但我们也可以使用记录器或任何我们想要的东西。

接下来,我们将 HttpServer类中的create()方法 与我们刚刚创建的过滤器一起使用:

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

这里有一些争论,所以让我们来看看它们。首先,地址与以前一样采用InetSocketAddress的形式。其次,一个整数指定套接字积压。这是一次允许排队的最大 TCP 连接数。第三,我们有背景。在这里,我们指定要处理到达127.0.0.1:8080/test 的流量。第四个参数是HttpHandler,与我们之前创建的类似。最后是我们的过滤器作为第五个参数。

这提供了与我们之前使用处理程序时相同的功能。然而,我们现在可以完全控制日志输出。

结论
在本文中,我们看到我们可以快速启动 Java 18 的简单 Web 服务器,并且它提供了少量有用的功能。

首先,我们看到通过使用命令行工具jwebserver我们可以立即启动并运行服务器。该服务器提供对我们运行它的位置中的文件和子目录的读取访问权限。

接下来,我们查看了 API 和可用的新类,例如SimpleFileServer。使用此 API,我们可以实现与命令行工具相同的结果,但以编程方式实现。我们还可以使用HttpHandler 和Filter来扩展我们的控制。