官网API点击这里跳转

1.Authentication依赖包安装(passport-jwt)

yarn add @nestjs/passport passport passport-local @types/passport-local @nestjs/jwt passport-jwt @types/passport-jwt --save-dev

2.书写加密类,继承内置类、重写validate方法

// jwt.strategy.ts
import { Strategy } from 'passport-local';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { AuthService } from './auth.service';
 * * 我们遵循了之前描述的所有Passport策略。在我们使用passport-local的用例中,没有配置选项,所以我们的构造函数只是调用super(),没有选项对象。
 * 把用户信息存储到user中的类,继承内置类PassportStrategy、重写validate方法
@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy, 'encry') { // 继承PassportStrategy方法抛出的类,传递一个Strategy ,第二个参数是自定义的加密的字符串
    constructor(private readonly authService: AuthService) { // 依赖注入服务
        super(); // 并且调用父类的构造函数
    public async validate(username: string, password: string): Promise<any> {
        const user = await this.authService.validateUser(username, password); // (模拟)去数据库 验证是否成功
        if (!user) {
            throw new UnauthorizedException(); // 抛出未授权异常
        return user; // validate()方法返回的值自动创建一个对象,并将其分配给Request对象:获取例如:req.user
validate方法的两个参数,当使用守卫装饰路由后自动在body中注入成形参,然后提供给validate方法内部使用,当验证没有发生错误的情况下,数据在返回的时候被自动注入到request请求对象中,增加了一个user属性,里面包含了返回的数据,类型不限

validate由于继承了内置的类,所以只需要书写守卫装饰器,该方法会被系统自动调用

3.书写认证服务,模拟实现账号密码验证,登录成功生成token

// auth.service.ts
import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt'; // 引入jwt
 * 验证登录账号密码正确性,并产生token
 * @function validateUser 验证登录账号密码正确性
 * @function login 产生token
@Injectable()
export class AuthService {
    constructor(
        // private readonly usersService: UsersService,
        private readonly jwtService: JwtService,
    ) { }
     * 模拟数据库匹配账号密码
     * @param username 用户名
     * @param pass 密码
    public async validateUser(username: string, pass: string): Promise<any> {
		// 模拟数据
        const user = {
            id: '12fDAA267CCFa9932c',
            username: 'liu',
            password: '1111',
        // 模拟查询数据库,判断密码什么的是否正确
        if (user && user.password === pass) {
            const { password, ...result } = user;
            return result; // 然后返回除了密码的数据,给local.strategy.ts那边使用
        return null;
    public async login(user: any) { // 登录,创建一个登录的token并返回
        const { username, id } = user;
        const payload = { username, id };
        return {
           // 调用内置的nestjs的jwt生成token的对象方法
            token: 'Bearer ' + this.jwtService.sign(payload),

JwtService这个jwt内置服务,会提供生成token的对象方法,当然还需要在模块中配置一些对应的才能生效

4.创建一个路由控制器类,用于使用jwt安全认证,登录成功后生成token

// auth.controller.ts
import { Controller, Request, Post, UseGuards, Get } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { AuthService } from './auth.service';
 * @UseGuards(AuthGuard('local'))我们使用的AuthGuard是@nestjs/passport自动设置
@Controller('/auth')
export class AuthController {
	// 前面也提到过的,注入服务,提供给整个路由控制器类使用
    public constructor(private readonly authService: AuthService) { }
     * 使用jwt安全认证,登录成功后生成token
    @UseGuards(AuthGuard('encry')) // encry 自定义的,默认是local,在local.strategy.ts文件中修改
    @Post('/login')
    public async login(@Request() req): Promise<{ access_token: string }> { // 登录验证在authService里面的validateUser进行
        return this.authService.login(req.user); // 发送登录请求,获取token
AuthGuard守卫,内置安全认证的守卫,通过传递的字符串来辨别是验证数据还是token解析

1.默认情况下local字符串是对数据进行一系列操作,执行local.strategy.ts方法的validate

2.而后面使用的jwt字符串就是解析token的操作,会在Authentication字段中提取出token并解析出之前生成token放入的数据
3.默认情况下的这字符串可以修改,例如local.strategy.ts的PassportStrategy方法的第二个参数,就是自定义的字符串,然后使用也就用相应的字符串

这时候访问http://localhost:3000/auth/login是没有用的,因为我们还没配置对应的模块

5.配置模块,用于注册控制器,服务,内置jwt加解密模块

// auth.module.ts
import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { jwtConstants } from './constants';
import { LocalStrategy } from './local.strategy';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
@Module({
    imports: [
        JwtModule.register({
            secret: jwtConstants.secret, // 设置secret
            signOptions: { expiresIn: '36000s' }, // 设置token的属性,时间为3600*10就是十小时,其余配置可以看jwt的一些相关配置
        }),




    

    controllers: [AuthController], // 注册控制器
    providers: [AuthService, LocalStrategy], // 把AuthService,LocalStrategy注册成提供者
    exports: [AuthService], // 把这个服务抛出,给其他模块使用
export class AuthModule { }
constants.ts里面是一个常量对象,创建即可,密钥可以自定义
* jwt的密匙 export const jwtConstants = { secret: 'secretKey',
这样就注册了一个登录时候生成token的配置,也有设置了密钥和有效期

6.解析token,创建一个解析jwt的类

// jwt.strategy.ts
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import { jwtConstants } from './constants';
 * 解析token的类
 * * 命名策略,实现策略时,可以通过向PassportStrategy函数传递第二个参数来为其提供名称。如果你不这样做,每个策略都有一个默认名称(例如,jwt-strategy的'jwt'
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy/*, 'myjwt'*/) {// 自定义成myjwt后,解析也要使用myjwt
    constructor() {
        super({
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            ignoreExpiration: false,
            secretOrKey: jwtConstants.secret,
        });
    async validate({id, username}: any) {
        return { id , username };

区别不大,就是调用父类的时候,传递了三个参数

  • jwtFromRequest:接收一个passport-jwt对象的ExtractJwt的fromAuthHeaderAsBearerToken方法执行的结果(JwtFromRequestFunction类型)
  • ignoreExpiration 接收一个布尔类型,是否忽略过期时间,正常是false,不忽略过期
  • secretOrKey 就是加密的时候的密钥,需要一致才能解密
    validate,然后重写父类的这个方法会接收到一个token解析后的payload数据,和生成token所用的payload一致

7.解析token的服务配置到模块中

// auth.module.ts
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import { jwtConstants } from './constants';
import { LocalStrategy } from './local.strategy';
import { JwtStrategy } from './jwt.strategy';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
@Module({
    imports: [
        // PassportModule,使用@nestjs/passport里面的PassportModule模块
        // 使用该register()方法可以以相同的方式传递任何标准的Passport自定义选项。可用选项取决于正在实施的策略。
        PassportModule.register({ defaultStrategy: 'jwt'/*, session: true */ }), // 默认策略,之后在装饰器中使用就不需要传递
        JwtModule.register({
            secret: jwtConstants.secret, // 设置secret
            signOptions: { expiresIn: '36000s' }, // 设置token的属性,时间为3600*10就是十小时,其余配置可以看jwt的一些相关
        }),
    controllers: [AuthController], // 注册控制器
    providers: [AuthService, LocalStrategy, JwtStrategy], // 把AuthService,LocalStrategy,JwtStrategy注册成提供者
    exports: [AuthService], // 把这个服务抛出,给其他模块使用
export class AuthModule { }
 * 在第一种情况下(用户未登录),我们需要执行两个不同的功能:
 * * 限制未经身份验证的用户可以访问的路由(即拒绝访问受限制的路由)。我们将以熟悉的方式使用Guards来处理此功能,方法是在受保护的路由上放置一个Guard。
 * * 正如您所预料的那样,我们将在此Guard中检查是否存在有效的JWT,因此我们将在稍后成功发布JWT后继续使用此Guard。
增加了PassportModule.register模块和JwtStrategy这个自定义继承实现的服务

使用该register()方法可以以相同的方式传递任何标准的Passport自定义选项。可用选项取决于正在实施的策略。

PassportModule.register({ defaultStrategy: ‘jwt’/*, session: true */ }), // 默认策略,之后在装饰器中使用就不需要传递,相当于提取出来AuthGuard()传递的字符串’jwt’,默认就是jwt,也可以在jwt.strategy.ts里面设置PassportStrategy的第二个参数

8.在控制器路由中使用,加上以下路由方法

* 解析token并返回数据 // @UseGuards(AuthGuard('jwt')) @UseGuards(AuthGuard()) // 设置了默认策略之后 @Get('me') public getProfile(@Request() req): any { return req.user;
@UseGuards(AuthGuard('jwt'))方式是在注册的时候没有配置 defaultStrategy: 'jwt'的情况下使用的,配置了就不需要传递'jwt'字符串
这样访问http://localhost:3000/auth/me 并在请求头设置Authentication是登录生成的token即可

TypeORM连接使用Mysql数据库

8.TypeORM结合Nest的依赖库安装

yarn add @nestjs/typeorm typeorm mysql --save

9.创建数据库连接,单个数据库连接

// app.module.ts
import { Module } from '@nestjs/common';
// 使用typeorm
import { TypeOrmModule } from '@nestjs/typeorm';
import { Connection } from 'typeorm';
@Module({
  imports: [TypeOrmModule.forRoot(
    { // 注意:使用ts或者es6以上的方式,不支持ormconfig.json的方式
      type: 'mysql', // 类型
      host: 'localhost', // 本地host
      port: 3306, // 3306 mysql 端口号
      username: 'root', // mysql数据库账号
      password: 'password', // 数据库密码
      database: 'test', // 对应的数据库
      entities: [
        __dirname + '/**/entity/*.entity{.ts,.js}',
      synchronize: true,
    }),
export class AppModule {
  // 完成此操作后,TypeORM Connection和EntityManager对象将可用于**在整个项目中进行注入**(无需导入任何模块),
  public constructor(private readonly connection: Connection) { }
引入,配置数据库连接,entities是typeORM扫描的实体路径,当数据库中不存在该表/集合会创建

10.抽离出配置到ormconfig.json文件中,放置在和package.json文件同等目录下(记得不是src,是dist运行自动打包的项目目录)

"type": "mysql", "host": "localhost", "port" : 3306, "username": "root", "password": "test", "database": "test", "entities": [ "dist/**/entity/*.entity{.ts,.js}" "synchronize": true

11.创建实例类,与数据库字段一致

// entity/users.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Users {
    @PrimaryGeneratedColumn()
    id: number;
    @Column({ length: 100, update: false })
    username: string;
    @Column({ length: 100 })
    password: string;
    @Column({
        length: 10,
        default: 'admin',
        update: false,
    type: string;
    @Column({ length: 255 })
    header: string;
    @Column({ length: 100 })
    post: string;
    @Column({ length: 100 })
    info: string;
    @Column({ length: 100 })
    company: string;
    @Column({ length: 100 })
    salary: string;

typeorm的装饰器的一些使用,可以观看官方文档或者,本人写的恶补typeorm
Nest恶补Typeorm - Typeorm快速入门学习(结合typescript)

TypeOrm官方API文档,跳转

12.创建服务,用于注入查找数据

// users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Users } from './entity/users.entity';
@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(Users) // 注入实体,传递实体类参数
    private readonly usersRepository: Repository<Users>, // 类型为Repository的泛型类
  ) { }
  public findAll(): Promise<Users[]> {
    return this.usersRepository.find();

13.创建路由控制器

// users.controller.ts
import { Controller, Get, Post, Param } from '@nestjs/common';
import { Users } from './entity/users.entity';
import { UsersService } from './users.service';
@Controller('/user')
export class UsersController {
    public constructor(private readonly usersService: UsersService) { }
    @Get()
    public findAll(): Promise<Users[]> {
        return this.usersService.findAll(); // get请求查询全部user数据

14.创建模块,然后imports注入到app模块中

// users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { Users } from './entity/users.entity';
@Module({
  imports: [TypeOrmModule.forFeature([Users/*, 'name' */])], // 加入功能模块,为一个数组的实体类 , 第二个参数为一个字符串,表示你在连接数据库设置的name,也是标识多个数据库连接的name
  providers: [UsersService],
  controllers: [UsersController],
export class UsersModule { }

TypeOrmModule.forFeature(参数1,参数2) 加入功能模块,为一个数组的实体类 , 第二个参数为一个字符串,表示你在连接数据库设置的name,也是标识多个数据库连接的

引入模块到app.module.ts中
// app.module.ts
import { Module } from '@nestjs/common';
// 使用typeorm
import { TypeOrmModule } from '@nestjs/typeorm';
import { Connection } from 'typeorm';
import { UsersModule } from './users.module'
@Module({
  imports: [TypeOrmModule.forRoot(
      type: 'mysql', // 类型
      host: 'localhost', // 本地host
      port: 3306, // 3306 mysql 端口号
      username: 'root', // mysql数据库账号
      password: 'password', // 数据库密码
      database: 'test', // 对应的数据库
      entities: [
        __dirname + '/**/entity/*.entity{.ts,.js}',
      synchronize: true,
    }),
    UsersModule
export class AppModule {
  // 完成此操作后,TypeORM Connection和EntityManager对象将可用于**在整个项目中进行注入**(无需导入任何模块),
  public constructor(private




    
 readonly connection: Connection) { }
这样就可以使用typeOrm进行对数据库的操作了
public constructor(private readonly connection: Connection) {}

这个构造函数的目的是可以让Connection和EntityManager对象将可用于**在整个项目中进行注入**(无需导入任何模块)

15.使用Connection和EntityManager对象

// users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository, InjectConnection, InjectEntityManager } from '@nestjs/typeorm';
import { Repository, EntityManager, Connection } from 'typeorm';
import { Users } from './entity/users.entity';
@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(Users) // 注入实体,传递实体类参数
    private readonly usersRepository: Repository<Users>, // 类型为Repository的泛型类,生成两个参数,manager和metadata
    // 或者把连接数据库设置的name传递连接注入Connection或EntityManager
    @InjectConnection(/*'personsConnection'*/) // 获取对应的连接
    private readonly connection: Connection,
    @InjectEntityManager(/*'personsConnection'*/) // 获取注入的实体管理
    private readonly entityManager: EntityManager,
  ) { }
  public findAll(): Promise<Users[]> {
    return this.entityManager.find(Users);
    // or
    // return this.connection.manager.find(Users);
    // return this.usersRepository.find();
上面就使用了Connection对象和EntityManager对象,替换了前面的Repository泛型类的操作

16.自定义存储库,定制findById查询单个数据操作等

// custom.repository.ts
import { EntityRepository, Repository } from 'typeorm';
import { Users } from './entity/users.entity';
 * 定制存储库
 * * TypeORM提供了一个称为自定义存储库的功能。自定义存储库允许您扩展基本存储库类,并使用几种特殊方法对其进行丰富
 * * 下一步是将实例化责任委派给Nest。为此,我们必须将AuthorRepository类传递给TypeOrm.forFeature()方法。
 * * 之后在imports里面使用的TypeOrmModule.forFeature([Users] 替换成TypeOrmModule.forFeature([UsersRepository]
@EntityRepository(Users) // 扩展了基本的存储库操作等
export class UsersRepository extends Repository<Users> {
    constructor( // 使用Object.assign对this上面添加连接成功后的操作对象
        connection: Connection,
        super();
        Object.assign(this, connection.getRepository(Users));
  // 扩展基本库,增加以下方法,通过id查找单条数据
  public findById(id: number): Promise<Users> {
    return this.findOne({ id });
  // 扩展基本库,增加add这个增加数据的操作
  public add(users: Users): Promise<Users> {
    return this.save(users);
在存储库扩展的情况下,继承Repository<Users> 这个泛型类,可以使用先前默认的find,findOne....等等等增删改查的方法
替换掉全部使用Users实体的地方(users.module.ts和users.service.ts)
users.module.ts
// users.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule, getRepositoryToken } from '@nestjs/typeorm';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { UsersRepository } from './custom.repository';
@Module({
  // imports: [TypeOrmModule.forFeature([Users/*, 'name' */])], // 加入功能模块,为一个数组的实体类 , 第二个参数为一个字符串,表示你在连接数据库设置的name,也是标识多个数据库连接的name
  imports: [TypeOrmModule.forFeature([UsersRepository])], // 注入自定义扩展存储库后的实体
  providers: [UsersService],
  controllers: [UsersController],
export class UsersModule { }
users.service.ts
import { Injectable } from '@nestjs/common';
import { InjectConnection, InjectEntityManager } from '@nestjs/typeorm';
import { EntityManager, Connection } from 'typeorm';
import { Users } from './entity/users.entity';
import { UsersRepository } from './custom.repository';
@Injectable()
export class UsersService {
  constructor(
    private readonly usersRepository: UsersRepository, // 类型为Repository的泛型类,生成两个参数,manager和metadata
    // 或者把连接数据库设置的name传递连接注入Connection或EntityManager
    @InjectConnection(/*'personsConnection'*/) // 获取对应的连接
    private readonly connection: Connection,
    @InjectEntityManager(/*'personsConnection'*/) // 获取注入的实体管理
    private readonly entityManager: EntityManager,
  ) { }
  public findAll(): Promise<Users[]> {
    // return this.entityManager.find(Users);
    // or
    // return this.connection.manager.find(Users);
    return this.usersRepository.find();
  public getFindOne(id: number): Promise<Users> {
    return this.usersRepository.findById(id); // 使用自定义的存储库操作
  public addUser(user: Users): Promise<Users> { // 添加一条数据的方法
    return this.userRepository.add(user);
使用了扩展的UsersRepository存储库后,会增加两个自定义的方法,findById和add

17.增加路由控制器一些新操作尝试扩展的方法

// users.controller.ts
import { Controller, Get, Post, Param, Body } from '@nestjs/common';
import { Users } from './entity/users.entity';
import { UsersService } from './users.service';
@Controller('/user')
export class UsersController {
    public constructor(private readonly usersService: UsersService) { }
    @Get()
    public findAll(): Promise<Users[]> {
        return this.usersService.findAll();
    @Post('/select/:id') // 通过id查询单个用户信息
    public findOne(@Param('id') id: number): Promise<Users> {
        return this.usersService.getFindOne(id);
    @Post('/add') // 通过id查询单个用户信息
    public addUser(@Body() user: Users): Promise<Users> {
        return this.usersService.addUser(user);
这样扩展了存储库,也可以进行一些复杂的对数据库的操作封装,本人只是简单使用

18.异步配置连接数据库模块

// async.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TypeOrmConfigService } from './typeOrmConfig.service';
 * 异步配置存储库
 * * 异步传递存储库模块选项而不是静态传递。在这种情况下,请使用该forRootAsync()方法,该方法提供了几种处理异步配置的方法。
 * * 1.工厂功能
@Module({
    imports: [TypeOrmModule.forRootAsync({
    	// 方式1,直接使用useFactory方法配置,返回一个连接对象
        useFactory: () => ({
            type: 'mysql',
            host: 'localhost',
            port: 3306,
            username: 'root',
            password: 'root',
            database: 'test',
            entities: [__dirname + '/**/*.entity{.ts,.js}'],
            synchronize: true,
        }),
        // 方式2 使用以下useClass语法,配置一个创建连接的服务,
        // useClass: TypeOrmConfigService,
    })],
export class AsyncModule { }
// typeOrmConfig.service.ts
import { Injectable } from '@nestjs/common';
import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from '@nestjs/typeorm';
@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory { // 实现选项factory工厂
    createTypeOrmOptions(): TypeOrmModuleOptions { // 返回一个模块选项
        return {
            type: 'mysql',
            host: 'localhost',
            port: 3306,
            username: 'root',
            password: 'root',
            database: 'test',
            entities: [__dirname + '/**/*.entity{.ts,.js}'],
            synchronize: true,
暂时了解异步配置即可,也可以在正常项目中使用
其它的部分请前往首页查看,或者直接官方查看

本博客主的首页地址(点击跳转)

NestJS入门Authentication认证,TypeORM数据库连接官网API点击这里跳转1.Authentication依赖包安装(passport-jwt)yarn add @nestjs/passport passport passport-local @types/passport-local @nestjs/jwt passport-jwt @types/passport-j...
一套目前来说最好的nestjs实战教程,提供QQ长期问答服务. 本人从 08 年到 18 年一直从事于 PHP 的开发。从 18 年开始转向 Typescript+React+Nestjs 的技术栈。目前来说 React 应该是一个非常好用的前端框架,生态非常完善,并且十分灵活简单。Nestjs 则是 Node.js 中唯一且无敌存在的后端 web 框架。因为我个人从事这套技术栈开发已经 4 年多,所以颇有心得,做了这套 React18 视频教程和 Nestjs 实战视频教程。现在视频教程也是刚刚开始做了一部分,还在持续更新。使用 TS 全栈开发可以基本涵盖各种平台的方方面面,比如开发桌面应用的 Electron, 开发小程序的 Taro, 开发 Spa 中后台的 React,开发 SSR 网站的 next.js,开发移动应用的 React Native, 开发 CLI 的 Yargs, 以及开发后端的 Nestjs。基本学会一套,全面够用,再加上 Monorepo 组织结构,一个仓库所有平台都可以搞定。 包含以下知识点 - 掌握Nestjs框架的依赖注入,模块,提供者,生命周期等概念- 掌握DTO数据验证,响应序列化,异常过滤器等常用功能- 学会编写一些常用的class-validator验证约束- 熟练掌握Typeorm以及NestjsTypeorm结合开发- 学会整合Swagger输出Open API文档- 掌握TS装饰器以及反射元数据的定义和使用- 编写一些数据库相关的数据验证约束(比如树形表的同级别某字段唯一验证等)- 学会通过继承并魔改Nestjs源码编写自定义的全局验证器- 可以编写自定义的配置系统以及核心功能包- 学会自定义的代码组织方式(比如教程中我把默认的Nestjs应用改成Util+PluginModule模式)- 掌握编写一些常用的Util仓库(比如数据库,Redis,Restful)- 利用Yargs结合魔改后的框架可以编写一些自定义CLI命令(比如数据迁移,数据填充等)- 掌握如何利用阿里云/腾讯云推送邮件和短信- 掌握使用消息列队(MQ)的方式异步推送邮件和短信- 掌握守卫原理以及编写一些用户验证的守卫- 编写一个完善的用户系统(JWT认证,短信/邮件登录,短信/邮件注册,找回密码,绑定手机和邮箱等)- 熟练地通过编写装饰器去实现一些常用的功能- 通过SSE,WebSockets实现用户的上线,下线以及消息实时推送,消息广播等- 学会使用云存储来上传文件- 学会大文件断点雪川- 实现RBAC的权限系统- 理解请求范围概念以及性能方便的考量- 自己构建配置系统,实现配置验证以及通过YAML或数据库来进行动态配置- 通过适用Vscode进行Debug以及编写Jest测试来提升开发效率与程序的可用性- 学会使用Node来编写自定义的CLI命令- 利用NestCURD进行快速开发- 学会Graphql替代Restful写API- 使用Mongodb替代关系型数据库- 掌握一些常用的打包工具,比如通过ncc打包成单文件,通过pack打包成二进制等- 学会一些常用的部署方式,比如通过nginx+pm2反向代理部署,devops自动化CI,CD等- 学会使用pnpm workspaces来使用monreopo组织代码
提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、pandas是什么? 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 二、使用步骤 1.引入库
人真的有惰性思维哎一旦懒惰了两天(周六、周日),都忘了自己想干什么了所以说上班真是让人快乐的存在呐----------------------------------------------------------------过程:目录结构:1、安装依赖npm install typeorm --save npm install reflect-metadata --save npm instal...
nest官方提供的@nest/config确实让我们方便注入env的,但是我用法不太对,比如一开始的typeorm需要连接数据库,前面文章里直接forroot然后默认就走的ormconfig去连接编译后的文件,虽然效果也行,但用用别的方法也挺有趣的。 连接编译后的文件我还遇到个大坑,差点把我吓死,还好失败回滚了。就是ts实体编译后,然后我改变实体名,或者删掉实体,我本意就是不想让typeorm去操作那个实体,然后我开 yarn add @nestjs/passport passport passport-http-bearer @nestjs/jwt passport-jwt auth.service.ts import { JwtService } from '@nestjs/jwt'; import { Injectable } from '@nestjs/common'; // import {... lib/typeorm.module.ts import { Module, DynamicModule, Global } from '@nestjs/common'; import { ConnectionOptions } from 'typeorm'; import { createTypeOrmPr
一、数据库中事务操作的必要性 在数据库操作中,如果涉及到多表关联、多表有关系操作的时候,我们就要进行事务处理,以免一张表的数据已经发生了修改,刚好发生了异常,造成另外一张表的数据不进行更新。 两张表关联关系同时需要插入、删除数据 银行转换一个表数据减少另外一个表的数据增加 二、方式一、隐式commit,隐式rollback 1、控制层的代码 @Post() async creat...
React进阶用法和hooks - 5.useRef,useImperativeHandle和forwardRef的结合使用以及useLayoutEffect、useDebugValue的简单使用 11212