第一步
- 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 处理静态文件的中间件
代码语言: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
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、读写
代码语言: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 如:
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 条件
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
如:
代码语言:javascript复制SELECT class,COUNT(class) FROM student
WHERE score>60
GROUP BY COUNT(class) DESC
LIMIT 2;
至此,归纳了Express的基础使用,以及对模板引擎进行归纳。