初步使用
第一步
- 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
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>
- 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
如:
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的基础使用,以及对模板引擎进行归纳。