NestJs 从入门到实战项目笔记

  • 时间:2025-12-03 22:14 作者: 来源: 阅读:0
  • 扫一扫,手机访问
摘要:C controller 控制用于处理路由请求路由的三种参数 Param Query BodyParam: restful API 参数Query:url 参数Body:post 参数Param 就是获取 /xxx/:id@Get('/data/:id') getData(@Param() param): string { #技术分享  console.log('

C controller 控制

用于处理路由请求

路由的三种参数 Param Query Body

Param: restful API 参数

Query:url 参数

Body:post 参数

Param 就是获取 /xxx/:id

@Get('/data/:id')
getData(@Param() param): string { #技术分享
  console.log(' ~ AppController ~ getData ~ param:', param)
  return 'data' +

}  @Controller('user') export class UserController { @Get('/:id') getUser(@Param('id', ParseIntPipe) id: number) { console.log(' ~ UserController ~ id:', typeof id)  return 'get user' + id } } 

Body

@Post('/data')
  postData(@Body() body): string {
    console.log(' ~ AppController ~ postData ~ body:', body)
    return 'post data'
  }

Query /xxx/xxx?id=xxx¶m=222

@Get('/data/:id')
  getData(@Param() param, @Query() query): string {
    console.log(' ~ AppController ~ getData ~ param:', param)
    console.log(' ~ AppController ~ getData ~ query:', query)
    return 'data' + param.id
  }

providers 提供函数方法

就是提供方法 哪里需要使用这个方法就在哪里进行注入

实则拿 koa2 来进行举例就是

controller ​是进行路由对接的 然后执行具体的函数方法 是在 service 里面执行的 数据库的修改就是进一层的里

import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

@Get('/data/:id')
  getData(@Param() param): string {
    return this.appService.getData(param)
  }
import { Injectable } from '@nestjs/common'

@Injectable()
export class AppService {
  getData(param: any) {
    console.log(' ~ AppService ~ getData ~ param:', param)
    return 'data' + param.id
  }
}

异常处理器

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common'
import { Request, Response } from 'express'

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp()
    const response = ctx.getResponse<Response>()
    const request = ctx.getRequest<Request>()
    const status = exception.getStatus()

    response.status(status).json({
      statusCode: status,
      message: exception.message,
      type: 'error',
      timestamp: new Date().toISOString(),
      path: request.url,
    })
  }
}

main.ts


import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'
import { HttpExceptionFilter } from './common/exception/http-exception.filter'
import { VersioningType } from '@nestjs/common'

async function bootstrap() {
  const app = await NestFactory.create(AppModule)

  app.setGlobalPrefix('api')
  app.enableVersioning({ type: VersioningType.URI, defaultVersion: '1' })

  app.useGlobalFilters(new HttpExceptionFilter())

  await app.listen(3000)
}
bootstrap().catch((err) => console.error(err))

C config 配置文件

安装配置依赖

pnpm add @nestjs/config

根目录下创建配置文件 .env (该文件不进行提交) 我们创建.env.example 进行提交到代码仓库

.env

APP_NAME=nest-admin
​

DB_TYPE=mysql DB_HOST=localhost DB_PORT=3306 DB_USERNAME= DB_PASSWORD= DB_DATABASE= DB_SYNCHRONIZE=false

创建 config 模块文件

./common/config

import { registerAs } from '@nestjs/config'

export default registerAs('app', () => {
  return {
    name: process.env.APP_NAME,
    
  }
})


import { registerAs } from '@nestjs/config'

export default registerAs('database', () => {
  return {
    type: process.env.DB_TYPE || 'mysql',
    host: process.env.DB_HOST || 'localhost',
    port: parseInt(process.env.DB_PORT, 10) || 3306,
    username: process.env.DB_USERNAME,
    password: process.env.DB_PASSWORD,
    database: process.env.DB_DATABASE,
    synchronize: process.env.DB_SYNCHRONIZE === 'true',
  }
})



import appConfig from './app.config'
import dbConfig from './db.config'

export default [appConfig, dbConfig]

再app.module.ts 进行导入使用

import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'
import { UserModule } from './modules/user/user.module'
import { AuthController } from './modules/auth/auth.controller'
import { AuthModule } from './modules/auth/auth.module'
import { ConfigModule } from '@nestjs/config'
import config from './common/config'

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [...config],
    }),
    UserModule,
    AuthModule,
  ],
  controllers: [AppController, AuthController],
  providers: [AppService],
})
export class AppModule {}

再具体的模块之中进行使用

import { Controller, Get, Inject } from '@nestjs/common'
import { ConfigType } from '@nestjs/config'
import appConfig from './common/config/app.config'

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    
    @Inject(appConfig.KEY) private readonly app: ConfigType<typeof appConfig>,
  ) {}

  @Get('/test')
  getTest(): string {
    console.log(' ~ AppController ~ getTest ~ this.app.name:', this.app)
    return this.app.name
  }

}

连接数据库与操作流程

mysql 数据库创建

数据库名: admin-dev
字符集: utf8
排序规则: utf8 general ci
pnpm install --save @nestjs/typeorm typeorm mysql2
  • 连接数据库
import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'
import { UserModule } from './modules/user/user.module'
import { AuthController } from './modules/auth/auth.controller'
import { AuthModule } from './modules/auth/auth.module'
import { ConfigModule, ConfigService } from '@nestjs/config'
import config from './common/config'
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [...config],
    }),
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (configService: ConfigService) =>

({ type: configService.get('database.type'), host: configService.get('database.host'), port: configService.get('database.port'), username: configService.get('database.username'), password: configService.get('database.password'), database: configService.get('database.database'), synchronize: configService.get('database.synchronize'), autoLoadEntities: true, }) as TypeOrmModuleOptions, }), UserModule, AuthModule, ], controllers: [AppController, AuthController], providers: [AppService], }) export class AppModule {} 
  • 定义数据模型
import { Column, Entity, PrimaryGeneratedColumn, Unique } from 'typeorm'

@Entity('admin_user')
export class User {
  @PrimaryGeneratedColumn()
  id: number

  @Column()
  @Unique(['username'])
  username: string

  @Column()
  password: string

  @Column()
  role: string

  @Column()
  nickname: string

  @Column()
  active: boolean
}

  • 当前哪一个module需要使用就引入 实体
import { Module } from '@nestjs/common'
import { UserController } from './user.controller'
import { TypeOrmModule } from '@nestjs/typeorm'
import { User } from './user.entity'
import { UserService } from './user.service'

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  controllers: [UserController],
  providers: [UserService],
})
export class UserModule {}

  • 再具体模块的service进行实体使用
import { Injectable } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { User } from './user.entity'
import { Repository } from 'typeorm'

@Injectable()
export class UserService {
  constructor(
    
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
  ) {}

  findOne(id: number) {
    
    return this.userRepository.findOne({ where: { id } })
  }
}

  • service 查询然后返回给controller进行使用
import { Controller, Get, Param, ParseIntPipe } from '@nestjs/common'
import { UserService } from './user.service'

@Controller('user')
export class UserController {
  
  constructor(private readonly userService: UserService) {}

  @Get('/:id')
  
  getUser(@Param('id', ParseIntPipe) id: number) {
    return this.userService.findOne(id)
  }
}

守卫/全局守卫


nest g gu modules/auth
import { Module } from '@nestjs/common'
import { AuthService } from './auth.service'
import { AuthController } from './auth.controller'
import { APP_GUARD } from '@nestjs/core'
import { AuthGuard } from './auth.guard'

@Module({
  controllers: [AuthController],
  providers: [
    AuthService,
    {
      
      provide: APP_GUARD,
      useClass: AuthGuard,
    },
  ],
})
export class AuthModule {}

如果只是定义单个的守卫 那么就不需要再 这个module里面写任何东西 只需要创建一个守卫 然后哪里需要哪里注入即可

这里我们注册的是全局路由守卫 就是每一个路由请求都会进入到这个守卫里面

  • 定义一个聚合装饰器,将标记公共装饰器和守卫装饰器聚合
import { applyDecorators, SetMetadata, UseGuards } from '@nestjs/common'
import { AuthGuard } from './auth.guard'

export const IS_PUBLIC_KEY = 'isPublic'
export function Auth() {
  
  
  
  return applyDecorators(SetMetadata(IS_PUBLIC_KEY, true), UseGuards(AuthGuard))
}

  • 全局守卫(基础版本) 固定写法课参照文档 全局守卫
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'
import { Reflector } from '@nestjs/core'
import { Observable } from 'rxjs'
import { IS_PUBLIC_KEY } from './auth.decorator'

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ])

    
    if (isPublic) {
      return true
    }
    return false
  }
}

使用


import { Controller, Post } from '@nestjs/common'
import { Auth } from './auth.decorator'

@Controller('auth')
export class AuthController {
  @Auth()  
  @Post('login')
  login() {
    return 'login'
  }
}

  • 全部评论(0)
最新发布的资讯信息
【系统环境|】创建一个本地分支(2025-12-03 22:43)
【系统环境|】git 如何删除本地和远程分支?(2025-12-03 22:42)
【系统环境|】2019|阿里11面+EMC+网易+美团面经(2025-12-03 22:42)
【系统环境|】32位单片机定时器入门介绍(2025-12-03 22:42)
【系统环境|】从 10 月 19 日起,GitLab 将对所有免费用户强制实施存储限制(2025-12-03 22:42)
【系统环境|】价值驱动的产品交付-OKR、协作与持续优化实践(2025-12-03 22:42)
【系统环境|】IDEA 强行回滚已提交到Master上的代码(2025-12-03 22:42)
【系统环境|】GitLab 15.1发布,Python notebook图形渲染和SLSA 2级构建工件证明(2025-12-03 22:41)
【系统环境|】AI 代码审查 (Code Review) 清单 v1.0(2025-12-03 22:41)
【系统环境|】构建高效流水线:CI/CD工具如何提升软件交付速度(2025-12-03 22:41)
手机二维码手机访问领取大礼包
返回顶部