前言
昨天发现的框架,看了下官方文档,号称Nodejs
版本的spring(java)
开发模式有ng6
既视感,这对有ng
经验的小伙伴来说,莫名的亲切..
适合尝尝鲜,目前有1W+ star
, 上正式线我觉得等version 6
会稳定些,
这个系列我会以一个真实项目的开发进展作为基础,一边爬坑一边水文;
后台大佬用的PHP
,我打算用空闲时间拿nestjs
重写我们后台管理系统提供的那部分接口
其他就不多说了
官网 | NestJS迭代计划(roadmap)
-
2018-12-7:
mysql 8
链接报认证问题远程数据库是
5.7
, 备份下来切换到本地的mysql8
,因为mysql 8
升级了安全机制,没法类似以前那样直连.我们需要修改下,使其支持
# 登录/切换数据库/用新的机制更新我们的密码/ 刷新权限 -> mysql -u root -> use mysql -> ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456'; -> flush privileges; 复制代码
效果图
失败
失败的原因有那么几个;
- 数据库的配置信息跟实际要链接的数据库数据不一致(比如数据库名字,比如用户名密码)
- 隧道转发的端口给本地其他服务占用了,比如mysql本地启动的(默认3306)
- 这时候要么改端口映射,要么关闭本地数据库
mysql 8+
需要修改特权认证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的命令解释(官方手册): 英文,写的很详细;
我们主要用了以下几个参数
-L
: 端口转发
-C
: 压缩传送数据
-f
: 后台运行
-N
: 不执行远程命令
常规alias
# 这条命令会在后台运行
alias mstunnel=ssh -L 3306:localhost:3306 [email protected] -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 [email protected] -NCf
复制代码
走IPV6
就带上 -6
- npm模块的姿势
可以通过安装ssh2,Promise
成功后再去链接数据库;
不考虑用这种,因为实际服务器都是内部直连的,隧道我们也在开发过程用的比较多
总结
语法转义
- 若是使用
js
文件
目前的版本,还是要考虑commonjs
的写法,为什么这样说,
我把数据库链接的配置文件分离出来,不能用export default
导入的时候也不能用...(rest)
解耦的方式. 不然会报语法错误
ts
文件
可以任性使用ES6+
语法
有不对之处请留言,会及时修正,谢谢阅读