【Node.js】Web开发框架
个人主页: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框架生态
1.3 框架选择考虑因素
mindmaproot((Web框架选择))性能需求高并发应用低延迟资源消耗开发效率开发速度学习曲线社区支持项目复杂度小型项目中型应用企业级应用团队技能TypeScript经验现有框架经验架构偏好生态系统中间件ORM支持插件丰富度应用类型REST APIGraphQL实时应用静态网站
2. Express.js
2.1 Express.js概述
Express.js是Node.js最流行的Web框架,提供了简单而灵活的API,适用于各种Web应用和API开发。
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); // 客户端IPconsole.log(req.path); // 请求路径console.log(req.method); // HTTP方法// 响应对象(res)res.status(200); // 设置状态码res.set('Content-Type', 'application/json'); // 设置响应头res.cookie('name', 'value', { maxAge: 900000 }); // 设置cookieres.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特性提供更简洁的中间件机制。
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' }; // 响应体// Cookiesctx.cookies.set('name', 'value', { maxAge: 86400000 });const cookie = ctx.cookies.get('name');
});
3.4 Koa与Express对比
4. Nest.js
4.1 Nest.js概述
Nest.js是一个用于构建高效、可靠、可扩展的服务器端应用程序的渐进式Node.js框架,它结合了面向对象编程、函数式编程和函数响应式编程的元素。
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 依赖注入
// 定义提供者
@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,适合构建高性能的服务。
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性能对比
bartitle 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路由等。
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 数据获取方法
// 服务器端渲染示例 (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和服务。
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/jwtconst 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)的开发体验。
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等功能。
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框架
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 - 内容管理框架
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;// 自动生成slugif (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 框架特性对比
10.2 适用场景选择
mindmaproot((选择框架))微服务FastifyNest.jsExpress企业应用Nest.jsLoopbackHapi.jsAPI开发ExpressFastifyKoaLoopback全栈应用Next.jsAdonisJSSails.js内容平台StrapiNext.js实时应用Sails.jsSocket.io + Express
结语
感谢您的阅读!期待您的一键三连!欢迎指正!
相关文章:

【Node.js】Web开发框架
个人主页:Guiat 归属专栏:node.js 文章目录 1. Node.js Web框架概述1.1 Web框架的作用1.2 Node.js主要Web框架生态1.3 框架选择考虑因素 2. Express.js2.1 Express.js概述2.2 基本用法2.2.1 安装Express2.2.2 创建基本服务器 2.3 路由2.4 中间件2.5 请求…...

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

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

MySQL--day5--多表查询
(以下内容全部来自上述课程) 多表查询 1. 为什么要用多表查询 # 如果不用多表查询 #查询员工名为Abel的人在哪个城市工作? SELECT* FROM employees WHERE last_name Abel;SELECT * FROM departments WHERE department_id 80;SELECT * FROM locati…...
【Redis】AOF日志的三种写回机制
目录 1、背景2、appendfsync always(同步写回)【1】工作机制【2】特点【3】实现原理 3、appendfsync everysec(每秒写回,默认配置)【1】工作机制【2】特点【3】实现原理 4、appendfsync no(操作系统控制&am…...

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

基于Spring Boot和Vue的在线考试系统架构设计与实现(源码+论文+部署讲解等)
源码项目获取联系 请文末卡片dd我获取更详细的演示视频 系统介绍 基于Spring Boot和Vue的在线考试系统。为学生和教师/管理员提供一个高效、便捷的在线学习、考试及管理平台。系统采用前后端分离的架构,后端基于成熟稳定的Spring Boot框架,负责数据处理…...
MySQL Workbench 工具导出与导入数据库:实用指南
目录 一、MySQL Workbench 简介二、导出数据库2.1 打开 MySQL Workbench2.2 数据库导出步骤三、导入数据库3.1 打开 MySQL Workbench3.2 数据库导入步骤四、注意事项五、总结MySQL Workbench 是一款强大的数据库管理和开发工具,它提供了直观的图形界面,方便用户进行数据库的设…...

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系列:https://github.com/juancarlospaco/aw…...
ubuntu22.04 卸载ESP-IDF
要在Ubuntu 22.04上完全卸载ESP-IDF,请按照以下步骤操作: 卸载ESP-IDF的步骤 删除ESP-IDF目录: # 假设ESP-IDF安装在~/esp/esp-idf目录 rm -rf ~/esp/esp-idf删除ESP-IDF工具链和下载的工具: rm -rf ~/.espressif从PATH中移除ESP…...

Spring IOCDI————(2)
DI详解 我们之前讲了控制反转IOC,也就是bean的存,那么我们还需要Bean的取,就是DI了,DI翻译过来就是依赖注入,啥意思呢,就是我们通过IOC容器,把所有的对象交给Spring管理,我们指定哪…...
80. Java 枚举类 - 使用枚举实现单例模式
文章目录 80. Java 枚举类 - 使用枚举实现单例模式**1️⃣ 为什么用枚举实现单例?****2️⃣ 枚举实现单例模式****3️⃣ 枚举单例如何防止反射攻击?****4️⃣ 枚举单例如何防止反序列化破坏?****5️⃣ 枚举单例 vs 传统单例****6️⃣ 枚举单例…...

融云 uni-app IMKit 上线,1 天集成,多端畅行
融云 uni-app IMKit 正式上线,支持一套代码同时运行在 iOS、Android、H5、小程序主流四端,集成仅需 1 天,并可确保多平台的一致性体验。 融云 uni-app IMKit 在 Vue 3 的高性能加持下开发实现,使用 Vue 3 Composition API&#x…...
Java中的集合详解
下面是文章详细介绍了 Java 集合框架的基本思路、主要接口与实现、各类集合之间的区别与各自的适用场景,以及一些常见的使用技巧和最佳实践,供你参考。 Java中的集合详解 在 Java 开发中,集合(Collection)作为存储和操…...
利用 Java 爬虫根据关键词获取某手商品列表
在电商领域,根据关键词获取商品列表是常见的需求。某手作为国内知名的电商平台,提供了丰富的商品资源。通过 Java 爬虫技术,我们可以高效地根据关键词获取某手商品列表,并提取商品的基本信息。本文将详细介绍如何利用 Java 爬虫根…...
Axure项目实战:智慧运输平台后台管理端-订单管理2(多级交互)
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢!如有帮助请订阅专栏! Axure产品经理精品视频课已登录CSDN可点击学习https://edu.csdn.net/course/detail/40420 课程主题:订单管理2 主要内容:中继器筛选、表单跟随菜单拖动、审批数据互通等 应用场景:订单管理…...

篇章五 项目创建
目录 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.创建…...
Ntfs!ATTRIBUTE_RECORD_HEADER结构$INDEX_ROOT=0x90的一个例子
Ntfs!ATTRIBUTE_RECORD_HEADER结构$INDEX_ROOT0x90的一个例子 1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_FILE_RECORD_SEGMENT_HEADER *)0xc431a400) ((Ntfs!_FILE_RECORD_SEGMENT_HEADER *)0xc431a400) : 0xc431a400 [Type: _FILE_RECORD_SEGMENT_HEADER …...
AGI大模型(30):LangChain链的基本使用
为开发更复杂的应用程序,需要使用Chain来链接LangChain中的各个组件和功能,包括模型之间的链接以及模型与其他组件之间的链接。 链在内部把一系列的功能进行封装,而链的外部则又可以组合串联。 链其实可以被视为LangChain中的一种基本功能单元。 API地址:https://python.…...
代码随想录算法训练营第六十六天| 图论11—卡码网97. 小明逛公园,127. 骑士的攻击
继续补,又是两个新算法,继续进行勉强理解,也是训练营最后一天了,六十多天的刷题告一段落了! 97. 小明逛公园 97. 小明逛公园 感觉还是有点难理解原理 Floyd 算法对边的权值正负没有要求,都可以处理。核心…...
[创业之路-364]:企业战略管理案例分析-5-战略制定-宇树科技的使命、愿景、价值观的演变过程
目录 一、宇树科技的使命、愿景、价值观的演变过程 初创阶段(2016 年成立前后):以技术梦想奠基,明确核心使命愿景 发展阶段(2017 - 2023 年):技术突破与市场拓展,价值观逐步成型 …...
React--函数组件和类组件
React 中的函数组件和类组件是两种定义组件的方式,它们有以下主要区别: 1. 语法与定义方式 函数组件: 是 JavaScript 函数,接收 props 作为参数,返回 JSX。 const MyComponent (props) > {return <div>Hell…...
Flask 路由装饰器:从 URL 到视图函数的优雅映射
前置知识,关于Python装饰器的语法,链接:Python 装饰器:从“语法糖”到“代码神器”的深度解析 1、路由装饰器的功能:给 URL 贴 “功能标签” 在 Flask 开发中,你一定见过这样的代码: from fla…...
DDoS防护实战——从基础配置到高防IP部署
一、基础防护:服务器与网络层加固 Linux内核优化: 调整TCP协议栈参数,缓解SYN Flood攻击: # 启用SYN Cookie并减少超时时间 echo 1 > /proc/sys/net/ipv4/tcp_syncookies echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout…...

aws平台s3存储桶夸域问题处理
当我们收到开发反馈s3存在跨域问题 解决步骤: 配置 S3 存储桶的 CORS 设置: 登录到 AWS 管理控制台。转到 S3 服务。选择你存储文件的 存储桶。点击 权限 标签页。在 跨域资源共享(CORS)配置 部分,点击 编辑。 登陆…...
HOT100(二叉树)
二叉树 二叉树的中序遍历 class Solution { public:void traversal(TreeNode* root, vector<int> & vec){if(root nullptr) return;traversal(root->left, vec);vec.push_back(root->val);traversal(root->right, vec);}vector<int> inorderTraver…...

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

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…...
springboot3.4.5-springsecurity+session
创建springboot项目,添加以下依赖: LombokSpring WebSpring SecuritySpring Data JDBCMyBatis FrameworkMySQL Driver 添加fastjson2进行序列化和反序列化 <dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>f…...