Skip to content

从 Express 迁移到 Ktor

从 Express 迁移到 Ktor

在本指南中,我们将了解在基本场景下如何将 Express 应用程序迁移到 Ktor:从生成应用程序和编写第一个应用程序,到创建用于扩展应用程序功能的中间件。

生成应用

Express

你可以使用 express-generator 工具生成一个新的 Express 应用程序:

shell
Ktor

Ktor 提供了以下方式来生成应用程序骨架:

有关详细说明,请参阅

创建、打开并运行新的 Ktor 项目
了解如何使用 Ktor 打开、运行和测试服务器应用程序。
教程。

Hello world

在本节中,我们将了解如何创建最简单的服务器应用程序,该程序接受 GET 请求并响应预定义的纯文本。

Express

下面的示例展示了启动服务器并侦听端口 3000 连接的 Express 应用程序。

javascript

有关完整示例,请参阅 1_hello 项目。

Ktor

在 Ktor 中,你可以使用 embeddedServer 函数在代码中配置服务器参数并快速运行应用程序。

kotlin

有关完整示例,请参阅 1_hello 项目。

你还可以在使用 HOCON 或 YAML 格式的 外部配置文件 中指定服务器设置。

请注意,上述 Express 应用程序添加了 DateX-Powered-ByETag 响应头,其内容可能如下所示:

要在 Ktor 的每个响应中添加默认的 ServerDate 标头,你需要安装

DefaultHeaders
所需依赖项:io.ktor:%artifact_name%
插件。
ConditionalHeaders
所需依赖项:io.ktor:%artifact_name%
插件可用于配置 Etag 响应头。

提供静态内容

在本节中,我们将了解如何在 Express 和 Ktor 中提供静态文件,例如图像、CSS 文件和 JavaScript 文件。假设我们有一个包含主 index.html 页面和一组链接资产的 public 文件夹。

Express

在 Express 中,将文件夹名称传递给 express.static 函数。

javascript

有关完整示例,请参阅 2_static 项目。

Ktor

在 Ktor 中,使用 staticFiles() 函数将对 / 路径发出的任何请求映射到 public 物理文件夹。此函数可以递归地提供 public 文件夹中的所有文件。

kotlin

有关完整示例,请参阅 2_static 项目。

提供静态内容时,Express 会添加多个响应头,如下所示:

要在 Ktor 中管理这些标头,你需要安装以下插件:

  • Accept-Ranges

    PartialContent
    所需依赖项:io.ktor:%artifact_name% 服务器示例:download-file,客户端示例:client-download-file-range

  • Cache-Control

    CachingHeaders
    所需依赖项:io.ktor:%artifact_name%

  • ETagLast-Modified

    ConditionalHeaders
    所需依赖项:io.ktor:%artifact_name%

路由

路由
路由是服务器应用程序中处理传入请求的核心插件。
允许处理发送到特定端点的传入请求,该端点由特定的 HTTP 请求方法(GETPOST 等)和路径定义。下面的示例展示了如何处理发送到 / 路径的 GETPOST 请求。

Express
javascript

有关完整示例,请参阅 3_router 项目。

Ktor
kotlin

TIP

请参阅 接收请求,了解如何接收 POSTPUTPATCH 请求的请求体。

有关完整示例,请参阅 3_router 项目。

以下示例演示了如何按路径对路由处理程序进行分组。

Express

在 Express 中,你可以使用 app.route() 为路由路径创建可链式调用的路由处理程序。

javascript

有关完整示例,请参阅 3_router 项目。

Ktor

Ktor 提供了一个 route 函数,通过该函数你可以定义路径,然后将该路径的动作(动词)作为嵌套函数放置。

kotlin

有关完整示例,请参阅 3_router 项目。

这两个框架都允许你在单个文件中对相关路由进行分组。

Express

Express 提供了 express.Router 类来创建可挂载的路由处理程序。假设在应用程序目录中有一个 birds.js 路由文件。这个路由模块可以像 app.js 中所示的那样加载到应用程序中:

javascript
javascript

有关完整示例,请参阅 3_router 项目。

Ktor

在 Ktor 中,一种常见的模式是在 Routing 类型上使用扩展函数来定义实际路由。下面的示例(Birds.kt)定义了 birdsRoutes 扩展函数。通过在 routing 块内调用此函数,你可以在应用程序(Application.kt)中包含相应的路由:

kotlin
kotlin

有关完整示例,请参阅 3_router 项目。

除了将 URL 路径指定为字符串外,Ktor 还包含实现

类型安全路由
Resources 插件允许你实现类型安全路由。
的功能。

路由参数与查询参数

本节将展示如何访问路由参数和查询参数。

路由(或路径)参数是命名的 URL 段,用于捕获 URL 中其所在位置指定的值。

Express

要在 Express 中访问路由参数,你可以使用 Request.params。例如,对于 /user/admin 路径,下面代码片段中的 req.parameters["login"] 将返回 admin

javascript

有关完整示例,请参阅 4_parameters 项目。

Ktor

在 Ktor 中,路由参数使用 {param} 语法定义。你可以在路由处理程序中使用 call.parameters 来访问路由参数:

kotlin

有关完整示例,请参阅 4_parameters 项目。

下表比较了如何访问查询字符串的参数。

Express

要在 Express 中访问路由参数,你可以使用 Request.params。例如,对于 /user/admin 路径,下面代码片段中的 req.parameters["login"] 将返回 admin

javascript

有关完整示例,请参阅 4_parameters 项目。

Ktor

在 Ktor 中,路由参数使用 {param} 语法定义。你可以在路由处理程序中使用 call.parameters 来访问路由参数:

kotlin

有关完整示例,请参阅 4_parameters 项目。

发送响应

在前面的章节中,我们已经了解了如何响应纯文本内容。下面让我们看看如何发送 JSON、文件和重定向响应。

JSON

Express

要在 Express 中发送具有适当内容类型的 JSON 响应,请调用 res.json 函数:

javascript

有关完整示例,请参阅 5_send_response 项目。

Ktor

在 Ktor 中,你需要安装

ContentNegotiation
ContentNegotiation 插件有两个主要用途:在客户端和服务器之间协商媒体类型,以及以特定格式序列化/反序列化内容。
插件并配置 JSON 序列化程序:

kotlin

要将数据序列化为 JSON,你需要创建一个带有 @Serializable 注解的数据类:

kotlin

然后,你可以使用 call.respond 在响应中发送该类的对象:

kotlin

有关完整示例,请参阅 5_send_response 项目。

文件

Express

要在 Express 中响应一个文件,请使用 res.sendFile

javascript

有关完整示例,请参阅 5_send_response 项目。

Ktor

Ktor 提供了 call.respondFile 函数用于向客户端发送文件:

kotlin

有关完整示例,请参阅 5_send_response 项目。

Express 应用程序在响应文件时会添加 Accept-Ranges HTTP 响应头。服务器使用此标头向客户端宣告其支持文件下载的部分请求。在 Ktor 中,你需要安装

PartialContent
所需依赖项:io.ktor:%artifact_name% 服务器示例:download-file,客户端示例:client-download-file-range
插件来支持部分请求。

文件附件

Express

res.download 函数将指定文件作为附件传输:

javascript

有关完整示例,请参阅 5_send_response 项目。

Ktor

在 Ktor 中,你需要手动配置 Content-Disposition 标头以将文件作为附件传输:

kotlin

有关完整示例,请参阅 5_send_response 项目。

重定向

Express

要在 Express 中生成重定向响应,请调用 redirect 函数:

javascript

有关完整示例,请参阅 5_send_response 项目。

Ktor

在 Ktor 中,使用 respondRedirect 发送重定向响应:

kotlin

有关完整示例,请参阅 5_send_response 项目。

模板

Express 和 Ktor 都允许配合模板引擎来处理视图。

Express

假设我们在 views 文件夹中具有以下 Pug 模板:

要响应此模板,请调用 res.render

javascript

有关完整示例,请参阅 6_templates 项目。

Ktor

Ktor 支持多种

JVM 模板引擎
了解如何使用通过 HTML/CSS 或 JVM 模板引擎构建的视图。
,例如 FreeMarker、Velocity 等。例如,如果你需要响应放置在应用程序资源中的 FreeMarker 模板,请安装并配置 FreeMarker 插件,然后使用 call.respond 发送模板:

kotlin

有关完整示例,请参阅 6_templates 项目。

接收请求

本节将展示如何接收不同格式的请求体。

原始文本

下面的 POST 请求向服务器发送文本数据:

http

让我们看看如何在服务器端以纯文本形式接收此请求的请求体。

Express

要在 Express 中解析传入的请求体,你需要添加 body-parser

javascript

post 处理程序中,你需要传递文本解析器(bodyParser.text)。请求体将在 req.body 属性下可用:

javascript

有关完整示例,请参阅 7_receive_request 项目。

Ktor

在 Ktor 中,你可以使用 call.receiveText 以文本形式接收请求体:

kotlin

有关完整示例,请参阅 7_receive_request 项目。

JSON

在本节中,我们将了解如何接收 JSON 请求体。下面的示例展示了一个请求体中包含 JSON 对象的 POST 请求:

http
Express

要在 Express 中接收 JSON,请使用 bodyParser.json

javascript

有关完整示例,请参阅 7_receive_request 项目。

Ktor

在 Ktor 中,你需要安装

ContentNegotiation
ContentNegotiation 插件有两个主要用途:在客户端和服务器之间协商媒体类型,以及以特定格式序列化/反序列化内容。
插件并配置 Json 序列化程序:

kotlin

要将接收到的数据反序列化为对象,你需要创建一个数据类:

kotlin

然后,使用接受此数据类作为参数的 receive 方法:

kotlin

有关完整示例,请参阅 7_receive_request 项目。

URL 编码

现在让我们看看如何接收使用 application/x-www-form-urlencoded 类型发送的表单数据。下面的代码片段展示了一个包含表单数据的 POST 请求示例:

http
Express

与纯文本和 JSON 一样,Express 需要 body-parser。你需要将解析器类型设置为 bodyParser.urlencoded

javascript

有关完整示例,请参阅 7_receive_request 项目。

Ktor

在 Ktor 中,请使用 call.receiveParameters 函数:

kotlin

有关完整示例,请参阅 7_receive_request 项目。

原始数据

下一个用例是处理二进制数据。下面的请求向服务器发送一个类型为 application/octet-stream 的 PNG 图像:

http
Express

要在 Express 中处理二进制数据,请将解析器类型设置为 raw

javascript

有关完整示例,请参阅 7_receive_request 项目。

Ktor

Ktor 提供了 ByteReadChannelByteWriteChannel 用于异步读/写字节序列:

kotlin

有关完整示例,请参阅 7_receive request 项目。

多部分 (Multipart)

在最后一部分,让我们看看如何处理 多部分 (multipart) 请求体。下面的 POST 请求使用 multipart/form-data 类型发送带有描述的 PNG 图像:

http
Express

Express 需要一个单独的模块来解析多部分数据。在下面的示例中,使用了 multer 将文件上传到服务器:

javascript

有关完整示例,请参阅 7_receive_request 项目。

Ktor

在 Ktor 中,如果你需要接收作为多部分请求一部分发送的文件,请调用 receiveMultipart 函数,然后根据需要遍历每个部分。在下面的示例中,PartData.FileItem 用于以字节流的形式接收文件:

kotlin

有关完整示例,请参阅 7_receive_request 项目。

创建中间件

我们要看的最后一件事是如何创建允许你扩展服务器功能的中间件。下面的示例展示了如何使用 Express 和 Ktor 实现请求日志记录。

Express

在 Express 中,中间件是使用 app.use 绑定到应用程序的函数:

javascript

有关完整示例,请参阅 8_middleware 项目。

Ktor

Ktor 允许你使用

自定义插件
了解如何创建你自己的自定义插件。
来扩展其功能。下面的代码示例展示了如何处理 onCall 来实现请求日志记录:

kotlin

有关完整示例,请参阅 8_middleware 项目。

后续步骤

本指南中还有许多未涵盖的用例,例如会话管理、授权、数据库集成等。对于大多数这些功能,Ktor 提供了专用插件,可以将其安装在应用程序中并根据需要进行配置。要继续你的 Ktor 之旅,请访问 学习页面,该页面提供了一系列分步指南和开箱即用的示例。