How to Create a Java Web Framework from Scratch, the Right Object-Oriented Way

The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:

你如何在Java中设计一个网页应用程序?你安装Spring,阅读手册,创建控制器,创建一些视图,添加一些注解,然后它就可以工作了。如果没有Spring(也没有Ruby中的Ruby on Rails,PHP中的Symphony等等),你会怎么做呢?让我们尝试从头开始创建一个网页应用程序,从纯Java SDK开始,最终得到一个完全功能的网页应用程序,并进行单元测试。我几周前录制了一个关于此的网络研讨会第42期,但这篇文章应该更详细地解释了所有内容。

首先,我们需要创建一个HTTP服务器,它将打开一个服务器套接字,监听传入的连接,读取它们所要说的一切(HTTP请求),并返回任何网页浏览器想要的信息(HTTP响应)。你知道HTTP是如何工作的,对吧?如果你不知道,这里有一个快速提醒:

网页浏览器向服务器发送请求,请求的格式如下(它是一段纯文本数据):

服务器必须读取该文本,准备答案(必须是浏览器可读的HTML页面),并以此方式返回。

就是这样。这是一个非常简单且我会说是原始的协议。在Java中实现一个Web服务器也并不那么复杂。以下是一个非常简化的形式:

尝试运行它,它应该可以工作。您应该能够在浏览器中打开 http://localhost:8080 页面并看到 Hello, world! 文本。

它还不是一个 Web 应用程序,只是一个框架,可以将 HTTP 请求分派到 HTTP 响应。尽管其中没有严格的面向对象编程,但它非常过程化,但确实有效。现在我们应该关注一个更重要的问题:如何向 Web 应用程序添加更多功能,使其能够处理不同页面、渲染更大的内容并处理错误?上述片段中的 request 变量应该以某种方式转换为 response

最简单的方法是:1)将请求转换为包含所有细节的 DTO,然后 2)将其发送到一个“控制器”,该控制器知道如何处理 DTO 的数据,然后 3)从控制器接收响应 DTO,提取数据并渲染响应。这就是 Spring 和大多数其他框架的工作方式。然而,我们不会选择这条路线,我们将尝试不使用 DTO,并完全面向对象。

我必须说,可能会有多种设计方式,都符合面向对象的风格。我现在只会展示其中一种选项。毫无疑问,您可能已经了解到我们的 Takes 框架,它诞生于几年前,它有自己的设计,也是面向对象的。但是我现在要建议的似乎更好。您也可能想出其他的方法,所以请随时在下方的评论中发布您的想法,甚至创建一个 GitHub 存储库并在那里分享您的思考。

我建议我们引入两个接口:ResourceOutputResource 是服务器端的实体,它会根据传入的请求参数进行变化。例如,当我们只知道请求是 GET / 时,它是一个资源。但是如果我们还知道请求有例如 Accept: text/plain,我们可以变异请求并创建一个新的请求,以提供纯文本。这是接口的定义:

以下是我们如何创建和突变它:

请注意:每次调用.refine()都会返回接口Resource的一个新实例。它们都是不可变的,就像对象必须是不可变的一样。由于这种设计,我们不会将数据与其处理器分离。资源即是数据,也是处理器。每个资源知道如何处理数据,并且只接收它应该接收的数据。从技术上讲,我们只是以面向对象的方式实现了请求分发

然后,我们需要将资源转换为响应。我们赋予资源将自己渲染到响应的能力。我们不希望数据以某种DTO形式逃离资源。我们希望资源打印响应。给资源增加一个额外的方法print()怎么样?

然后Output接口看起来像这样:

这是一个Output的原始实现:

构建一个HTTP响应,我们可以这样做:

现在让我们创建一个类,它将接收一个传入的请求字符串,并生成一个响应字符串,使用一个 Resource 的实例作为分发器

首先,我们解析请求,将其标头分成多行,并忽略请求的正文。您可以修改代码以解析正文并将其传递到refine()方法中,使用X-Body作为键。目前,上面的代码不会这样做。但是您有了这个想法。片段的解析部分准备了可以在请求中找到的键值对,并逐个将它们传递给封装的资源,对其进行变异直到达到最终形式。一个简单的资源,总是返回文本,可能看起来像这样:

一个关注查询字符串并根据查询路径将请求分发到其他资源的资源,可能如下所示:

我希望你明白了。上面的代码比较粗糙,大部分使用情景没有被实现,但如果你有兴趣的话,你可以自己去做。代码在yegor256/jpages存储库中。请毫不犹豫地提交拉取请求,让这个小框架变成现实。

Translated by ChatGPT gpt-3.5-turbo/42 on 2023-12-27 at 13:41

sixnines availability badge   GitHub stars