如何使用Java 18的简单Web 服务器

22-04-19 banq

Java 18 的简单 Web 服务器是在JEP 408中添加到jdk.httpserver模块的最小 HTTP 静态文件服务器。它服务于单个目录层次结构,并且仅服务于 HTTP/1.1 上的静态文件;不支持动态内容和其他 HTTP 版本。

Web 服务器的规范以使 JDK 更易于使用的总体目标为依据。该服务器是一种开箱即用的工具,具有简单的设置和最少的功能,可让您立即开始运行并专注于手头的任务。简单的设计还避免了与功能丰富或商业级服务器的任何混淆——毕竟,生产环境存在更好的替代方案,而在这种情况下,简单 Web 服务器不是正确的选择。相反,该服务器在原型设计、即席编码和测试环境中大放异彩。

服务器只支持HEAD和GET请求方法;任何其他请求都会收到501 - 未实施或405 - 不允许的响应。HEAD和GET请求的处理方式如下。
  • 如果请求的资源是一个文件,其内容将被提供。
  • 如果请求的资源是一个带有索引文件的目录,那么将提供索引文件的内容。
  • 否则,将返回目录列表。


命令行:

jwebserver [-b bind address] [-p port] [-d directory]
           [-o none|info|verbose] [-h to show options]
           [-version to show version information]



每个选项都有短版和长版,还有常规的选项用于打印帮助信息和版本信息。下面是一些用法选项。
  • -h 或 -? 或 --help。打印帮助信息并退出。
  • -b addr 或 --bind-address addr:指定要绑定的地址。默认是127.0.0.1或::1(回环)。对于所有接口,使用-b 0.0.0.0或-b ::。
  • -d dir 或 --directory dir。指定要服务的目录。默认是当前目录。
  • -o level 或 --output level。指定输出格式。级别有无、信息和粗略的。缺省是info。
  • -p port或--port端口。指定要监听的端口。默认值是8000。
  • --version或--version。打印简单网络服务器的版本信息并退出。


启动服务器
下面的命令启动简单网络服务器。

$ jwebserver

默认情况下,服务器会绑定到环回地址和8000端口,并为当前工作目录提供服务。如果启动成功,服务器会在前台运行,并向System.out打印一条信息,列出本地地址和被服务目录的绝对路径,如/cwd。举例来说:

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



配置服务器
你可以通过使用相应的选项来改变默认配置。例如,下面是如何将简单网络服务器绑定到所有的接口上。

$ jwebserver -b 0.0.0.0
Serving /cwd and subdirectories on 0.0.0.0 (all interfaces) port 8000
URL http://123.456.7.891:8000/


停止服务器
一旦启动成功,简单网络服务器就会一直运行,直到被停止。在UNIX平台上,可以通过向其发送SIGINT信号来停止服务器,这可以通过在终端窗口按Ctrl+C来实现。

上面关于如何启动、配置和停止服务器的描述捕捉了jwebserver的全部功能。该服务器是最小的,但又是可配置的,足以涵盖Web开发和Web服务测试中的常见用例,以及跨系统的文件共享或浏览。

虽然jwebserver工具在很多情况下都很方便,但如果你想用现有的代码来使用简单网络服务器的组件或进一步定制它们呢?这就是一组新的API点出现的地方。

处理程序
现在,服务器组件可以很容易地被检索到,简单网络服务器团队希望加强现有的com.sun.net.httpserver API的可组合性。特别是该团队在创建和组合处理程序方面加倍努力,这些处理程序是请求处理逻辑的核心。

为此,团队引入了HttpHandlers类,它有两个新方法。

  1. HttpHandlers::of返回一个具有固定状态的预制响应处理程序,即一个状态代码、一组头文件和一个响应体。
  2. HttpHandlers::handleOrElse在一个条件上结合两个处理程序。

下面是一个关于如何使用它们的例子。

jshell> Predicate<Request> IS_GET = r -> r.getRequestMethod().equals("GET");

jshell> var jsonHandler = HttpHandlers.of(200, 
   ...> Headers.of("Content-Type", "application/json"),
   ...> Files.readString(Path.of("some.json")));

jshell> var notAllowedHandler = HttpHandlers.of(405, Headers.of("Allow", "GET"), "");

jshell> var handler = HttpHandlers.handleOrElse(IS_GET, jsonHandler, notAllowedHandler);


在上面的例子中,jsonHandler是一个预制的响应处理程序,它总是返回200的状态代码、给定的头和给定的JSON文件的内容作为响应体。另一方面,notAllowedHandler总是返回一个405响应。基于谓词,组合处理程序检查传入请求的请求方法,并将请求转发给适当的处理程序。

总的来说,这两个新方法是一个整齐的组合,用于编写定制的请求处理逻辑,因此,它们可以帮助你解决各种测试和调试的情况。

调整请求状态
说到测试和调试,还有一些时候,你可能想在处理一个请求之前检查并可能调整它的某些属性。

为了支持这一点,你可以使用Filter.adaptRequest,这是一个返回预处理过滤器的方法,可以读取并选择性地改变一个请求的URI、方法或头文件。

jshell> var filter = Filter.adaptRequest("Add Foo header", 
   ...> request -> request.with("Foo", List.of("Bar"))); 
jshell> var server = HttpServer.create(new InetSocketAddress(8080), 10, "/", someHandler, 
   ...> filter); 
jshell> server.start();


在上面的例子中,过滤器在someHandler开始工作之前给每个传入的请求添加一个Foo头。这个功能使我们能够直接调整和扩展现有的处理程序。

 

猜你喜欢