【Node.js】Web开发框架

news2025/5/22 22:04:14

在这里插入图片描述

个人主页:Guiat
归属专栏:node.js

在这里插入图片描述

文章目录

  • 1. Node.js Web框架概述
    • 1.1 Web框架的作用
    • 1.2 Node.js主要Web框架生态
    • 1.3 框架选择考虑因素
  • 2. Express.js
    • 2.1 Express.js概述
    • 2.2 基本用法
      • 2.2.1 安装Express
      • 2.2.2 创建基本服务器
    • 2.3 路由
    • 2.4 中间件
    • 2.5 请求和响应
    • 2.6 完整的Express应用结构
  • 3. Koa.js
    • 3.1 Koa.js概述
    • 3.2 基本用法
      • 3.2.1 安装Koa
      • 3.2.2 创建基本服务器
    • 3.3 中间件和上下文
    • 3.4 Koa与Express对比
  • 4. Nest.js
    • 4.1 Nest.js概述
    • 4.2 基本用法
      • 4.2.1 安装Nest.js
      • 4.2.2 主要组件
    • 4.3 依赖注入
    • 4.4 中间件、守卫和拦截器
  • 5. Fastify
    • 5.1 Fastify概述
    • 5.2 基本用法
      • 5.2.1 安装Fastify
      • 5.2.2 创建服务器
    • 5.3 Schema验证和序列化
    • 5.4 插件系统
    • 5.5 与Express和Koa性能对比
  • 6. Next.js
    • 6.1 Next.js概述
    • 6.2 基本用法
      • 6.2.1 创建Next.js应用
      • 6.2.2 页面和路由
    • 6.3 数据获取方法
    • 6.4 API路由
    • 6.5 中间件和布局
  • 7. Hapi.js
    • 7.1 Hapi.js概述
    • 7.2 基本用法
      • 7.2.1 安装Hapi
      • 7.2.2 创建服务器
    • 7.3 路由和处理程序
    • 7.4 插件和扩展
    • 7.5 验证和认证
  • 8. 全栈框架: AdonisJS和Sails.js
    • 8.1 AdonisJS概述
    • 8.2 AdonisJS基本用法
      • 8.2.1 创建AdonisJS应用
      • 8.2.2 AdonisJS应用结构
      • 8.2.3 路由和控制器
    • 8.3 Sails.js概述
    • 8.4 Sails.js基本用法
      • 8.4.1 创建Sails.js应用
      • 8.4.2 模型和API
      • 8.4.3 路由配置
  • 9. 专业领域框架
    • 9.1 Loopback - API框架
      • 9.1.1 基本使用
    • 9.2 Strapi - 内容管理框架
      • 9.2.1 基本使用
  • 10. 框架选择指南与比较
    • 10.1 框架特性对比
    • 10.2 适用场景选择

正文

1. Node.js Web框架概述

Node.js的生态系统提供了多种Web开发框架,它们各自具有不同的特点和适用场景。这些框架帮助开发者快速构建高性能、可维护的Web应用程序。

1.1 Web框架的作用

  • 简化HTTP服务器的创建
  • 提供路由管理
  • 集成中间件系统
  • 统一错误处理
  • 提供模板引擎支持
  • 简化API开发
  • 改善应用程序结构

1.2 Node.js主要Web框架生态

Node.js Web框架
Express.js
Koa.js
Hapi.js
Nest.js
Fastify
Next.js
Adonis.js
Sails.js
Loopback
Middleware-based
Async/Await友好
配置驱动
TypeScript优先
性能导向
React SSR/SSG
全栈MVC
企业级API
API开发

1.3 框架选择考虑因素

mindmap
  root((Web框架选择))
    性能需求
      高并发应用
      低延迟
      资源消耗
    开发效率
      开发速度
      学习曲线
      社区支持
    项目复杂度
      小型项目
      中型应用
      企业级应用
    团队技能
      TypeScript经验
      现有框架经验
      架构偏好
    生态系统
      中间件
      ORM支持
      插件丰富度
    应用类型
      REST API
      GraphQL
      实时应用
      静态网站

2. Express.js

2.1 Express.js概述

Express.js是Node.js最流行的Web框架,提供了简单而灵活的API,适用于各种Web应用和API开发。

客户端请求
Express应用
路由
中间件1
中间件2
路由处理器
响应
客户端

2.2 基本用法

2.2.1 安装Express

npm install express

2.2.2 创建基本服务器

const express = require('express');
const app = express();
const port = 3000;

// 路由处理
app.get('/', (req, res) => {
  res.send('Hello World!');
});

// 启动服务器
app.listen(port, () => {
  console.log(`服务器运行在 http://localhost:${port}`);
});

2.3 路由

// 基本路由
app.get('/users', (req, res) => {
  res.json([{ name: 'John' }, { name: 'Jane' }]);
});

app.post('/users', (req, res) => {
  // 创建用户
  res.status(201).json({ success: true });
});

// 参数路由
app.get('/users/:id', (req, res) => {
  const userId = req.params.id;
  res.json({ id: userId, name: 'John Doe' });
});

// 路由模块化
const usersRoutes = express.Router();

usersRoutes.get('/', (req, res) => { /* ... */ });
usersRoutes.post('/', (req, res) => { /* ... */ });
usersRoutes.get('/:id', (req, res) => { /* ... */ });

app.use('/api/users', usersRoutes);

2.4 中间件

请求
全局中间件
路由特定中间件
路由处理器
响应
// 内置中间件
app.use(express.json()); // 解析JSON请求体
app.use(express.urlencoded({ extended: true })); // 解析URL编码的请求体
app.use(express.static('public')); // 提供静态文件

// 自定义中间件
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url} at ${new Date()}`);
  next(); // 继续下一个中间件
});

// 路由特定中间件
const authenticate = (req, res, next) => {
  const token = req.headers.authorization;
  if (!token) {
    return res.status(401).json({ error: '未授权' });
  }
  // 验证token...
  next();
};

app.get('/protected', authenticate, (req, res) => {
  res.json({ message: '受保护的数据' });
});

// 错误处理中间件
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: '服务器内部错误' });
});

2.5 请求和响应

// 请求对象(req)
app.get('/example', (req, res) => {
  console.log(req.query);     // 查询参数
  console.log(req.params);    // 路由参数
  console.log(req.body);      // 请求体
  console.log(req.headers);   // 请求头
  console.log(req.cookies);   // Cookies (需要cookie-parser)
  console.log(req.ip);        // 客户端IP
  console.log(req.path);      // 请求路径
  console.log(req.method);    // HTTP方法
  
  // 响应对象(res)
  res.status(200);            // 设置状态码
  res.set('Content-Type', 'application/json'); // 设置响应头
  res.cookie('name', 'value', { maxAge: 900000 }); // 设置cookie
  res.json({ data: 'JSON响应' }); // 发送JSON响应
  res.send('文本响应');       // 发送通用响应
  res.sendFile('/path/to/file.pdf'); // 发送文件
  res.download('/report.pdf'); // 下载文件
  res.redirect('/new-page'); // 重定向
  res.render('template', { title: '模板渲染' }); // 渲染模板
});

2.6 完整的Express应用结构

project-root/
├── config/                  # 配置文件
│   ├── database.js
│   └── app.js
├── controllers/             # 控制器
│   ├── userController.js
│   └── productController.js
├── middleware/              # 中间件
│   ├── auth.js
│   └── errorHandler.js
├── models/                  # 数据模型
│   ├── User.js
│   └── Product.js
├── routes/                  # 路由
│   ├── userRoutes.js
│   └── productRoutes.js
├── public/                  # 静态资源
│   ├── css/
│   ├── js/
│   └── images/
├── views/                   # 视图模板
│   ├── layouts/
│   ├── users/
│   └── products/
├── tests/                   # 测试
│   ├── unit/
│   └── integration/
├── app.js                   # 主应用文件
├── server.js                # 服务器启动文件
├── package.json
└── .env                     # 环境变量

3. Koa.js

3.1 Koa.js概述

Koa是由Express团队开发的更轻量级、更富有表现力的Node.js Web框架,专为异步编程设计,利用async/await特性提供更简洁的中间件机制。

客户端请求
Koa应用
中间件1
中间件2
中间件3
响应处理
中间件3 返回
中间件2 返回
中间件1 返回
响应

3.2 基本用法

3.2.1 安装Koa

npm install koa

3.2.2 创建基本服务器

const Koa = require('koa');
const app = new Koa();
const port = 3000;

// 中间件
app.use(async (ctx, next) => {
  const start = Date.now();
  await next();
  const ms = Date.now() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(port, () => {
  console.log(`服务器运行在 http://localhost:${port}`);
});

3.3 中间件和上下文

// 错误处理中间件
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (err) {
    ctx.status = err.statusCode || 500;
    ctx.body = {
      message: err.message
    };
    ctx.app.emit('error', err, ctx);
  }
});

// 数据解析中间件
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());

// 路由中间件
const Router = require('@koa/router');
const router = new Router();

router.get('/', async (ctx) => {
  ctx.body = { message: '首页' };
});

router.get('/users/:id', async (ctx) => {
  const userId = ctx.params.id;
  ctx.body = { id: userId, name: 'John Doe' };
});

app.use(router.routes());
app.use(router.allowedMethods());

// 上下文操作示例
app.use(async ctx => {
  // 请求数据
  console.log(ctx.request.query);  // 查询参数
  console.log(ctx.request.body);   // 请求体 (需要bodyParser)
  console.log(ctx.params);         // 路由参数 (需要路由中间件)
  
  // 响应设置
  ctx.status = 200;                // 状态码
  ctx.set('X-Custom-Header', 'value'); // 自定义响应头
  ctx.type = 'application/json';   // 内容类型
  ctx.body = { data: 'success' };  // 响应体
  
  // Cookies
  ctx.cookies.set('name', 'value', { maxAge: 86400000 });
  const cookie = ctx.cookies.get('name');
});

3.4 Koa与Express对比

Web框架对比
Express
Koa
优点
成熟稳定
社区庞大
中间件丰富
简单直观
缺点
回调地狱
错误处理复杂
优点
async/await支持
更好的错误处理
更简洁的API
可组合中间件
缺点
学习曲线
需要额外模块

4. Nest.js

4.1 Nest.js概述

Nest.js是一个用于构建高效、可靠、可扩展的服务器端应用程序的渐进式Node.js框架,它结合了面向对象编程、函数式编程和函数响应式编程的元素。

Nest.js架构
模块Module
控制器Controller
提供者Provider
中间件Middleware
管道Pipe
守卫Guard
拦截器Interceptor
异常过滤器ExceptionFilter
功能封装
处理请求
提供服务
处理HTTP请求
数据转换/验证
权限验证
响应拦截/修改
异常处理

4.2 基本用法

4.2.1 安装Nest.js

npm i -g @nestjs/cli
nest new project-name

4.2.2 主要组件

// 控制器 (users.controller.ts)
import { Controller, Get, Post, Body, Param, UseGuards } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { AuthGuard } from '../auth/auth.guard';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  findAll() {
    return this.usersService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.usersService.findOne(+id);
  }

  @Post()
  @UseGuards(AuthGuard)
  create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }
}

// 服务 (users.service.ts)
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { User } from './entities/user.entity';

@Injectable()
export class UsersService {
  private readonly users: User[] = [];

  create(createUserDto: CreateUserDto): User {
    const user = { id: this.users.length + 1, ...createUserDto };
    this.users.push(user);
    return user;
  }

  findAll(): User[] {
    return this.users;
  }

  findOne(id: number): User {
    return this.users.find(user => user.id === id);
  }
}

// 模块 (users.module.ts)
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';

@Module({
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService]
})
export class UsersModule {}

// 主模块 (app.module.ts)
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module';
import { AuthModule } from './auth/auth.module';

@Module({
  imports: [UsersModule, AuthModule],
})
export class AppModule {}

4.3 依赖注入

Nest.js依赖注入
提供者Provider
消费者Consumer
服务Service
存储库Repository
工厂Factory
辅助类Helper
控制器Controller
其他服务Service
守卫Guard
拦截器Interceptor
// 定义提供者
@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  create(cat: Cat) {
    this.cats.push(cat);
  }

  findAll(): Cat[] {
    return this.cats;
  }
}

// 注册提供者
@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class CatsModule {}

// 消费依赖
@Controller('cats')
export class CatsController {
  constructor(private readonly catsService: CatsService) {}
  
  @Get()
  findAll() {
    return this.catsService.findAll();
  }
}

4.4 中间件、守卫和拦截器

客户端请求
中间件
守卫
拦截器-前
管道
控制器路由处理
拦截器-后
异常过滤器
响应
// 中间件
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: Function) {
    console.log(`Request... ${req.method} ${req.url}`);
    next();
  }
}

// 使用中间件
@Module({
  imports: [UsersModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('users');
  }
}

// 守卫
@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    // 验证逻辑
    return isAuthorized(request);
  }
}

// 拦截器
@Injectable()
export class TransformInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    console.log('Before...');
    
    return next
      .handle()
      .pipe(
        map(data => {
          console.log('After...');
          return { data, timestamp: new Date().toISOString() };
        }),
      );
  }
}

// 管道
@Injectable()
export class ValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    // 数据验证和转换逻辑
    return validatedValue;
  }
}

5. Fastify

5.1 Fastify概述

Fastify是一个专注于性能和低开销的快速Web框架,提供了一套精简API,适合构建高性能的服务。

Fastify特点
高性能
低内存占用
插件架构
Schema验证
TypeScript支持
日志内置

5.2 基本用法

5.2.1 安装Fastify

npm install fastify

5.2.2 创建服务器

const fastify = require('fastify')({ logger: true });
const port = 3000;

// 定义路由
fastify.get('/', async (request, reply) => {
  return { hello: 'world' };
});

// 启动服务器
const start = async () => {
  try {
    await fastify.listen({ port });
    fastify.log.info(`服务器运行在 ${fastify.server.address().port}`);
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};

start();

5.3 Schema验证和序列化

// 定义带有Schema的路由
fastify.route({
  method: 'POST',
  url: '/users',
  schema: {
    body: {
      type: 'object',
      required: ['name', 'email'],
      properties: {
        name: { type: 'string' },
        email: { type: 'string', format: 'email' },
        age: { type: 'integer', minimum: 18 }
      }
    },
    response: {
      200: {
        type: 'object',
        properties: {
          id: { type: 'integer' },
          name: { type: 'string' },
          email: { type: 'string' }
        }
      }
    }
  },
  handler: async (request, reply) => {
    const { name, email, age } = request.body;
    // 处理创建用户的逻辑
    const user = { id: 1, name, email };
    return user;
  }
});

5.4 插件系统

// 定义插件
const myPlugin = async (fastify, options) => {
  // 注册钩子
  fastify.addHook('onRequest', async (request, reply) => {
    request.log.info('请求已接收');
  });
  
  // 注册路由
  fastify.get('/plugin-route', async (request, reply) => {
    return { message: '这是插件路由' };
  });
  
  // 装饰fastify实例
  fastify.decorate('utility', function() {
    return 'utility value';
  });
  
  // 装饰请求
  fastify.decorateRequest('customProp', 'custom value');
};

// 注册插件
fastify.register(myPlugin, { pluginOption: 'value' });

// 使用插件功能
fastify.get('/use-plugin', async (request, reply) => {
  console.log(fastify.utility());
  console.log(request.customProp);
  return { success: true };
});

5.5 与Express和Koa性能对比

bar
    title Node.js框架性能对比(请求/秒)
    "Express" : 12000
    "Koa" : 15000
    "Fastify" : 30000
    "Bare Node.js" : 35000

6. Next.js

6.1 Next.js概述

Next.js是一个React框架,用于构建服务器渲染、静态生成和客户端渲染的React应用。它提供了现代Web应用所需的所有功能,如路由、图像优化、API路由等。

Next.js特性
服务器渲染SSR
静态站点生成SSG
混合渲染模式
文件系统路由
API路由
图像优化
自动代码分割
TypeScript支持

6.2 基本用法

6.2.1 创建Next.js应用

npx create-next-app my-next-app
# 或
yarn create next-app my-next-app

6.2.2 页面和路由

// pages/index.js - 主页
import Head from 'next/head';

export default function Home() {
  return (
    <div>
      <Head>
        <title>Next.js应用</title>
        <meta name="description" content="我的Next.js应用" />
      </Head>
      <main>
        <h1>欢迎来到Next.js!</h1>
      </main>
    </div>
  );
}

// pages/users/[id].js - 动态路由
import { useRouter } from 'next/router';

export default function User() {
  const router = useRouter();
  const { id } = router.query;

  return (
    <div>
      <h1>用户: {id}</h1>
    </div>
  );
}

// pages/about.js - 静态页面
export default function About() {
  return (
    <div>
      <h1>关于我们</h1>
      <p>这是关于页面的内容</p>
    </div>
  );
}

6.3 数据获取方法

Next.js数据获取
getServerSideProps
getStaticProps
getStaticPaths
客户端数据获取
每次请求运行
服务器端渲染SSR
构建时运行
静态站点生成SSG
指定动态路由
需要预渲染的路径
React钩子
SWR/React Query
// 服务器端渲染示例 (SSR)
export async function getServerSideProps(context) {
  // 从服务器获取数据
  const res = await fetch('https://api.example.com/data');
  const data = await res.json();

  // 将数据传递给页面组件
  return {
    props: { data }, // 作为props传递给页面
  };
}

// 静态生成示例 (SSG)
export async function getStaticProps() {
  // 在构建时获取数据
  const res = await fetch('https://api.example.com/static-data');
  const data = await res.json();

  return {
    props: { data },
    revalidate: 60, // 增量静态再生成 (ISR) - 每60秒更新
  };
}

// 静态路径示例
export async function getStaticPaths() {
  // 获取所有可能的路径
  const res = await fetch('https://api.example.com/users');
  const users = await res.json();
  
  // 为每个用户生成路径
  const paths = users.map((user) => ({
    params: { id: user.id.toString() },
  }));

  return {
    paths,
    fallback: 'blocking', // 或 true 或 false
  };
}

6.4 API路由

// pages/api/hello.js
export default function handler(req, res) {
  res.status(200).json({ message: 'Hello World!' });
}

// pages/api/users/[id].js - 动态API路由
export default function handler(req, res) {
  const { id } = req.query;
  const { method } = req;

  switch (method) {
    case 'GET':
      // 获取用户
      res.status(200).json({ id, name: 'John Doe' });
      break;
    case 'PUT':
      // 更新用户
      res.status(200).json({ id, ...req.body });
      break;
    case 'DELETE':
      // 删除用户
      res.status(200).json({ id, deleted: true });
      break;
    default:
      res.setHeader('Allow', ['GET', 'PUT', 'DELETE']);
      res.status(405).end(`Method ${method} Not Allowed`);
  }
}

6.5 中间件和布局

// middleware.js (Next.js 12+)
import { NextResponse } from 'next/server';

export function middleware(request) {
  // 检查身份验证
  const token = request.cookies.get('token');
  
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  
  return NextResponse.next();
}

// _app.js - 全局布局
import '../styles/globals.css';
import Layout from '../components/Layout';

function MyApp({ Component, pageProps }) {
  // 如果页面有自定义布局,使用它,否则使用默认布局
  const getLayout = Component.getLayout || ((page) => <Layout>{page}</Layout>);
  
  return getLayout(<Component {...pageProps} />);
}

export default MyApp;

// components/Layout.js
export default function Layout({ children }) {
  return (
    <>
      <header>网站头部</header>
      <main>{children}</main>
      <footer>网站底部</footer>
    </>
  );
}

7. Hapi.js

7.1 Hapi.js概述

Hapi.js是一个功能丰富的框架,专注于配置而非代码,旨在帮助开发者构建可扩展的API和服务。

Hapi.js特性
配置驱动开发
内置缓存
身份验证框架
状态管理
插件系统
请求验证

7.2 基本用法

7.2.1 安装Hapi

npm install @hapi/hapi

7.2.2 创建服务器

const Hapi = require('@hapi/hapi');

const init = async () => {
    const server = Hapi.server({
        port: 3000,
        host: 'localhost'
    });

    // 定义路由
    server.route({
        method: 'GET',
        path: '/',
        handler: (request, h) => {
            return 'Hello World!';
        }
    });

    await server.start();
    console.log('服务器运行在 %s', server.info.uri);
};

process.on('unhandledRejection', (err) => {
    console.log(err);
    process.exit(1);
});

init();

7.3 路由和处理程序

// 基本路由
server.route({
    method: 'GET',
    path: '/users/{id}',
    handler: (request, h) => {
        const id = request.params.id;
        return { id, name: 'John Doe' };
    }
});

// 使用路由选项
server.route({
    method: 'POST',
    path: '/users',
    options: {
        validate: {
            payload: Joi.object({
                name: Joi.string().min(3).required(),
                email: Joi.string().email().required()
            })
        },
        auth: 'jwt',
        tags: ['api', 'users'],
        description: '创建新用户'
    },
    handler: async (request, h) => {
        const user = await createUser(request.payload);
        return h.response(user).code(201);
    }
});

// 路由通配符和参数
server.route({
    method: 'GET',
    path: '/files/{param*}',
    handler: (request, h) => {
        const path = request.params.param || '';
        return `请求的文件路径: ${path}`;
    }
});

7.4 插件和扩展

// 定义插件
const myPlugin = {
    name: 'myPlugin',
    version: '1.0.0',
    register: async function (server, options) {
        // 添加路由
        server.route({
            method: 'GET',
            path: '/plugin-route',
            handler: (request, h) => {
                return { plugin: 'myPlugin' };
            }
        });

        // 注册扩展点
        server.ext('onRequest', (request, h) => {
            request.app.requestTime = new Date().getTime();
            return h.continue;
        });

        // 添加方法
        server.method('calculateTax', (price) => {
            return price * 0.2;
        });
    }
};

// 注册插件
const init = async () => {
    const server = Hapi.server({ /* ... */ });
    
    await server.register({
        plugin: myPlugin,
        options: { /* 插件选项 */ }
    });
    
    // 使用插件提供的方法
    server.route({
        method: 'GET',
        path: '/tax/{price}',
        handler: (request, h) => {
            const price = parseFloat(request.params.price);
            const tax = server.methods.calculateTax(price);
            return { price, tax, total: price + tax };
        }
    });
    
    await server.start();
};

7.5 验证和认证

// 安装依赖
// npm install @hapi/joi @hapi/basic @hapi/jwt

const Joi = require('@hapi/joi');
const Basic = require('@hapi/basic');
const JWT = require('@hapi/jwt');

const init = async () => {
    const server = Hapi.server({ /* ... */ });
    
    // 注册认证插件
    await server.register([Basic, JWT]);
    
    // 配置JWT认证策略
    server.auth.strategy('jwt', 'jwt', {
        keys: 'your-secret-key',
        verify: {
            aud: 'urn:audience:app',
            iss: 'urn:issuer:app',
            sub: false,
            maxAgeSec: 14400 // 4小时
        },
        validate: (artifacts, request, h) => {
            return {
                isValid: true,
                credentials: { user: artifacts.decoded.payload.user }
            };
        }
    });
    
    // 配置基本认证策略
    server.auth.strategy('simple', 'basic', {
        validate: async (request, username, password, h) => {
            // 验证逻辑
            const isValid = username === 'admin' && password === 'password';
            const credentials = { id: 1, name: username };
            
            return { isValid, credentials };
        }
    });
    
    // 设置默认认证策略
    server.auth.default('jwt');
    
    // 带有验证的路由
    server.route({
        method: 'POST',
        path: '/users',
        options: {
            auth: 'jwt',
            validate: {
                payload: Joi.object({
                    name: Joi.string().min(3).max(50).required(),
                    email: Joi.string().email().required(),
                    age: Joi.number().integer().min(18).required()
                }),
                query: Joi.object({
                    includeDetails: Joi.boolean().default(false)
                }),
                failAction: (request, h, err) => {
                    throw err; // 将验证错误返回给客户端
                }
            }
        },
        handler: async (request, h) => {
            // 处理创建用户的逻辑
            return { success: true };
        }
    });
    
    await server.start();
};

8. 全栈框架: AdonisJS和Sails.js

8.1 AdonisJS概述

AdonisJS是一个全栈MVC框架,提供开箱即用的ORM、身份验证、授权等功能,类似于Laravel(PHP)和Rails(Ruby)的开发体验。

AdonisJS特性
MVC架构
内置ORM
身份验证
ACL授权
验证器
命令行工具
WebSocket支持

8.2 AdonisJS基本用法

8.2.1 创建AdonisJS应用

npm init adonis-ts-app@latest my-app

8.2.2 AdonisJS应用结构

my-app/
├── app/                   # 应用代码
│   ├── Controllers/       # 控制器
│   ├── Models/            # 数据模型
│   ├── Middleware/        # 中间件
│   ├── Validators/        # 验证器
│   └── Services/          # 服务
├── config/                # 配置文件
├── contracts/             # TypeScript接口定义
├── database/              # 数据库相关
│   ├── migrations/        # 数据库迁移
│   └── seeders/           # 数据种子
├── providers/             # 服务提供者
├── public/                # 静态资源
├── resources/             # 视图和其他资源
│   └── views/             # 视图模板
├── start/                 # 启动文件
│   ├── routes.ts          # 路由定义
│   ├── kernel.ts          # HTTP内核配置
│   └── events.ts          # 事件监听器
├── .env                   # 环境变量
└── server.ts              # 服务器启动文件

8.2.3 路由和控制器

// start/routes.ts
import Route from '@ioc:Adonis/Core/Route'

Route.get('/', 'HomeController.index')
Route.get('/about', 'HomeController.about')

Route.group(() => {
  Route.get('/', 'PostsController.index')
  Route.post('/', 'PostsController.store').middleware('auth')
  Route.get('/:id', 'PostsController.show')
  Route.put('/:id', 'PostsController.update').middleware('auth')
  Route.delete('/:id', 'PostsController.destroy').middleware('auth')
}).prefix('/api/posts')

// app/Controllers/Http/PostsController.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import Post from 'App/Models/Post'

export default class PostsController {
  public async index({ request, response }: HttpContextContract) {
    const page = request.input('page', 1)
    const limit = request.input('limit', 10)
    
    const posts = await Post.query().paginate(page, limit)
    return response.ok(posts)
  }
  
  public async store({ request, response, auth }: HttpContextContract) {
    const postData = request.only(['title', 'content'])
    
    const post = await Post.create({
      ...postData,
      userId: auth.user!.id
    })
    
    return response.created(post)
  }
  
  public async show({ params, response }: HttpContextContract) {
    const post = await Post.find(params.id)
    
    if (!post) {
      return response.notFound({ message: '文章未找到' })
    }
    
    return response.ok(post)
  }
}

8.3 Sails.js概述

Sails.js是一个基于Express的全栈MVC框架,专注于企业级应用开发,提供了自动生成REST API、实时WebSocket等功能。

Sails.js特性
MVC架构
自动生成API
实时WebSocket
ORM/Waterline
自动路由
国际化支持
安全策略

8.4 Sails.js基本用法

8.4.1 创建Sails.js应用

npm install sails -g
sails new my-sails-app
cd my-sails-app
sails lift

8.4.2 模型和API

// api/models/User.js
module.exports = {
  attributes: {
    name: {
      type: 'string',
      required: true
    },
    email: {
      type: 'string',
      required: true,
      unique: true,
      isEmail: true
    },
    posts: {
      collection: 'post',
      via: 'owner'
    }
  }
};

// api/models/Post.js
module.exports = {
  attributes: {
    title: {
      type: 'string',
      required: true
    },
    content: {
      type: 'string'
    },
    owner: {
      model: 'user'
    }
  }
};

// api/controllers/PostController.js
module.exports = {
  // 自定义动作
  featured: async function(req, res) {
    const featuredPosts = await Post.find({ isFeatured: true });
    return res.json(featuredPosts);
  },
  
  // 覆盖默认动作
  create: async function(req, res) {
    // 自定义创建逻辑
    try {
      const postData = req.body;
      postData.owner = req.session.userId;
      
      const newPost = await Post.create(postData).fetch();
      return res.status(201).json(newPost);
    } catch (err) {
      return res.serverError(err);
    }
  }
};

8.4.3 路由配置

// config/routes.js
module.exports.routes = {
  // 自定义REST路由
  'GET /api/posts/featured': 'PostController.featured',
  
  // 蓝图API路由 (自动生成)
  'GET /api/posts': 'PostController.find',
  'GET /api/posts/:id': 'PostController.findOne',
  'POST /api/posts': 'PostController.create',
  'PATCH /api/posts/:id': 'PostController.update',
  'DELETE /api/posts/:id': 'PostController.destroy',
  
  // 视图路由
  'GET /': { view: 'pages/homepage' }
};

// config/blueprints.js
module.exports.blueprints = {
  // 启用/禁用 REST 路由
  rest: true,
  
  // 启用/禁用 CRUD 快捷方式
  shortcuts: false,
  
  // 启用/禁用 WebSocket 动作
  actions: false,
  
  // REST 前缀
  prefix: '/api'
};

9. 专业领域框架

9.1 Loopback - API框架

Loopback特性
API自动生成
OpenAPI规范
强大的ORM
关系管理
授权/认证
GraphQL支持

9.1.1 基本使用

npm install -g @loopback/cli
lb4 app my-api
// 定义模型
import {Entity, model, property} from '@loopback/repository';

@model()
export class Product extends Entity {
  @property({
    type: 'number',
    id: true,
    generated: true,
  })
  id?: number;

  @property({
    type: 'string',
    required: true,
  })
  name: string;

  @property({
    type: 'number',
    required: true,
  })
  price: number;

  constructor(data?: Partial<Product>) {
    super(data);
  }
}

// 定义存储库
import {DefaultCrudRepository} from '@loopback/repository';
import {Product} from '../models';
import {DbDataSource} from '../datasources';
import {inject} from '@loopback/core';

export class ProductRepository extends DefaultCrudRepository<
  Product,
  typeof Product.prototype.id
> {
  constructor(@inject('datasources.db') dataSource: DbDataSource) {
    super(Product, dataSource);
  }
}

// 定义控制器
import {
  Count,
  CountSchema,
  Filter,
  FilterExcludingWhere,
  repository,
  Where,
} from '@loopback/repository';
import {
  post,
  param,
  get,
  getModelSchemaRef,
  patch,
  put,
  del,
  requestBody,
  response,
} from '@loopback/rest';
import {Product} from '../models';
import {ProductRepository} from '../repositories';

export class ProductController {
  constructor(
    @repository(ProductRepository)
    public productRepository : ProductRepository,
  ) {}

  @post('/products')
  @response(200, {
    description: 'Product model instance',
    content: {'application/json': {schema: getModelSchemaRef(Product)}},
  })
  async create(
    @requestBody({
      content: {
        'application/json': {
          schema: getModelSchemaRef(Product, {
            title: 'NewProduct',
            exclude: ['id'],
          }),
        },
      },
    })
    product: Omit<Product, 'id'>,
  ): Promise<Product> {
    return this.productRepository.create(product);
  }

  @get('/products/{id}')
  @response(200, {
    description: 'Product model instance',
    content: {
      'application/json': {
        schema: getModelSchemaRef(Product, {includeRelations: true}),
      },
    },
  })
  async findById(
    @param.path.number('id') id: number,
    @param.filter(Product, {exclude: 'where'}) filter?: FilterExcludingWhere<Product>
  ): Promise<Product> {
    return this.productRepository.findById(id, filter);
  }
}

9.2 Strapi - 内容管理框架

Strapi特性
无头CMS
自定义内容类型
管理面板
用户角色权限
插件系统
RESTful API
GraphQL API

9.2.1 基本使用

npx create-strapi-app my-project
// 自定义控制器
// ./src/api/article/controllers/custom.js
module.exports = {
  async featured(ctx) {
    try {
      const featuredArticles = await strapi.db.query('api::article.article').findMany({
        where: { featured: true },
        populate: ['cover', 'category', 'author'],
      });
      
      return featuredArticles;
    } catch (err) {
      ctx.body = err;
    }
  },
};

// 自定义路由
// ./src/api/article/routes/custom.js
module.exports = {
  routes: [
    {
      method: 'GET',
      path: '/articles/featured',
      handler: 'custom.featured',
      config: {
        policies: [],
        middlewares: [],
      },
    },
  ],
};

// 生命周期钩子
// ./src/api/article/content-types/article/lifecycles.js
module.exports = {
  beforeCreate(event) {
    const { data, where, select, populate } = event.params;
    
    // 自动生成slug
    if (data.title && !data.slug) {
      data.slug = slugify(data.title, { lower: true });
    }
  },
  
  afterCreate(event) {
    const { result, params } = event;
    
    // 发送通知
    console.log(`Created article: ${result.title}`);
  },
};

10. 框架选择指南与比较

10.1 框架特性对比

框架特性对比
性能
学习曲线
开发速度
TypeScript支持
社区支持
企业适用性
Fastify > Koa > Express > Nest > Adonis
Express < Koa < Fastify < Nest < Adonis
Adonis > Nest > Express > Koa > Fastify
Nest > Adonis > Next > Express/Koa/Fastify
Express > Next > Nest > Koa > Fastify > Adonis
Nest > Adonis > Express > Fastify > Koa

10.2 适用场景选择

mindmap
  root((选择框架))
    微服务
      Fastify
      Nest.js
      Express
    企业应用
      Nest.js
      Loopback
      Hapi.js
    API开发
      Express
      Fastify
      Koa
      Loopback
    全栈应用
      Next.js
      AdonisJS
      Sails.js
    内容平台
      Strapi
      Next.js
    实时应用
      Sails.js
      Socket.io + Express

结语
感谢您的阅读!期待您的一键三连!欢迎指正!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2383414.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Vite创建一个动态网页的前端项目

1. 引言 虽然现在的前端更新换代的速度很快&#xff0c;IDE和工具一批批的换&#xff0c;但是我们始终要理解一点基本的程序构建的思维&#xff0c;这些环境和工具都是为了帮助我们更快的发布程序。笔者还记得以前写前端代码的时候&#xff0c;只使用文本编辑器&#xff0c;然…

系统架构设计师案例分析题——web篇

软考高项系统架构设计师&#xff0c;其中的科二案例分析题为5选3&#xff0c;总分75达到45分即合格。本贴来归纳web设计题目中常见的知识点即细节&#xff1a; 目录 一.核心知识 1.常见英文名词 2.私有云 3.面向对象三模型 4.计网相关——TCP和UDP的差异 5.MQTT和AMQP协…

MySQL--day5--多表查询

&#xff08;以下内容全部来自上述课程&#xff09; 多表查询 1. 为什么要用多表查询 # 如果不用多表查询 #查询员工名为Abel的人在哪个城市工作? SELECT* FROM employees WHERE last_name Abel;SELECT * FROM departments WHERE department_id 80;SELECT * FROM locati…

leetcode hot100刷题日记——7.最大子数组和

class Solution { public:int maxSubArray(vector<int>& nums) {//方法一&#xff1a;动态规划//dp[i]表示以i下标结尾的数组的最大子数组和//那么在i0时&#xff0c;dp[0]nums[0]//之后要考虑的就是我们要不要把下一个数加进来&#xff0c;如果下一个数加进来会使结…

基于Spring Boot和Vue的在线考试系统架构设计与实现(源码+论文+部署讲解等)

源码项目获取联系 请文末卡片dd我获取更详细的演示视频 系统介绍 基于Spring Boot和Vue的在线考试系统。为学生和教师/管理员提供一个高效、便捷的在线学习、考试及管理平台。系统采用前后端分离的架构&#xff0c;后端基于成熟稳定的Spring Boot框架&#xff0c;负责数据处理…

Android 绘制折线图

用了一段时间的 Jetpack Compose ,感觉写 UI 的效率确实会提升不少 。 配合 AI 编程绘制了一个折线图。供大家学习参考! @Composable fun TemperatureChart() {val timeLabels = listOf("7:00", "8:00", "9:00", "10:00", "11:…

自建srs实时视频服务器支持RTMP推流和拉流

文章目录 一、整体示意图二、服务器端1.srs简介及架构2.docker方式安装3.k8s方式安装4.端口 三、推流端1.OBS Studio2.ffmpeg推流3.streamlabs苹果手机4.twire安卓手机5.网络推流摄像头 四、拉流端1.vlc2.srs 参考awesome系列&#xff1a;https://github.com/juancarlospaco/aw…

Spring IOCDI————(2)

DI详解 我们之前讲了控制反转IOC&#xff0c;也就是bean的存&#xff0c;那么我们还需要Bean的取&#xff0c;就是DI了&#xff0c;DI翻译过来就是依赖注入&#xff0c;啥意思呢&#xff0c;就是我们通过IOC容器&#xff0c;把所有的对象交给Spring管理&#xff0c;我们指定哪…

融云 uni-app IMKit 上线,1 天集成,多端畅行

融云 uni-app IMKit 正式上线&#xff0c;支持一套代码同时运行在 iOS、Android、H5、小程序主流四端&#xff0c;集成仅需 1 天&#xff0c;并可确保多平台的一致性体验。 融云 uni-app IMKit 在 Vue 3 的高性能加持下开发实现&#xff0c;使用 Vue 3 Composition API&#x…

篇章五 项目创建

目录 1.创建一个SpringBoot项目 2.创建核心类 2.1 Exchange类 2.2 MessageQueue类 2.3 Binding类 2.4 Message类 1.Message的组成 2.逻辑删除 3.工厂方法 4.序列化与反序列化 5.offsetBeg和offsetEnd 1.创建一个SpringBoot项目 1.点击 2.填写表单 3.添加依赖 2.创建…

aws平台s3存储桶夸域问题处理

当我们收到开发反馈s3存在跨域问题 解决步骤&#xff1a; 配置 S3 存储桶的 CORS 设置&#xff1a; 登录到 AWS 管理控制台。转到 S3 服务。选择你存储文件的 存储桶。点击 权限 标签页。在 跨域资源共享&#xff08;CORS&#xff09;配置 部分&#xff0c;点击 编辑。 登陆…

【vue-text-highlight】在vue2的使用教程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、下载二、使用步骤1.引入库2.用法 效果速通 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;随着人工智能的不断发…

pycharm无法正常调试问题

pycharm无法正常调试问题 1.错误代码 已连接到 pydev 调试器(内部版本号 231.8109.197)Traceback (most recent call last):File "E:\Python\pycharm\PyCharm 2023.1\plugins\python\helpers\pydev\_pydevd_bundle\pydevd_comm.py", line 304, in _on_runr r.deco…

Leetcode百题斩-哈希

看来面试前还是要老老实实刷leetcode为好&#xff0c;今天看到一个题库&#xff0c;leetcode百题斩&#xff0c;刚好最近面试的这两题全在里面。瞄了一眼&#xff0c;也有不少题之前居然也刷过。那么&#xff0c;冲冲冲&#xff0c;看多久能把这百题刷完。 第一天&#xff0c;先…

EXIST与JOIN连表比较

结论 1&#xff1a;EXIST可以用于链表&#xff0c;且可以利用到索引2&#xff1a;当join无法合理利用到索引&#xff0c;可以尝试EXIST链表3&#xff1a;EXIST在某些情况下可以更好地利用到索引4&#xff1a;大数据量时&#xff0c;要考虑EXIST的使用 EXIST SQL: EXPLAN JOIN…

【Linux】利用多路转接epoll机制、ET模式,基于Reactor设计模式实现

&#x1f4da; 博主的专栏 &#x1f427; Linux | &#x1f5a5;️ C | &#x1f4ca; 数据结构 | &#x1f4a1;C 算法 | &#x1f152; C 语言 | &#x1f310; 计算机网络 上篇文章&#xff1a;多路转接epoll&#xff0c;实现echoserver 至此&#xff0c;Linux与…

react中运行 npm run dev 报错,提示vite.config.js出现错误 @esbuild/win32-x64

在React项目中运行npm run dev时&#xff0c;如果遇到vite.config.js报错&#xff0c;提示esbuild/win32-x64在另一个平台中被使用&#xff0c;通常是由于依赖冲突或缓存问题导致的。解决方法是删除node_modules文件夹&#xff0c;并重新安装依赖。 如下图&#xff1a; 解决办…

鸿蒙UI开发——Builder与LocalBuilder对比

1、概 述 在ArkUI中&#xff0c;有的朋友应该接触过Builder和LocalBuilder。其中有了LocalBuilder的存在&#xff0c;是为了解决组件的父子关系和状态管理的父子关系保持一致的问题。 这里面最直观的表现则是this的指向问题与组件刷新问题&#xff0c;本文对Builder与LocalBu…

关于光谱相机的灵敏度

一、‌灵敏度的核心定义‌ ‌光谱灵敏度&#xff08;单色灵敏度&#xff09;‌ 描述光谱相机对单色辐射光的响应能力&#xff0c;即探测器对特定波长入射光的输出信号强度与入射光功率的比值。 例如&#xff0c;若在680nm波长下的光谱灵敏度较高&#xff0c;则表示该相机对此…

Model 速通系列(一)nanoGPT

这个是新开的一个系列用来手把手复现一些模型工程&#xff0c;之所以开这个系列是因为有人留言说看到一个工程不知道从哪里读起&#xff0c;出于对自身能力的提升与兴趣&#xff0c;故新开了这个系列。由于主要动机是顺一遍代码并提供注释。 该系列第一篇博客是 nanoGPT &…