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

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 【NodeJS】归纳篇(三)Express | 链式操作 | cookie && session | 模板引擎 | Router | mysql

初步使用

第一步

  • npm install express

示例:server.js

  • 1、创建服务
  • 2、监听
  • 3、处理请求
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 处理静态文件的中间件

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这个目录下读取静态文件

处理数据

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

链式操作

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

改写示例:

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,这是一个可选操作,即供用户选择是否要下一步操作。

中间件怎么写——原生

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。

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模块

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
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签名
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、读写

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/

const jade = require('jade');
var str = jade.renderFile('a.jade',{pretty:true});
console.log(str);

a.jade

//用缩进代表层级
html
 head
  style
  script
 body
  div
  p  
  • ejs

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

ejs.js

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

a.ejs

<html>
  <head>
  </head>
  <body>
    {%= name %} //注意变量前后的空格,另外变量name来自ejs.js中
  </body>
</html>

路由-route:一个小型的Express

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

  • 假设访问 xxx.com/news ,则调用 mod_news
    子路由 post , 则调用 news_post
  • 访问 xxx.com/users ,则调用 mod_users
    如:
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
});
})

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

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

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

server.use('/article',require('./route/createRouterA.js')());

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

mysql

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

例如:user_table表

ID      
username  用户名       varchar(32)
password  密码        varchar(32)
src       用户头像     varchar(64)

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

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)

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

//createPool
const db = mysql.createPool({
  host:'localhost',
  port:3306,
  user:'root',
  password:'root',
  database:'testdb'
});

sql语言-CURD

SQL 标准写法:

1、关键字大写

2、库、表、字段需要加上’’

3、分号结尾

//增-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 条件
WHERE age<=10
WHERE age>=10 AND score<60
WHERE age>15 OR score>80
  • ORDER 排序
ORDER BY age ASC/DESC
//先按价格升序,再按销量降序
ORDER BY price ASC,sales DESC 
  • GROUP 聚类、合并相同
//按班级分组,将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

如:

SELECT class,COUNT(class) FROM student
WHERE score>60
GROUP BY COUNT(class) DESC
LIMIT 2;

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


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
SQL 关系型数据库 MySQL
Python怎么操作Mysql数据库
Python怎么操作Mysql数据库
51 0
|
1月前
|
SQL 关系型数据库 MySQL
python如何操作mysql数据库
python如何操作mysql数据库
24 0
|
2月前
|
SQL 存储 算法
mysql常用指令操作
mysql常用指令操作
|
21天前
|
存储 SQL 关系型数据库
【MySQL】4. 表的操作
【MySQL】4. 表的操作
21 0
|
3月前
|
关系型数据库 MySQL
MySQL对小数进行四舍五入等操作
MySQL对小数进行四舍五入等操作
25 0
|
3月前
|
SQL 关系型数据库 MySQL
MySQL| 数据库的管理和操作【操作数据库和操作表】【附练习】
MySQL | 数据库的基本操作和表的基本操作【附练习】
|
1月前
|
SQL 关系型数据库 MySQL
|
3月前
|
SQL 关系型数据库 MySQL
MySQL | 数据库的管理和操作【表的增删改查】(一)
MySQL | 数据库的管理和操作【表的增删改查】
|
3月前
|
SQL 关系型数据库 MySQL
MySQL | 数据库的管理和操作【表的增删改查】(二)
MySQL | 数据库的管理和操作【表的增删改查】(二)
|
19天前
|
缓存 关系型数据库 MySQL
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)
MySQL查询优化:提速查询效率的13大秘籍(合理使用索引合并、优化配置参数、使用分区优化性能、避免不必要的排序和group by操作)(下)