NestJS 是一个用于构建高效、可靠和可扩展的服务器端应用程序的框架。在 NestJS 中,适配器模式(Adapter Pattern)主要体现在其对不同类型的 HTTP 服务端框架的适配上。NestJS 本身是建立在 Express 或者 Fastify 这样的底层 HTTP 框架之上的,但它提供了一个抽象层,使得开发者可以不必关心底层框架的具体实现。
适配器模式是一种结构型设计模式,它允许对象以兼容的方式协同工作,即便它们的接口不兼容。在 NestJS 中,这意味着你可以在不改变应用程序核心逻辑的情况下,切换不同的 HTTP 框架。
如何工作的?
- 抽象层:NestJS 定义了一组抽象的 HTTP 接口,这些接口描述了处理 HTTP 请求所需的基本操作,如处理请求、响应等。
// @nestjs\core\adapters\http-adapter.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AbstractHttpAdapter = void 0;
/**
* @publicApi
*/
class AbstractHttpAdapter {
constructor(instance) {
this.instance = instance;
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
async init() { }
use(...args) {
return this.instance.use(...args);
}
get(...args) {
return this.instance.get(...args);
}
post(...args) {
return this.instance.post(...args);
}
head(...args) {
return this.instance.head(...args);
}
delete(...args) {
return this.instance.delete(...args);
}
put(...args) {
return this.instance.put(...args);
}
patch(...args) {
return this.instance.patch(...args);
}
all(...args) {
return this.instance.all(...args);
}
search(port, hostname, callback) {
return this.instance.search(port, hostname, callback);
}
options(...args) {
return this.instance.options(...args);
}
listen(port, hostname, callback) {
return this.instance.listen(port, hostname, callback);
}
getHttpServer() {
return this.httpServer;
}
setHttpServer(httpServer) {
this.httpServer = httpServer;
}
setInstance(instance) {
this.instance = instance;
}
getInstance() {
return this.instance;
}
}
exports.AbstractHttpAdapter = AbstractHttpAdapter;
- 适配器:对于每种支持的底层 HTTP 框架(如 Express 或 Fastify),NestJS 提供了一个适配器。这个适配器实现了 NestJS 定义的 HTTP 抽象接口,但在内部使用特定框架的方法。
// @nestjs\platform-express\adapters\express-adapter.js
const http_adapter_1 = require("@nestjs/core/adapters/http-adapter");
class ExpressAdapter extends http_adapter_1.AbstractHttpAdapter {
...
}
exports.ExpressAdapter = ExpressAdapter;
FastifyAdapter
的实现。
// @nestjs\platform-fastify\adapters\fastify-adapter.js
const http_adapter_1 = require("@nestjs/core/adapters/http-adapter");
class FastifyAdapter extends http_adapter_1.AbstractHttpAdapter {
...
}
exports.FastifyAdapter = FastifyAdapter;
- 灵活切换:因为 NestJS 应用程序是针对这些抽象接口编写的,所以可以通过简单地更换适配器来切换底层的 HTTP 框架,而不需要重写应用逻辑。
执行await NestFactory.create(AppModule)
的时候,会判断serverOrOptions
传进去是不是一个Adapter
。
class NestFactoryStatic {
constructor() {
this.logger = new logger_service_1.Logger('NestFactory', {
timestamp: true,
});
this.abortOnError = true;
this.autoFlushLogs = false;
}
async create(moduleCls, serverOrOptions, options) {
const [httpServer, appOptions] = this.isHttpServer(serverOrOptions)
? [serverOrOptions, options]
: [this.createHttpAdapter(), serverOrOptions];
...
}
}
示例
例如,如果你想将你的 NestJS 应用从 Express 切换到 Fastify,你只需要更换相应的适配器。在 NestJS 中,这通常通过更改 main.ts
文件中的一行代码来完成:
const app = await NestFactory.create(AppModule, new FastifyAdapter());
相比之下,如果使用 Express 适配器,代码将会是:
const app = await NestFactory.create(AppModule); // 默认是 ExpressAdapter
express
和Fastify
都实现了AbstractHttpAdapter
方法,于是无论用户传入哪一种都可以实现http
模块的解耦。
优势
- 灵活性:允许开发者根据项目需求或个人偏好选择合适的 HTTP 框架。
- 解耦:应用核心逻辑与底层 HTTP 框架解耦,提高了代码的可维护性。
- 易于测试:由于底层框架被抽象化,使得对应用逻辑的单元测试更加容易。
总之,适配器模式在 NestJS 中的应用提供了一种优雅的方式来支持不同的 HTTP 框架,同时保持应用核心逻辑的一致性和可维护性。