【NodeJS】归纳篇(三)Express | 链式操作 | cookie && session | 模板引擎 | Router | mysql

2023-10-07 17:24:21 浏览数 (3)

初步使用

第一步

  • npm install express

示例:server.js

  • 1、创建服务
  • 2、监听
  • 3、处理请求
代码语言:javascript复制
const express = require('express');
var server = express();//1、创建服务
//3、响应请求
//use() 添加响应
server.use('/a.html',function(req,res){
//req和res是经过express封装过的,并非nodejs中原生的
	res.send('abc');//类似于write()
	res.end();
});
server.use('/b.html',function(req,res){
	res.send('cba');//类似于write()
	res.end();
});
server.listen(8080);//2、监听

3种接收用户请求的方法:

  • get(’/’,function(req,res){});
  • post(’/’,function(req,res){});
  • use(’/’,function(req,res){});//都能接收get和post方式的请求

改进

express-static 处理静态文件的中间件

代码语言:javascript复制
const express = require('express');
const expressStatic = require('express-static');
var server = express();
server.listen(8080);
//接口:get方式: /login?user=xxx&psw=xxx
//返回: {result:true/false,msg:'原因'}
server.get('/login',function(req,res){
	var user = req.query['user'];
	var psw  = req.query['psw'];
	if(users[user]==null){
		res.send({reslut:false,msg:'不存在'});
	}else {
		if(users[user]!=pass){
			res.send({reslut:false,msg:'密码错了'});
		}else{
			res.send({reslut:true,msg:'成功'});
		}
	}
});
server.use(expressStatic('./www'));//从www这个目录下读取静态文件

处理数据

代码语言:javascript复制
const express = require('express');
const bodyParser = require('body-parser');
var server = express();
server.listen(8080);

server.use(bodyParser.urlencoded({
	extended: false,  //扩展模式,true启用,false普通模式
	limit: 2*1024*1024         //限制,最大支持的POST数据,默认100k
})); //使用多个use()时,会形成一个链式操作(下面会讲到)

//获取Get,Post相关数据
server.use('/',function(req,res){
	console.log(req.query); //获取Get
	console.log(req.body); 
	//获取Post,需要一个中间环节server.use(bodyParser.urlencoded({}));
});

由此可见:

  • Get无需中间件支持
  • POST需要body-parser中间件,先server.use(bodyParser.urlencoded({})); 后req.body

链式操作

从上节中可以看到链式操作,你可以简单理解使用链式操作是规定这个操作流程有一个步骤,即需要先做什么,然后做什么。依次下去形成一个**“流水线”**。

改写示例:

代码语言:javascript复制
const express = require('express');
const bodyParser = require('body-parser');
var server = express();
server.listen(8080);

server.use('/',function(req,res,next){//注意参数
	console.log(1);
	next();  //**注意,next()是选择性的执行**
});

server.use('/',function(req,res,next){
	console.log(2);
});

注意到,在use()的参数中,多了一个next,这是一个可选操作,即供用户选择是否要下一步操作。

中间件怎么写——原生

代码语言:javascript复制
const express = require('express');
const querystring = require('querystring');
var server = express();
server.listen(8080);


server.use(function(req,res,next){//没有第一个参数,则对所有路径请求都接收
//原生写法
	var str = '';
	req.on('data',function(data){
		str =data;
	});
	req.on('end',function(){
		req.body = querystring.parse(str);  //解析字符串
		next();  //**注意next()所在位置**
	});
	
});
server.use(function(req,res){
	console.log(req.body);
});

改写,将其写成一个模块mybody-parser.js。

代码语言:javascript复制
const querystring = require('querystring');
modules.exports={//没有第一个参数,则对所有路径请求都接收
	parser:function(){
		return function(req,res,next){
				var str = '';
				req.on('data',function(data){
					str =data;
				});
				req.on('end',function(){
					req.body = querystring.parse(str);  //解析字符串
					next();  //注意next()所在位置
				});
			};
	};
};

引用mybody-parser.js模块

代码语言:javascript复制
const express = require('express');
const mybodyParser = require('mybody-parser');
//mybody-parser输出的是一个function,那么mybodyParser就是一个function

var server = express();
server.listen(8080);

server.use(mybodyParser.parser());//使用mybody-parser中间件

server.use(function(req,res){
	console.log(req.body);
});
  • 其他: multer 多文件上传中间件,需求先指定上传后文件的存储位置。

cookie && session

  • cookie : 在浏览器保存一些数据,每次请求都会带过来 缺陷:不安全、存储空间有限(4k)
  • session : session是逻辑上的,其还是基于cookie实现,也保存数据,但保存在服务端。 优点:安全、存储空间依据服务器空间。 原理:客服端请求服务端,先带一个空的cookie={}传到服务端,然后服务端对这个cookie赋值并写到客户端;下一次客户端向服务端发起请求时,就会带上这个cookie。cookie中会有一个session的ID,服务器利用sesssion的ID找到session文件或读取、写入。 隐患session劫持
读取与发送cookie
  • 读取——cookie-parser
代码语言:javascript复制
const express = require('express');
const cookieParser = require('cookie-parser');//引入中间件
var server = express();

//cookie
server.use(cookieParser());

server.use('/',function(req,res){
	res.cookie('user','imaginecode',{path:'/www',maxAge:30*24*36000*1000});
	//maxAge:设置过期时间(有效期),单位毫秒
	//path:指定在该路径下可以读这个cookie 
	//读取cookie
	console.log(req.cookies);
	
});

server.listen(8080);
  • cookie安全性:cookie签名
代码语言:javascript复制
const express = require('express');
const cookieParser = require('cookie-parser');//引入中间件
var server = express();

//cookie
server.use(cookieParser('imaginecode0101'));

server.use('/',function(req,res){
	req.secret = 'imaginecode0101';//设置密钥
	res.cookie('user','imaginecode',{signed:true});
	//加入参数signed签名,需要提供密钥secret
	console.log("带签名的cookie",req.signedCookies);
	console.log("无签名的cookie",req.cookies);	
});

server.listen(8080);

注意 cookie空间非常下,要省着用; 安全性差——校验cookie是否被纂改过;

小结

  • res.cookie()//发送cookie
  • 读取cookie:使用到中间件——cookieParser,server.use(cookieParser('密钥'))
  • 用cookie: req.cookies 未签名版,req.signedCookies 带签名
  • 删除cookie: res.clearCookie(cookie名);
  • cookie加密——cookie-encrypter,cookie加密意义不大。
session——cookie-session中间件

1、写入 2、读写

代码语言:javascript复制
const express = require('express');
const cookieParser = require('cookie-parser');//引入中间件
const cookieSession = require('cookie-session');
var server = express();

//cookie
server.use(cookieParser('imaginecode0101'));
//session
server.use(cookieSession({
	name: 'sess',//session名
	keys = ['aaa','bbb','ccc'],
	//使用session时,需要加keys--密钥,keys为数组,会依次循环使用keys中的密钥对session加密
	//keys密钥数组越长,越安全
	maxAge: 1*3600*1000 //设置有效期1小时
}));

server.use('/',function(req,res){
if(req.session['count']==null){//第一次
	req.session['count']=1;
}else {
	req.session['count']  ;
}
		console.log(req.session);//注意session在request上
});

server.listen(8080);

模板引擎

  • jade: 破坏式的、侵入式、强依赖
  • ejs: 温和、非侵入式、弱依赖 (推荐)
  • template.js
jade与ejs对比
  • jade

参考文档:http://jade-lang.com/

代码语言:javascript复制
const jade = require('jade');
var str = jade.renderFile('a.jade',{pretty:true});
console.log(str);

a.jade

代码语言:javascript复制
//用缩进代表层级
html
 head
  style
  script
 body
  div
  p  
  • ejs

参考文档:https://ejs.bootcss.com/ ejs.js

代码语言:javascript复制
const ejs = require('ejs');
ejs.renderFile('a.ejs',{name:'imaginecode'},function(err,data){
	if(err){console.log('编译失败')}
	ekse {console.log(data);}
});

a.ejs

代码语言:javascript复制
<html>
	<head>
	</head>
	<body>
		{%= name %} //注意变量前后的空格,另外变量name来自ejs.js中
	</body>
</html>
  • art-template 参考:https://aui.github.io/art-template/zh-cn/index.html
  • consolidate 模板引擎适配库
路由-route:一个小型的Express

把不同的目录对应到不同的模块。

  • 假设访问 xxx.com/news ,则调用 mod_news 子路由 post , 则调用 news_post
  • 访问 xxx.com/users ,则调用 mod_users 如:
代码语言:javascript复制
var r1 = express.Router();
var r2 = express.Router();
server.use('/article',r1);//**添加路由时要使用use()
r1.get('/a.html',function(req,res){
	res.send('a.html').end(); //r1用于管理article目录下的a.html

server.use('/comment',r2);
r2.get('/b.html',function(req,res){
	res.send('b.html').end();//r2用于管理comment目下的b.html
});
})

路由多的情况下,使用函数管理。如:

代码语言:javascript复制
var r1 = createRouter();
function createRouter() {
	var router = express.Router();
	router.get('/a.html',function(req,res){
	res.send('a.html').end();
	});
	router.get('/b.html',function(req,res){
	res.send('b.html').end();
	});
	return router;
}

改进:写成一个模块

/route/createRouterA.js

代码语言:javascript复制
const express = require('express');
module.exports = function() {
	var router = express.Router();
	router.get('/a.html',function(req,res){
	res.send('a.html').end();
	});
	router.get('/b.html',function(req,res){
	res.send('b.html').end();
	});
	return router;
{

然后进行引入: server.js

代码语言:javascript复制
server.use('/article',require('./route/createRouterA.js')());

上面是对artile目录进行操作,同理,可以对comment目录进行相同的操作。

mysql

设计表之前可以先建立数据字典,有一个宏观的参考。

例如:user_table表

代码语言:javascript复制
ID      
username  用户名       varchar(32)
password  密码        varchar(32)
src       用户头像     varchar(64)

然后建表完成之后,可以进行mysql客户端的操作。

代码语言:javascript复制
const mysql = require('mysql');//引用mysql模块
//1、连接
//createConnection(服务器名,用户名,密码,数据库名);
var db = mysql.createConnection({
	host:'localhost',
	port:3306,
	user:'root',
	password:'root',
	database:'testdb'
});
//2、查询 query(sql语言,回调函数)
db.query("",(err,data)=>{
	if(err){
		console.log('出错',err);
	}else {
		console.log('成功',data);
	}
});
连接池 (Pool)

保持某个数目的连接数,连接的时候选择能用的连接,避免重复连接

代码语言:javascript复制
//createPool
const db = mysql.createPool({
	host:'localhost',
	port:3306,
	user:'root',
	password:'root',
	database:'testdb'
});
sql语言-CURD

SQL 标准写法: 1、关键字大写 2、库、表、字段需要加上’’ 3、分号结尾

代码语言:javascript复制
//增-INSERT
// INSERT INTO 表 (字段列表) VALUES(值列表)
INSERT INTO 'user_table' ('ID','username','password') VALUES(0,'imaginecode','123');

//删-DELETE
DELETE FROM 表 where 条件

//改-UPDATE
UPDATE 表 SET 字段=值,字段=值,... WHERE 条件

// 查-SELECT
// SELECT 字段名 FROM 表
SELECT * FROM 'user_table';
字句
  • WHERE 条件
代码语言:javascript复制
WHERE age<=10

WHERE age>=10 AND score<60

WHERE age>15 OR score>80
  • ORDER 排序
代码语言:javascript复制
ORDER BY age ASC/DESC
//先按价格升序,再按销量降序
ORDER BY price ASC,sales DESC 
  • GROUP 聚类、合并相同
代码语言:javascript复制
//按班级分组,将class相同的合并
SELECT class,COUNT(class) FROM student
GROUP BY class

//计算各班平均分
SELECT class,AGE(score) FROM student
GROUP BY class
//计算各班最高分,最低分
SELECT class,MAX(score),MIN(score) FROM student
GROUP BY class
//统计每个人买的数量,按总数升序排列
SELECT name,SUM(price) FROM sales_table GROUP BY name ORDER BY SUM(price) ASC
  • LIMIT-限制输出

应用:分页。

分页的方式 1、所有数据一次性传给前端;不适合数据量大的情况。 2、每次后台只给一页数据给前端;

写法:

LIMIT 10;要10条 LIMIT 2,8;从第二条开始,要8个

注意:字句之间有顺序: WHERE, GROUP BY, ORDER BY, LIMIT

如:

代码语言:javascript复制
SELECT class,COUNT(class) FROM student
WHERE score>60
GROUP BY COUNT(class) DESC
LIMIT 2;

至此,归纳了Express的基础使用,以及对模板引擎进行归纳。

1 人点赞