安装MySQL及相关依赖

下载dmg文件安装

前往MySQL :: Download MySQL Community Server下载最新版本的MySQL。

打开系统设置,拉到最下方可以看到MySQL,打开看到两个绿点表示安装成功,也可以在这里修改MySQL密码。

nestjs swaager全局绑定的token没带上_redis

配置环境变量

打开终端配置MySQL环境:

vim ~/.bash_profile

按字母 i 键切换至输入状态,添加如下配置:

export PATH=${PATH}:/usr/local/mysql/bin

按ESC键退出输入状态,输入:wq回车即可,然后执行 source ~/.bash_profile 使其配置生效。为确保配置成功,vim ~/.zshrc 按以上步骤操作一遍。

输入mysql --version,出现MySQL版本信息,则表示配置成功。

进入MySQL

终端输入 mysql -u root -p 回车输入数据库密码,出现如下信息说明进入MySQL成功。

nestjs swaager全局绑定的token没带上_javascript_02

安装MySQL可视化工具(可选)

MySQL Workbench 官方地址:https://dev.mysql.com/downloads/workbench/。或者使用一个 VSCode 数据库可视化插件Database Client,安装完后连接我们的数据库就能进行一个可视化操作。先需要使用账号密码连接MySQL,然后创建一个数据库ADMIN,然后可以手动创建表或者选择导入sql文件,也可以通过后面的实体文件自动创建。最终效果如下:

nestjs swaager全局绑定的token没带上_javascript_03

安装相关依赖

安装typeorm及mysql2等相关依赖,typeorm可以将数据库的 sql 操作转化为对象操作:

npm install --save @nestjs/typeorm typeorm mysql2

项目配置

来到app.module.ts中进行数据库的配置,引入TypeOrmModule调用forRoot进行配置。

import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { UserModule } from "./user/user.module";
import { TypeOrmModule } from "@nestjs/typeorm";
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: "mysql",
      synchronize: true,
      autoLoadEntities: true, //自动加载实体
      host: "localhost",
      port: 3306, // 端口号
      username: "root", // 用户名
      password: "root", // 密码
      database: "admin", //数据库名
      synchronize: true, //是否自动同步实体文件,生产环境建议关闭
    }),
    UserModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

当我们将autoLoadEntities设置为 true 的时候,NestJS 会自动加载数据库实体文件xx.entity.ts文件来创建数据表(如果没有的话),比如 user/entities/user.entity.ts,我们简单加一些字段:

import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";

@Entity("user")
export class User {
  @PrimaryGeneratedColumn("uuid")
  id: number; // 标记为主键,值自动生成

  @Column({ length: 30 })
  username: string; //用户名
  @Column()
  password: string; //密码
}

启动项目,然后就会发现自动创建了一个 user 表。

到此为止,mysql和typeorm配置相关内容就完成了。下面进入Redis的编译和使用。

Redis使用

下载Redis源码并编译

前往Download | Redis下载Redis源码,解压后使用make命令进行编译。make成功后会在src文件夹下产生一些二进制可执行文件,包括redis-server、redis-cli等等:

$ find . -type f -executable

./redis-benchmark //用于进行redis性能测试的工具
./redis-check-dump //用于修复出问题的dump.rdb文件
./redis-cli //redis的客户端
./redis-server //redis的服务端
./redis-check-aof //用于修复出问题的AOF文件
./redis-sentinel //用于集群管理

启动redis

启动redis非常简单,进入到Redis源码的src目录,直接./redis-server就可以启动服务端了,还可以用下面的方法指定要加载的配置文件:

./redis-server ../redis.conf

默认情况下,redis-server会以非daemon的方式来运行,且默认服务端口为6379。

使用redis客户端

我们直接看一个使用redis-cli启动redis客户端的例子:
$ ./redis-cli
//用set指令来设置key、value
127.0.0.1:6379> set name "roc" 
OK
//来获取name的值
127.0.0.1:6379> get name 
"roc"
//通过客户端来关闭redis服务端
127.0.0.1:6379> shutdown 
127.0.0.1:6379>

Redis可视化插件

我们使用命令行想查看redis中的数据不太方便,所以我们需要一个可视化插件,前面文章已经提到过,安装一个将Database Client的插件,它可以将数据库可视化,同时也可以连接redis。

安装相关依赖

使用代码来操作redis需要安装Redis库,因nest.js官方推荐的redis库年久失修,考虑社区活跃度和稳定性选择@liaoliaots/nestjs-redis和ioredis:

npm install @liaoliaots/nestjs-redis ioredis

由于@liaoliaots/nestjs-redis依赖的nest.js组件版本过旧,npm install的时候会失败,需要在package.json中增加:

"overrides": {
    "@liaoliaots/nestjs-redis": {
      "@nestjs/common": "^10.0.0",
      "@nestjs/core": "^10.0.0"
    },
  },

项目配置

一般我们会给对 redis 的操作单独建一个模块,后面有哪些模块需要使用 redis 直接引入这个模块即可,这里我们将模块命名为 cache,使用 nestcli 命令创建。

在service中我们实现一些常用的Redis操作:

import { InjectRedis } from '@liaoliaots/nestjs-redis'
import { Injectable } from '@nestjs/common'
import Redis from 'ioredis'

@Injectable()
export class CacheService {
    constructor(@InjectRedis() private readonly client: Redis) { }

    getClient(): Redis {
        return this.client
    }

    /* --------------------- string 相关 -------------------------- */

    /**
     *
     * @param key 存储 key 值
     * @param val key 对应的 val
     * @param seconds 可选,过期时间,单位 秒
     */
    async set(key: string, val: string, seconds?: number): Promise<'OK' | null> {
        if (!seconds) return await this.client.set(key, val)
        return await this.client.set(key, val, 'EX', seconds)
    }

    /**
     * 返回对应 value
     * @param key
     */
    async get(key: string): Promise<string | null> {
        if (!key || key === '*') return null
        return await this.client.get(key)
    }

    async del(keys: string | string[]): Promise<number> {
        if (!keys || keys === '*') return 0
        if (typeof keys === 'string') keys = [keys]
        return await this.client.del(...keys)
    }
}

@Global() 装饰器使模块具有全局作用域。CacheModule的CacheService将无处不在,希望注入CacheService的模块将不需要在其导入数组中导入 CacheModule。同时为了注册经过配置的RedisModule,这里使用动态模块来创建自定义的模块,这个模块可以动态注册和配置provider:

import { Module, Global, DynamicModule } from '@nestjs/common';
import { CacheService } from './cache.service';
import { RedisModule, RedisModuleAsyncOptions, RedisModuleOptions } from '@liaoliaots/nestjs-redis'

@Global()
@Module({
  exports: [CacheService],
  providers: [CacheService],
})
export class CacheModule {
  static forRoot(options: RedisModuleOptions, isGlobal = true): DynamicModule {
    return {
      module: CacheModule,
      imports: [RedisModule.forRoot(options, isGlobal)],
      providers: [CacheService],
      exports: [CacheService]
    }
  }

  static forRootAsync(options: RedisModuleAsyncOptions, isGlobal = true): DynamicModule {
    return {
      module: CacheModule,
      imports: [RedisModule.forRootAsync(options, isGlobal)],
      providers: [CacheService],
      exports: [CacheService]
    }
  }
}