百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

Java 的简单 Web 服务器:静态 HTTP 服务器变得简单

toyiye 2024-09-03 01:10 6 浏览 0 评论

Java 18 版本(2022 年 3 月)中包含的最方便的新功能之一是新的 Simple Web Server,它可以轻松启动和配置 HTTP 文件服务器。它还公开了一个 API,该 API 扩展了现有httpserver包以构建简单的用例。

新的 Simple Web Server 是一个有用的工具,每个 Java 开发人员都应该拥有它。让我们来看看!

目录

  • 命令行上的 Java 简单 Web 服务器
  • 使用 Java 的简单 Web 服务器 API
  • 从内存中提供虚拟文件系统
  • 快速、简单且灵活的 Web 服务器

命令行上的 Java 简单 Web 服务器

Java 的新jwebserver命令使运行基本 Web 服务器变得简单。它类似于Python世界中流行的SimpleHTTPServer工具。

第一步是确保您运行的是 Java 18 或更高版本。键入java --version以找出您当前正在运行的版本。我建议使用SDKMan来管理 JDK 安装。它对于处理多个版本特别有用。

jweb服务器基础知识

使用 Java Simple Web Server 可以做的最基本的事情是在端口 8000 上为当前目录提供服务。只需输入清单 1 中所示的命令即可。

清单 1. 无参数 Web 服务器


$ jwebserver

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

从那里,如果您转到浏览器并访问localhost:8000,您将看到文件系统的列表,如图 1 所示。

图 1. 在端口 8000 上运行的简单 Web 服务器实例。

配置命令行

您可能需要执行几项常见操作来在命令行上微调 Simple Web Server。例如,您可以更改端口、要绑定的地址(要侦听的网络接口)以及要提供服务的目录。

在清单 2 中,您可以看到如何侦听端口 8080、所有接口和目录/foo/bar

清单 2. 侦听端口 8080、所有接口、/foo/bar


$ jwebserver -b 0.0.0.0 -p 8081 -d /foo/bar

You can get a list of all the options with $ jwebserver -h.

正如您所看到的,jwebserver命令行工具可以使用最简单的语法来提供静态文件。接下来,我们将了解简单 Web 服务器 API。

使用 Java 的简单 Web 服务器 API

Simple Web Server Javadoc是学习 API 的一个很好的起点。该类SimpleFileServer存在于com.sun.net.httpserver包中。(这个包还包含用于构建 Web 服务器的较旧的、较低级别的 API。该httpserver包扩展了该功能以满足更简单的需求。)jwebserverCLI 工具用于SimpleFileServer完成其工作,我们也可以以编程方式使用它。

该类SimpleFileServer仅处理GETHTTP/1.1。不过,我们可以用它做一些有趣的事情。例如,本 关于使用 Simple Web Server 的介绍建议了一种使用 Google Java 内存中文件系统项目为处理程序伪造文件系统的方法。

我们将使用内存中文件系统的思想来修改 inFileHandlerSimpleFileServer实际为内存中的虚拟文件系统提供服务。然后,我们将使用该httpserver包来处理POST将人造文件添加到人造文件系统中。

从内存中提供虚拟文件系统

首先,让我们使用以下命令创建一个快速 Maven 项目:


$ mvn archetype:generate -DgroupId=.com.infoworld -DartifactId=jsws -DarchetypeArtifactId=maven-archetype-quickstart

现在,CD 进入新/jsws目录。

18在 pom.xml 中设置编译器和源版本,如此处所述。

接下来,将 Google 添加jimfs到依赖项中,如清单 3 所示。

清单 3. Google Java 内存中文件系统依赖项


<dependency>
  <groupId>com.google.jimfs</groupId>
  <artifactId>jimfs</artifactId>
  <version>1.3.0</version>
</dependency>

现在,我们可以修改该src/main/java/App.java文件以服务于假文件系统。您可以在清单 4 中看到执行此操作的代码。

清单 4. 使用 SimpleFileServer 为内存中文件系统提供服务


package com.infoworld;

import java.util.List;
import java.nio.charset.StandardCharsets;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import com.sun.net.httpserver.SimpleFileServer;

import static com.sun.net.httpserver.SimpleFileServer.OutputLevel;

public class Mem {
  private static final InetSocketAddress ADDR =
    new InetSocketAddress("0.0.0.0", 8080);

  public static void main( String[] args ) throws Exception {
    Path root = createDirectoryHierarchy();
    var server = SimpleFileServer.createFileServer(ADDR, root, OutputLevel.VERBOSE);
    server.start();
  }

  private static Path createDirectoryHierarchy() throws IOException {
    FileSystem fs = Jimfs.newFileSystem(Configuration.unix());
    Path root = fs.getPath("/");

    Files.createDirectories(root.resolve("test/test2"));

    Path foo = fs.getPath("/foo");
    Files.createDirectory(foo);

    Path hello = foo.resolve("hello.txt"); 
    Files.write(hello,  List.of("hello", "world"), StandardCharsets.UTF_8);

    return root;
  }
}

清单 4 中的想法是使用Google 的开源 jimfs 库来模拟标准本地文件系统 API ,该库实现了java.nio.fileAPI,但在内存中执行所有操作,就像虚拟文件系统一样。使用该库,您可以通过编程方式定义自己的目录路径和文件。因此,我们创建自己的虚拟目录结构并将其作为SimpleFileServer文件处理程序。

我们SimpleFileServer以编程方式配置该类:


var server = SimpleFileServer.createFileServer(ADDR, root, OutputLevel.VERBOSE);

这接受要绑定的互联网地址,就像我们从命令行看到的那样。在本例中,我们传入未指定的接口和端口 8080。之后是文件系统根。对于这个例子,我们将给它Path由我们的createDirectoryHierarchy()方法创建的对象。

createDirectoryHierarchy()方法用于jimfs构建一个Path对象:FileSystem fs = Jimfs.newFileSystem(Configuration.unix());Path然后它用文件和目录填充。用于创建路径和包含内容的文件的APIjimfs并不难掌握;例如,我们创建一个带有Path hello = foo.resolve("hello.txt");. 您可以使用大多数对象,就像它们只是普通的 Java NIO 路径一样。

现在,如果我们运行此代码并访问localhost:8080,您将看到目录列表,并且能够浏览它并查看文件内容,就像使用普通文件服务器一样。

创建虚拟文件

让我们将这个想法更进一步,添加上传新文件的功能。我们可以使用该com.sun.net.httpserver包接受POST将新文件上传到内存文件系统的请求。您可以在清单 5 中看到这一点。

清单 5. 将新文件上传到内存文件系统


package com.infoworld;

import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpExchange;

import java.io.IOException;
import java.io.OutputStream;

import java.net.InetSocketAddress;
import java.util.List;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import com.sun.net.httpserver.SimpleFileServer;

import static com.sun.net.httpserver.SimpleFileServer.OutputLevel;

public class App {
  public static void main( String[] args ) throws Exception {
    // same config...
    server.start();

    // Create the HTTP server with the UploadHandler using the same 'root' path
    HttpServer httpServer = HttpServer.create(new InetSocketAddress("0.0.0.0", 8081), 0);
    httpServer.createContext("/upload", new UploadHandler(root));
    httpServer.start();
  }

  private static Path createDirectoryHierarchy() throws IOException {
    // same ...
  }

  // Handler to process POST requests and upload files
  static class UploadHandler implements HttpHandler {
    private final Path root;

    public UploadHandler(Path root) {
      this.root = root;
    }

    @Override
       public void handle(HttpExchange exchange) throws IOException {
       if ("POST".equalsIgnoreCase(exchange.getRequestMethod())) {
         String filename = exchange.getRequestHeaders().getFirst("filename");

         if (filename != null) {
           Path newFilePath = root.resolve(filename);
          try (OutputStream os = Files.newOutputStream(newFilePath)) {
            exchange.getRequestBody().transferTo(os);
          }
          String response = "File uploaded successfully: " + filename;
          exchange.sendResponseHeaders(200, response.getBytes(StandardCharsets.UTF_8).length);
          try (OutputStream os = exchange.getResponseBody()) {              
            os.write(response.getBytes(StandardCharsets.UTF_8));
          }
        } else {
          exchange.sendResponseHeaders(400, -1); // Bad Request
        }
      } else {
        exchange.sendResponseHeaders(405, -1); // Method Not Allowed
      }
    }
  }
}

在清单 5 中,我们保持类的大部分内容相同,但在 HttpServer侦听端口 8081 的实例上。这是使用我们的自定义配置的uploadHandler,它获取上传的数据并使用它将新文件写入我们在中创建的根路径createDirectoryHierarchy

为了测试这一点,我们可以使用以下命令运行整个服务器集群:


$ mvn clean install exec:java -Dexec.mainClass="com.infoworld.Mem"

您可以使用 CURL 请求将新文件推送到服务器,如清单 6 中所示。

清单 6. CURL POST 文件


$ touch file.txt
$ curl -X POST -H "filename: file.txt" -d "@file.txt" http://localhost:8081/upload

File uploaded successfully: file.txt

当您重新加载localhost:8080/文件列表时,您将看到新的文件列表file.txt,您可以单击它并查看其内容。

快速、简单且灵活的 Web 服务器

Simple Web Server 是 Java 工具集中受欢迎的补充。它不仅使 CLI 托管文件变得非常简单,而且还通过其 API 引入了一些有趣的可能性,特别是与较低级别的HttpServerAPI 结合使用时。

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码