fastify框架MVC架构教程

kimlopezkimlopez
3 min read

Fastify 标准项目结构示例

project-root/
├── src/                    # 源代码目录
   ├── controllers/        # 路由逻辑(处理请求的控制器)
      └── user.controller.ts
   ├── services/           # 业务逻辑层
      └── user.service.ts
   ├── routes/             # 路由定义
      └── user.route.ts
   ├── schemas/            # JSON Schema 定义(用于请求/响应验证)
      └── user.schema.ts
   ├── plugins/            # Fastify 插件(自定义功能)
      └── db.plugin.ts
   ├── config/             # 配置文件
      └── database.ts
   ├── types/              # TypeScript 类型定义
      └── index.ts
   └── app.ts              # Fastify 应用主入口
├── tests/                  # 测试目录
   └── user.test.ts
├── .env                    # 环境变量文件
├── .gitignore              # Git 忽略文件
├── package.json            # 项目依赖和脚本
├── tsconfig.json           # TypeScript 配置文件
└── README.md               # 项目说明

各部分详细说明

1.src/app.ts - 应用主入口

这是 Fastify 实例的初始化文件,负责启动服务器、注册插件和路由。

import fastify, { FastifyInstance } from 'fastify';
import dbPlugin from './plugins/db.plugin';
import userRoutes from './routes/user.route';

const app: FastifyInstance = fastify({ logger: true });

// 注册插件
app.register(dbPlugin);

// 注册路由(带前缀)
app.register(userRoutes, { prefix: '/api/users' });

const start = async () => {
  try {
    await app.listen({ port: 3000 });
    console.log('Server running on http://localhost:3000');
  } catch (err) {
    app.log.error(err);
    process.exit(1);
  }
};

start();

2. src/routes/ - 路由定义

路由文件负责定义 API 端点,通常与 Schema 结合使用。

// src/routes/user.route.ts
import { FastifyPluginAsync } from 'fastify';
import * as userSchema from '../schemas/user.schema';
import * as userController from '../controllers/user.controller';

const userRoutes: FastifyPluginAsync = async (fastify) => {
  fastify.get(
    '/',
    { schema: userSchema.getUsersSchema },
    userController.getUsers
  );

  fastify.post(
    '/',
    { schema: userSchema.createUserSchema },
    userController.createUser
  );
};

export default userRoutes;

3. src/schemas/ - JSON Schema 定义

Fastify 的一个亮点是内置对 JSON Schema 的支持,用于验证请求和响应。

// src/schemas/user.schema.ts
export const getUsersSchema = {
  response: {
    200: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          id: { type: 'number' },
          name: { type: 'string' },
        },
      },
    },
  },
};

export const createUserSchema = {
  body: {
    type: 'object',
    required: ['name'],
    properties: {
      name: { type: 'string' },
    },
  },
  response: {
    201: {
      type: 'object',
      properties: {
        id: { type: 'number' },
        name: { type: 'string' },
      },
    },
  },
};

4. src/controllers/ - 控制器
控制器处理具体的请求逻辑,通常调用服务层。

// src/controllers/user.controller.ts
import { FastifyRequest, FastifyReply } from 'fastify';
import * as userService from '../services/user.service';

export const getUsers = async (request: FastifyRequest, reply: FastifyReply) => {
  const users = await userService.getAllUsers();
  reply.send(users);
};

export const createUser = async (
  request: FastifyRequest<{ Body: { name: string } }>,
  reply: FastifyReply
) => {
  const { name } = request.body;
  const newUser = await userService.createUser(name);
  reply.code(201).send(newUser);
};

5. src/services/ - 业务逻辑
服务层封装具体的业务逻辑,与数据层交互。

// src/services/user.service.ts
export const getAllUsers = async () => {
  // 假设从数据库获取
  return [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
};

export const createUser = async (name: string) => {
  // 假设保存到数据库
  return { id: 3, name };
};

6. src/plugins/ - 插件
Fastify 的插件系统允许封装可复用功能,比如数据库连接。

// src/plugins/db.plugin.ts
import { FastifyPluginAsync } from 'fastify';
import fp from 'fastify-plugin';

const dbPlugin: FastifyPluginAsync = async (fastify) => {
  // 模拟数据库连接
  const db = { connected: true };
  fastify.decorate('db', db);
};

export default fp(dbPlugin);

7. src/config/ - 配置文件

存放配置项,比如数据库连接信息。

// src/config/database.ts
export const dbConfig = {
  host: process.env.DB_HOST || 'localhost',
  port: Number(process.env.DB_PORT) || 5432,
};

8. src/types/ - 类型定义

为 TypeScript 项目提供自定义类型。

// src/types/index.ts
import { FastifyInstance } from 'fastify';

declare module 'fastify' {
  interface FastifyInstance {
    db: { connected: boolean };
  }
}

9. tests/ - 测试文件

用于单元测试或集成测试。

// tests/user.test.ts
import { test } from 'tap';
import { build } from '../src/app';

test('GET /api/users should return users', async (t) => {
  const app = build();
  const response = await app.inject({
    method: 'GET',
    url: '/api/users',
  });
  t.equal(response.statusCode, 200);
  t.end();
});

为什么这样组织?

  1. 模块化: 路由、控制器、服务分离,便于维护和扩展。

  2. 验证优先: Schema 文件利用 Fastify 的验证功能,确保数据一致性。

  3. 插件驱动: 通过插件封装功能(如数据库连接),提高复用性。

  4. 测试友好: 结构清晰,易于编写单元测试和集成测试。

如何开始?

  1. 初始化项目

     npm init -y
     npm install fastify typescript @types/node ts-node
    
  2. 配置 tsconfig.json:

     {
       "compilerOptions": {
         "target": "es2019",
         "module": "commonjs",
         "outDir": "./dist",
         "rootDir": "./src",
         "strict": true,
         "esModuleInterop": true
       }
     }
    
  3. 启动脚本(package.json):

     {
       "scripts": {
         "start": "ts-node src/app.ts",
         "build": "tsc",
         "test": "tap tests/*.ts"
       }
     }
    
0
Subscribe to my newsletter

Read articles from kimlopez directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

kimlopez
kimlopez