前言
昨天发现的框架, 看了下官方文档, 号称 Node.JS 版本的 spring(java)
开发模式有 ng6 既视感, 这对有 ng 经验的小伙伴来说, 莫名的亲切..
适合尝尝鲜, 目前有 1W+ star, 上正式线我觉得等 version 6 会稳定些,
这个系列我会以一个真实项目的开发进展作为基础, 一边爬坑一边水文;
后台大佬用的 PHP, 我打算用空闲时间拿 nestjs 重写我们后台管理系统提供的那部分接口
其他就不多说了
官网 | NestJS 迭代计划 (roadmap)
效果图
失败
失败的原因有那么几个;
数据库的配置信息跟实际要链接的数据库数据不一致 (比如数据库名字, 比如用户名密码)
隧道转发的端口给本地其他服务占用了, 比如 MySQL 本地启动的 (默认 3306)
这时候要么改端口映射, 要么关闭本地数据库
ts 语法错误
成功
代码
db.ts(src/config)
温馨提示: 若是要用__dirname, 确保配置文件在根目录, 否则请改用相对路径, 不然会找不到实体
synchronize 是同步, 会自动同步到数据库, 比如建表什么的 (根据实体)
- import { join } from 'path';
- const EntityRecursivePath = join('..', '/**/*.entity{.ts,.js}');
- export const MySqlConfig: any = {
- type: 'mysql',
- host: 'localhost',
- port: 3306,
- username: 'root',
- password: '!=basestagging**',
- database: 'shengxi_v2',
- entities: [EntityRecursivePath],
- synchronize: true,
- };
App.module.ts
UsersModule 里面写了对应的服务, 实体的关联
- import { Module, NestModule, MiddlewareFunction } from '@nestjs/common';
- import { AppController } from './app.controller';
- import { AppService } from './app.service';
- // 用户模块, 注册, 登录, 更新个人信息
- import { UsersModule } from './modules/users/users.module';
- // 数据库 ORM
- import { TypeOrmModule } from '@nestjs/typeorm';
- import { MySqlConfig } from './config/db';
- @Module({
- imports: [TypeOrmModule.forRoot(MySqlConfig), UsersModule],
- controllers: [AppController],
- providers: [AppService],
- })
- export class AppModule implements NestModule {
- // consumer 这里可以挂在中间件什么的
- configure(consumer: MiddlewareFunction): void {
- consumer
- .apply(null)
- .with('AppModule')
- .forRoutes('/');
- }
- }
- users.entity.ts
- import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
- // entity 装饰器提供一个 options 可以配置关联的表名, 引擎等等, 具体看她的 interface
- // 不提供 name 的话,, 类名就是表名了
- @Entity({
- name: 'sx_admin',
- })
- export class Users {
- @PrimaryGeneratedColumn() id: number;
- // 用户名
- @Column('varchar', { length: 100 })
- admin_name: string;
- // 用户密码
- @Column('varchar', { length: 255 }) admin_passwd: string;
- // 创建时间
- @Column('timestamp') created_at: number;
- // 更新时间
- @Column('timestamp') updated_at: number;
- // 是否启用
- @Column('int') admin_status: number;
- }
剩下的姿势, 就在 services 里面注入实体和 ORM 的 Repository;
再到 controller 注入服务调用即可... 返回的是 Promise
要点提示及温馨提示
SSH 隧道转发 (SSH Tunnel)
远程数据库我们一般不暴露外接端口直连, 安全隐患太高;
一般选择走 SSH 隧道 (很常用的接入方式),
通过 SSH 登录认证服务器, 再转发本地的端口到远程端口, 达到数据打通的姿势
SSH 命令转发
SSH 的命令解释 (官方手册) https://man.openbsd.org/ssh : 英文, 写的很详细;
我们主要用了以下几个参数
-L: 端口转发
-C: 压缩传送数据
-f: 后台运行
-N: 不执行远程命令
常规 alias
- # 这条命令会在后台运行
- alias mstunnel=SSH -L 3306:localhost:3306 root@xxx.xx.xx.xx -NCf
- # 若是远程转远程 用 - R 替换 - L
传递参数的 alias
shell 的 alias 不支持参数的传递, 要传递只能写成 function 再赋值到 alias
可以设置多个占位符, 依次递增 (比如端口, 域名都变成外部传入什么的, 看自己喜好了)
- # SSH tunnel
- function sst(){
- SSH -L 3306:localhost:3306 root@$1 -NCf
- }
- alias sst=sst
关闭会话 (SSH tunnel)
分步进行的依赖 lsof,kill
找到对应的进程 PID ,lsof -i tcp:22(查询谁用着 22 的端口, SSH tunnel 默认走 tcp)
kill -9 pid , -9 是终止进程
若是要一步到位的, 就要借助几个命令一起了, awk,xargs 以及管道 (|)
- # 意思就是
- # 查询 TCP 且端口 22 的进程
- # 输出第二行的第二列 (第一行是列名)
- # stdin 转为 arguments 给 kill
- lsof -i tcp:22 | awk 'NR==2 { print $2}' |xargs kill -9
- # 当然也可以当做一个表达式来写
- kill -9 $(lsof -i tcp:22 | awk 'NR==2 { print $2}')
- # 若是要同时关闭多个引用该端口的进程 , NR!=1 即可 , kill 支持杀多进程
- # 有传递参数的 alias 记得用 function 来实现!!!
若是 SSH 没有配置定时发送信号, 一段时间后会自动停止会话 (packet_write_wait:);
此时要么去配置, 要么我们改写下 alias , 用 - o ServerAliveInterval=60 来保持连接的连接这
SSH -o ServerAliveInterval=60 -L 3306:localhost:3306 root@xxxx.xxx.xxx -NCf
走 IPV6 就带上 -6
NPM 模块的姿势
可以通过安装 https://www.npmjs.com/package/ssh2 ,Promise 成功后再去链接数据库;
不考虑用这种, 因为实际服务器都是内部直连的, 隧道我们也在开发过程用的比较多
总结
语法转义
若是使用 JS 文件
目前的版本, 还是要考虑 commonjs 的写法, 为什么这样说,
我把数据库链接的配置文件分离出来, 不能用 export default
导入的时候也不能用...(REST) 解耦的方式. 不然会报语法错误
ts 文件
可以任性使用 ES6 + 语法
有不对之处请留言, 会及时修正, 谢谢阅读
来源: https://juejin.im/post/5c088c5de51d453428652c60