-
Learn the decorator syntax and feel its simplicity and beauty; -
Learn a new development framework by yourself, feel the advantages and disadvantages of different frameworks, and lay the foundation for future development and selection; -
Feel the complexity of server-side troubleshooting and find inspiration for front-end design.
-
https://www.geeksforgeeks.org/best-nodejs-frameworks-for-app-development/ -
https://anywhere.epam.com/business/best-node-js-frameworks
-
[Required] There is no database, the interface request is completed, and it can run; -
[Required] Create the basic database MySQL and access the @nestjs/sequelize library to complete the add, delete, modify and query functions: CRUD -
[Optional] We plan to use Graphql to process API queries to achieve accurate data query. This has been popular for a long time, and we plan to use it directly in business in the future. -
[Optional] Connect to Swagger to automatically generate API documents and quickly conduct joint debugging and testing of front-end and back-end services. Swagger is an open source tool for designing, building, documenting and consuming RESTful web services. -
[Optional] Interface request, database optimization processing
-
Request offloading, database write locking, and concurrent process processing -
Add middleware to uniformly process requests and responses, perform authentication processing, request interception and other operations -
Database split backup, database disaster recovery processing, divided into: primary, backup, disaster -
Database reading and writing are separated, data is double-written, a database caching mechanism is established, and redis is used for processing.
# 进入文件夹目录
cd full-stack-demo/packages
# 安装脚手架
npm i -g @nestjs/cli
# 创建基础项目
nest new node-server-demo
# 进入项目
cd new node-server-demo
# 运行项目测试
npm run start:dev
-
common - public method class -
config - configuration class file -
controller - controller, used to handle various requests initiated by the front end -
service - service class, used to handle interaction logic with the database -
dto - DTO (Data Transfer Object) can be used to validate input data and limit the fields or formats transferred. -
entities - entity class, used to describe object-related attribute information -
module - module, used to register all service classes and controller classes, similar to beans in Spring
These are not completely equivalent. The two implementation mechanisms are different. It is just to help everyone understand.
main.ts - nest startup entry
types - typescript related declaration types
-
controllercontroller
// packages/node-server-demo/src/controller/user/index.ts
import { Controller, Get, Query } from '@nestjs/common';
import UserServices from '@/service/user';
import { GetUserDto, GetUserInfoDto } from '@/dto/user';
export class UserController {
constructor(private readonly userService: UserServices) {}
// Get 请求 user/name?name=bricechou
async findByName( getUserDto: GetUserDto) {
return this.userService.read.findByName(getUserDto.name);
}
// Get 请求 user/info?id=123
async findById( getUserInfoDto: GetUserInfoDto) {
const user = await this.userService.read.findById(getUserInfoDto.id);
return { gender: user.gender, job: user.job };
}
}
// packages/node-server-demo/src/controller/log/add.ts
import { Controller, Post, Body } from '@nestjs/common';
import { AddLogDto } from '@/dto/log';
import LogServices from '@/service/log';
'log') (
export class CreateLogController {
constructor(private readonly logServices: LogServices) {}
// post('/log/add')
'add') (
create( () createLogDto: AddLogDto) {
return this.logServices.create.create(createLogDto);
}
}
-
Data TransferData Transfer Object
// packages/node-server-demo/src/dto/user.ts
export class CreateUserDto {
name: string;
age: number;
gender: string;
job: string;
}
// 可以分开写,也可以合并
export class GetUserDto {
id?: number;
name: string;
}
// 可以分开写,也可以合并
export class GetUserInfoDto {
id: number;
}
-
service database interaction processing class
// packages/node-server-demo/src/service/user/read.ts
import { Injectable } from '@nestjs/common';
import { User } from '@/entities/User';
()
export class ReadUserService {
constructor() {}
async findByName(name: string): Promise<User> {
// 可以处理判空,从数据库读取/写入数据,可能会被多个 controller 进行调用
console.info('ReadUserService findByName > ', name);
return Promise.resolve({ id: 1, name, job: '程序员', gender: 1, age: 18 });
}
async findById(id: number): Promise<User> {
console.info('ReadUserService findById > ', id);
return Promise.resolve({
id: 1,
name: 'BriceChou',
job: '程序员',
gender: 1,
age: 18,
});
}
}
-
module module registration, service class/control class
// packages/node-server-demo/src/module/user.ts
import { Module } from '@nestjs/common';
import UserService, { ReadUserService } from '@/service/user';
import { UserController } from '@/controller/user';
@Module({
providers: [UserService, ReadUserService],
controllers: [UserController],
})
export class UserModule {}
// packages/node-server-demo/src/module/index.ts 根模块注入
import { Module } from '@nestjs/common';
import { UserModule } from './user';
import { LogModule } from './log';
@Module({
imports: [
UserModule,
LogModule,
],
})
export class AppModule {}
-
main.js starts all registered classes
// packages/node-server-demo/src/main.ts
import { AppModule } from '@/module';
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// 监听端口 3000
await app.listen(3000);
}
bootstrap();
-
Note: You must set a password for the installed database, and you must have a password to connect to the database, otherwise the database connection will fail. -
For MySQL, we only need to install the database. If you are familiar with the instructions, you can just operate it directly from the command line. -
If you are not familiar with it, then download the graphical management tool.
-
PRIMARY KEY 是表中的一个或多个列的组合,它用于唯一标识表中的每一行。 -
Not NULL 和 Unique 就不解释,就是直译的那个意思。 -
GENERATED 生成列是表中的一种特殊类型的列,它的值不是从插入语句中获取的,而是根据其他列的值通过一个表达式或函数生成的。
CREATE TABLE people (
first_name VARCHAR(100),
last_name VARCHAR(100),
full_name VARCHAR(200) AS (CONCAT(first_name, ' ', last_name))
);
-
UNS IGNED 这个数值类型就只能存储正数(包括零),不会存储负数。 -
ZEROFILL 将数值类型的字段的前面填充零,他会自动使字段变为 UNSIGNED,直到该字段达到声明的长度,如: 00007 -
BINARY 用于存储二进制字符串,如声明一个字段为 BINARY(5),那么存储在这个字段中的字符串都将被处理为长度为 5 的二进制字符串。
-
此外也可顺手创建一个索引,方便快速查找。
CREATE TABLE `rrweb`.`test_sys_req_log` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`content` TEXT NOT NULL,
`l_level` INT UNSIGNED NOT NULL,
`l_category` VARCHAR(255) NOT NULL,
`l_created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`l_updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
INDEX `table_index` (`l_level` ASC, `l_category` ASC, `l_time` ASC) VISIBLE);
3.连接数据库
-
安装 Sequelize
# 安装连接库
npm install --save @nestjs/sequelize sequelize sequelize-typescript mysql2
# 安装 type
npm install --save-dev @types/sequelize
-
配置数据库基础信息
// packages/node-server-demo/src/module/index.ts
import { Module } from '@nestjs/common';
import { UserModule } from './user';
import { LogModule } from './log';
import { Log } from '@/entities/Log';
import { SequelizeModule } from '@nestjs/sequelize';
@Module({
imports: [
SequelizeModule.forRoot({
dialect: 'mysql',
// 按数据库实际配置
host: '127.0.0.1',
// 按数据库实际配置
port: 3306,
// 按数据库实际配置
username: 'root',
// 按数据库实际配置
password: 'hello',
// 按数据库实际配置
database: 'world',
synchronize: true,
models: [Log],
autoLoadModels: true,
}),
LogModule,
UserModule,
],
})
export class AppModule {}
-
实体与数据库一一映射处理
import { getNow } from '@/common/date';
import {
Model,
Table,
Column,
PrimaryKey,
DataType,
} from 'sequelize-typescript';
'test_sys_req_log' }) ({ tableName:
export class Log extends Model<Log> {
({
type: DataType.INTEGER,
autoIncrement: true,
field: 'id',
})
id: number;
'content', type: DataType.TEXT }) ({ field:
content: string;
'l_level', type: DataType.INTEGER }) ({ field:
level: number; // 3严重,2危险,1轻微
'l_category' }) ({ field:
category: string; // 模块分类/来源分类
({
field: 'l_created_at',
type: DataType.NOW,
defaultValue: getNow(),
})
createdAt: number;
({
field: 'l_updated_at',
type: DataType.NOW,
defaultValue: getNow(),
})
updatedAt: number;
}
-
module 注册实体
// packages/node-server-demo/src/module/log.ts
import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { Log } from '@/entities/Log';
import LogServices, {
CreateLogService,
UpdateLogService,
DeleteLogService,
ReadLogService,
} from '@/service/log';
import {
CreateLogController,
RemoveLogController,
UpdateLogController,
} from '@/controller/log';
@Module({
imports: [SequelizeModule.forFeature([Log])],
providers: [
LogServices,
CreateLogService,
UpdateLogService,
DeleteLogService,
ReadLogService,
],
controllers: [CreateLogController, RemoveLogController, UpdateLogController],
})
export class LogModule {}
-
service 操作数据库处理数据
import { Log } from '@/entities/Log';
import { Injectable } from '@nestjs/common';
import { AddLogDto } from '@/dto/log';
import { InjectModel } from '@nestjs/sequelize';
import { ResponseStatus } from '@/types/BaseResponse';
import { getErrRes, getSucVoidRes } from '@/common/response';
()
export class CreateLogService {
constructor(
(Log)
private logModel: typeof Log,
) {}
async create(createLogDto: AddLogDto): Promise<ResponseStatus<null>> {
console.info('CreateLogService create > ', createLogDto);
const { level = 1, content = '', category = 'INFO' } = createLogDto || {};
const str = content.trim();
if (!str) {
return getErrRes(500, '日志内容为空');
}
const item = {
level,
category,
// Tips: 为防止外部数据进行数据注入,我们可以对内容进行 encode 处理。
// content: encodeURIComponent(str),
content: str,
};
await this.logModel.create(item);
return getSucVoidRes();
}
}
-
C create 创建 -
R read 读取 -
U update 更新 -
D delete 删除
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { User } from './user.model';
()
export class UserService {
constructor(
(User)
private userModel: typeof User,
) {}
// 创建新数据
async create(user: User) {
const newUser = await this.userModel.create(user);
return newUser;
}
// 查找所有数据
async findAll() {
return this.userModel.findAll();
}
// 按要求查找单个
async findOne(id: string) {
return this.userModel.findOne({ where: { id } });
}
// 按要求更新
async update(id: string, user: User) {
await this.userModel.update(user, { where: { id } });
return this.userModel.findOne({ where: { id } });
}
// 按要求删除
async delete(id: string) {
const user = await this.userModel.findOne({ where: { id } });
await user.destroy();
}
}
本文分享自微信公众号 - 京东云开发者(JDT_Developers)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
{{o.name}}
{{m.name}}