基础node&express&sql&jwt&session

更多内容建议官网走一波,这里是部分总结哦~

  • node基础
    • 文件读取
    • path模块
    • node的模块化
      • 模块作用域
      • nodejs遵循的是commonJs规范
      • 模块的加载机制
  • node web服务器http
  • express模块
  • 数据库模块
    • sql基本用法
    • sql进阶内容
  • 服务端验证
    • sessiong工作原理
    • jwt json web token

文件读取

读取路径的问题
当我们使用fs读或取文件的时候,如果不是恰好处于执行的这个文件,那么node会优先从执行node的那个文件开始查找
解决
使用完全路径
缺点:移植性差,不利于维护
__dirname 表示当前目录路径

path模块

如果是../那么会抵消路径,不建议使用+字符来拼接路径地址
方法
path.join(路径,路径) path.basename(路径,后缀[options]) path.extname(路径)

node的模块化

模块化

模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干个模块的过程,对于整个系统来说,模块是可以组合、分解和更换的单元
优势:
可复用、可维护、按需加载
模块化规范即对模块拆分和组合时需要遵循的规则,降低沟通成本

分类

内置模块
由node官方提供的,如fs,path

自定义模块

自己写的

第三方模块

非官方,由用户自定义的模块,需要下载使用的
加载方式:
require

模块作用域

和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块中访问
防止了全局变量的污染
通过module进行导出,导入使用require,导入导出的是一个对象,因此支持对象的结构;require导入的时候永
远以module.exports为基准
module.exports和exports指向的地址是相同的,但是当一个模块中既有module.exports和exports的时候,
并且都做了修改,
那么此时二者的值不一定相等了

nodejs遵循的是commonJs规范

  • 变量方法等职能使用自己模块内的
  • 导出使用exports(module.exports)
  • 导入使用require,并始终指向module.exports所导出的对象

模块的加载机制

优先从缓存中加载,提高模块的加载效率
内置模块加载机制:内置模块的加载优先级最高
自定义模块加载必须是路径,否则会当成内置模块或者第三方模块

自定义模块加载机制

按文件名加载
补全.js
补全.json
补全.node

第三方模块加载机制

先在项目的node_module中查找
在user路径下找node_module中查找
在根目录为node_module中查找

目录作为模块加载的时候

先在package.json中找main路径
然后在目录下的index.js,如果还没有则报错

其他

npm版本:moment@2.22.0
以点分十进制的形式组成,大版本+功能版本+bug修复版本
npm config get registry
npm config set registry=https: registry.npm.taobao.org
nrm工具
npm i nrm -g
nrm ls
nrm use taobao

node web服务器http

IP地址

ip地址是互联网每台计算机的唯一地址,因此具有唯一性
普通的电脑和服务器相差一个第三方的web服务器,而node可以通过http模块自行搭建web服务器,从而对外提供网
络资源
ip地址采用“点分十进制”,表示(a.b.c.d)每一位位0-255之间的十进制整数

域名和域名服务器

IP和域名是一一对应的关系,这份关系就存在域名服务器中(DNS);但是域名并不能直接就访问,还需要让域名
服务器进行转换,因此域名
服务器就是提供ip地址和域名之间转换的服务器,域名的使用使得互联网的访问变得更加方便
我们的电脑127.0.0.1对应的是localhost

端口号

计算机的端口号类似门牌号,由于实际生活中有N多个服务器,但是我们需要准确识别客户端发过来的网络请求是来自
哪个队赢的web服务器,因
此就需要通过端口号来进行区分
每个端口号不能同时被多个web服务占用
实际应用中只有80端口可以被省略

创建web服务器

req请求对象
当web服务器接收到request的请求时,会触发requests所绑定的事件,通过req可以访问与客户端相关的数据和属性,包括url、method
res响应内容
访问与服务器相关的数据或属性
像客户端响应一些内容,如res.end('jjj')
解决中文乱码
res.setHeader('Content-Type','text/html;charset=utf-8')

express模块

express是基于node.js平台,快速、开放极简的web开发框架,用来创建web服务器的

用途

web网站服务器 api接口服务器

基本使用

req.query 拿到URL的传参数
req.params拿到动态传的参数 app.get('/',(req,res)=> { }

托管静态资源,创建静态资源服务器

express.static(静态文件路径)
app.use(路径前缀(可选),express.static('./clock'))
express在指定的静态目录中查找文件,并对外提供资源的都访问路径,因此,存放静态文件的目录不会出现在url中

nodemon 持久化调试

参考:https://www.jianshu.com/p/a35dfc72c6e6

路由

express中的路由是客户端请求和服务器处理函数之间的映射关系,分别由请求类型+请求URL地址+处理函数组成;每当
一个请求到达服务器
时,会先按照定义的路由先后匹配,只有method和url匹配成功之后才会触发对应的处理函数;同时我们也希望将路由模
块化

中间件

在完成一个请求之前,中间会进行多次的预处理
因此当一个请求到达服务之前,可以连续调用多个中间件,从而对请求进行多次预处理
流程:客户端请求=》中间件1- N=》处理请求=》响应客户端
格式:function(req,res,next){} 包含一个next,可以把一个中间流转交给下一个路由或者中间件
注意:
针对模块化的路由,中间件的全局使用应该在所有注册路由的前面先使用use才能保证给所有的模块化路由正确添加中间件
作用:
多个中间件,共享同一份req和res,因此我们可以在上游统一为reqe/res添加属性或者方法,供下游的中间件或者路由
使用
多个全局中间件定义则是依次执行
全局中间件和模块内的中间件:先执行全局的,然后在执行模块内的中间件;是否执行模块内的中间,按照客户端请求和路
由注册顺序来
如果提前注册的路由为客户端的请求,那么中间件执行到当前模块注册的路由,并执行当前模块内的中间件,后面注册的
路由模块内的中
间件不在执行;执行结果一直按照注册路由的顺序一直执行到最后一个注册的路由
局部中间件
app.use('/api',ww,profileROuter); ww为中间件
分类
应用级中间件,绑定到app.use()
路由级别中间件,绑定到router.use()
错误级别中间件,补货项目中的错误,function(err,req,res,next){}
内置中间件:express.static(),express.json(),express.urlencoded({extended: false})
使用:router.use(express.json()),默认req.body返回是undefined
第三方中间件
npm i xx
aa = equire(xx)
app.use(aa)

数据库模块

cors(跨域资源共享)

是由一系列hhttp响应头组成,这些http响应头决定了浏览器是否阻止前端js代码跨域请求资源
解决跨域
使用中间件cors或者使用jsonp,但是jsonp职能支持get 方法
设置源和headers
Access-Control-Allow-Origins
Access-Control-Allow-Headers
Access-Control-Allow-Methods
响应一个jsonp是响应一个函数const str = ${funcName}(${JSON.stringify(data)});的过程,其中funcname是来自req.query.callback的值

数据库

数据库是用来组织、存储和管理数据的仓库
数据组织结构
数据库 数据表 数据行 字段,每个字段有对应的数据类型
工具: mysql mysql workbench

什么是sql

结构化查询语言,用来专门访问和处理数据库的编程语言。能够让我们以编程的形式操作数据库的数据;只能在关系型数据库中使用

sql基本用法

select 查询数据表中的内容
select * from 表
select username,password from users

insert into 向数据表中插入新的行
insert into users (passwork,username) values ('1233','tony')
insert into users set ? where id = ?

update 修改数据表中的数据,set的多个数据使用逗号(,)进行分割
update users set password='123' where id = 4
update users set ? where id = ?

delete 删除数据行(一般不用,更建议使用update进行标记删除)
delete from users where id = 4
注意:我下载的工具不能直接使用表,而应该数据库后面跟上表,即my_db_01.users

oerder by
按照所给的列进行排序 desc asc(ascending: [əˈsendɪŋ] ) 分别表示降序和升序

操作数据库:
查看所有数据库
show databases;
查看某个数据库的定义信息
show create database db1;
删除数据库
drop database db1;alter

操作数据表:
创建表,类型有int varchar double(4,1)(表明4位数,小数一位整数两位)
date(1996-07-21) timestap(2022-12-11 10:51:30)
create table if not exists my_db_01.student // if not exists可省略

查询表结构
desc my_db_01.student
修改表名称
alter table my_db_01.student rename to my_db_01.student2
给表增加一列,varchar注意给自负大小,如255
alter table my_db_01.student2 add sports varchar(255)
删除表的某一列
alter table my_db_01.student2 drop age
删除表/数据
drop table if exist my_db_01.student2 全删除
truncate table my_db_01.student2 删除保留表结构
delete from my_db_01.student2 where id = 1 逐行删除,不适用大量数据
修改表结构 change column xx
ALTER TABLE my_db_01.cmswing_auth_rule
CHANGE COLUMN pid pid INT NOT NULL DEFAULT '0' ;

查看safe-updates的工作状态
show variables like 'sql_safe_updates'
set sql_safe_updates = 0

sql进阶内容

主要介绍: 排序查询、聚合函数、模糊查询、分组查询、分页查询、(内连接、外连接)、子查询

age between 20 and 30 表明[20,30]之间 这个用来替换&&符号,即age>= 20 && age<=30
age in (20,30) 用来替换or 即age = 20 or age = 30

is not null 不为空
example:select * from my_db_01.student2 where sports is not null;

模糊查询like _:单个字符 %:多个任意字符
example: select * from my_db_01.student2 where name like 'w%';

distinct : remove duplicate values 返回不重复的init_name行,可用于计算行数量
example: select distinct init_name from my_db_01.student2;

排序查询 order by (desc asc)
init: zs ls. ww wb wb2
name: ls wb wb2 ww zs
age: null 20 22 30

聚合查询: count max min sum avg 个数 最大最小 求和 平均
count() 查询值的个数
avg 如果列表中有null将不能计算出平均值(保留三位小数),但是能计算出总数
example: select count(
) from my_db_01.student2;

分组查询: 查询某一类的内容,如某一项,按照某个规则获取的的平均分,规则下分组的个数等;甚至还可以加上where等
进行区间查询
example: select sex,avg(age),count(id) from my_db_01.student2 group by sex;

分页查询
语法:limit 开始的索引,每页查询的条数;
公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数
limit 是一个MySQL"方言"
example: select * from my_db_01.student2 limit 0,3 // 包含条数区间范围是:[0,3)

子查询
查询嵌套中的语句
example: 年龄最大用户的信息。 关键字:年龄最大、用户信息
年龄最大:select max(age) from my_db_01.student2;
用户信息: select * from my_db_01.students where age = xxx
汇总等于: select * from my_db_01.student2 where age = ( select max(age) from my_db_01.student2 );
子查询的结果是单行单列的 他可以作为条件 使用运算符进行运算
子查询的结果是多行单列的 可以使用 in 运算符来判断
select * from my_db_01.student2 where id in ( select id from my_db_01.student2 where name = 'aa' or name = 'bb'); // id=2/3分别表示 aa bb
子查询结果是多行多咧的 可以作为一张虚拟表参与查询
就这两句,没搞明白,怎么t1可以作为变量!!!使用并参与查询
select id,init_name,age,department from my_db_01.student2 t1 where department='master' or department='shooter';
select count(*) from my_db_01.student2 t1 where t1.department = 'master';

练习题

update my_db_01.ev_article_cate set name='语文',alias='y11uwen' where id=3;
select * from my_db_01.ev_article_cate
desc my_db_01.ev_users

show create table my_db_01.ev_users
alter table my_db_01.student rename to my_db_01.student2
alter table my_db_01.student2 add nickname varchar(255);
update my_db_01.student2 set nickname ='zs' where name = 'zs';
update my_db_01.student2 set nickname ='ls' where name = 'ls';
update my_db_01.student2 set nickname ='ww' where name = 'ww';
update my_db_01.student2 set nickname ='wb' where name = 'wb';
update my_db_01.student2 set nickname ='wb' where name = 'wb2';
alter table my_db_01.student2 drop age
insert into my_db_01.student2 values (1,'zs',411.2,'1996-07-21','2022-12-11 10:51:30','pingpont');
delete from my_db_01.student2 where id = 1;
set sql_safe_updates = 0;
show variables like 'sql_safe_updates';
insert into my_db_01.student2 (name,init_name) values ('wb2','wb');
update my_db_01.student2 set sex = 'girl' where name = 'zs';

select * from my_db_01.student2 order by age;
select distinct init_name from my_db_01.student2;
select * from my_db_01.student2 where name like 'w%';
select * from my_db_01.student2 where sports is not null;
select * from my_db_01.student2 where age between 22 and 30;
select * from my_db_01.student2;

select avg(age) from my_db_01.student2;
select sex,avg(age),count(id) from my_db_01.student2 group by sex;

select * from my_db_01.student2 limit 0,3;
select max(age) from my_db_01.student2;
select * from my_db_01.student2 where age = ( select max(age) from my_db_01.student2 );

select id,init_name,age,department from my_db_01.student2 t1 where department='master' or department='shooter';
select count(*) from my_db_01.student2 t1 where t1.department = 'master';

select * from my_db_01.student2 where id in ( select id from my_db_01.student2 where department='master' or department='shooter') ;

alter table my_db_01.student2 add department varchar(255) ;
update my_db_01.student2 set department = 'master' where name = 'zs';
update my_db_01.student2 set department = 'shooter' where name = 'ls';
update my_db_01.student2 set department = 'master' where name = 'wb';
update my_db_01.student2 set department = 'shooter' where name = 'wb2';
select * from my_db_01.student2;

服务端验证

服务端渲染推荐使用session认证机制,而前后端分离则是jwt认证机制

session

http的无状态性,指客户端端每次http请求都是独立的,连续多个请求之间没有用直接的关系,服务器不会主动保留每次http的状态

cookie

cookie是存储在用户浏览器中一段不超过4kb的字符串,他有一个名和一个值组成,和其他几个用于控制cookie有效期、安全性和适用范围的可选属性组成;不同域名下的cookie各自独立的,每当客户端发起请求时,会自动把当前域名下所有呀未过期cookie一同发给服务器
特点
自动发送
域名独立
4kb大小限制
过期时限
第三方包:express-session

sessiong工作原理

浏览器初次发起请求,并提交账号和密码;
服务器验证密码,并将登录成功的用户信息存储在服务器的内存中,同时生成对应的cookie字符串,响应给客户端;
客户端自动把cookie存储到当前域名;
当客户端再次发起请求时,会通过请求头自动把当前域名下的所有可用cookie发给服务器;
服务器从请求头中请求携带的cookie,找到内存中存储的用户信息;
当身份验证成功后再响应客户端;

session工作流程

使用过程

    const expressSession = require('express-session');
    app.use(expressSession({
        secret: 'zhu',
        resave: false,
        saveUninitialized: true, // 保存为初始化
    }))
    登录
    app.post('/api/login',(req,res) => {
        if (req.body.username != 'admin'|| req.body.password != '1234') {
            return res.send({
                status: 1,
                msg: 'login fail'
            })
        }
        req.session.user = req.body;
        console.log(req.session)
        req.session.islogin = true;
        res.send({
            status: 0,
            msg: 'login success'
        })
    })
    销毁:
    req.session.destroy(
                
    )

jwt json web token

session需要配合cookie实现,而cookie不支持跨域,所以当前端跨域请求后段接口的时候就不使用了,需要做额外的配置才能实现
跨域认证解决方案
工作原理
首先客户端向服务器发起一次请求,服务器验证成功后生成对应的token字符串,并返还给客户端;
接着客户端将token保存到本地;
当客户再次发起请求的时候,通过请求头的Authorization 将token发给服务器,服务器将token还原成对应的用户信息对象;
最后根据用户信息对象和内存进行比对,比对成功后响应给浏览器

组成
Header Payload Signature(保证安全性)
Authorization: Bearer <token>
express-jwt jsonwebtoken

定义secret
用于保证jwt字符串的安全性,专门用来加密和解密的密钥;因此当生成jwt字符串的时候,使用secret对用户信息进行加密
当需要还原jwt字符串的时候,则对secret进行解密

使用方法:
登录的时候使用jwt生成token:let token = jwt.sign({ username: req.body.username } ,secretStr ,{ expiresIn: '1h'})
注意加密的字段不要说隐私字段,比如密码
接着注册中间件,注意写法,algorithms([ˈælgərɪðmz])说必填字段
引入:var { expressjwt: expressjwt } = require("express-jwt");
注册:
app.use(expressjwt({
secret: secretStr,
algorithms: ["HS256"]
}).unless({ path: [/^/api//]}))
获取token则需要给请求的headers加上Authorization:Bearer <token>
看都看到这里了,不妨点赞支持支持~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,132评论 6 523
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,457评论 3 404
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 172,411评论 0 368
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,147评论 1 301
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,145评论 6 400
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,611评论 1 315
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,962评论 3 429
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,948评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,479评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,514评论 3 347
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,640评论 1 355
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,228评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,973评论 3 340
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,402评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,551评论 1 277
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,210评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,714评论 2 366

推荐阅读更多精彩内容