node -Express课程

1 Express简介

1.1 Express的介绍

Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你快速创建各种 Web 和移动设备应用。

简单来说Express就是运行在node中的用来搭建服务器的模块。 ejs

1.2 Express的使用

1.2.1 下载

下载模块:https://www.npmjs.com/

npm:node package manage

npm i express --save 安装express并添加到依赖项

1.2.2 静态资源

use:中间件是一个函数,该函数的职责是完成请求与响应之间的一些逻辑

static:是一个函数,通过该函数可以指定一个文件夹目录,可以直接访问该文件夹内的静态资源,特点有:

① 是一个文件夹目录

② 指定的资源目录可以写多个

③ 静态资源如果名字相同,那么当查找到第一个以后不会继续向下查找

④ 当你的资源名字为index.html时,访问时index.html可以省略

//引入express模块
var express = require('express')
//express得到的是一个函数对象
//创建应用对象
var app = express()
//配置静态资源
app.use(express.static(_diname+"weibo"));//中间件  文件夹
//开启服务器,监听3000端口
app.listen(80,“127.0.0.1”,function() {})

1.2.3 安装方法

1 先初始化npm,会创建一个package.json: npm init -y

2 下载安装express ,两种方法: 得到node-modules

① npm install express

② npm i express

3 创建一个server.js 引入第二点的服务器

**注意:**node-modules不用发(文件太大) 如果开发没有node-modules,在终端中npm i(安装的是记录) 或者npm install

2 路由(Route)

2.1 Route的介绍

路由是指如何定义应用的端点(URIs)以及如何响应客户端的请求。

路由是由一个 URI、HTTP 请求(GET、POST等)和若干个句柄组成的。

2.2 Route的定义

我们可以将路由定义为三个部分:

第一部分:HTTP请求的方法(get或post)

第二部分:URI路径 --地址

第三部分: 回调函数,有三个参数,req,res,next next是一个函数,该回调函数完成后,通过运行next函数可以继续向下查找符合条件的路由

2.3 Route的实现

Express中提供了一系列函数,可以让我们很方便的实现路由:

app.<method>(path,callback)
语法解析:
method指的是HTTP请求方法,比如:
app.get()
app.post()
path指要通过回调函数来处理的URL地址
callback参数是应该处理该请求并把响应发回客户端的请求处理程序

2.4 Route的基本使用

当请求地址是/one时,会执行回调函数,返回‘这里是路由返回的信息,/hello收到了get请求’

当请求方式相同,请求的uri也相同,那么当找到第一个满足条件的路由后,不会继续向下进行匹配。

// 路由:可以通过请求方式,uri 组成的。
app.get("/one",function(req,res){res.end("over1")
})
app.get("/one",function(req,res){res.end("over2")
})

当路由相同时,可以通过next()继续向下查找满足条件的路由

// next 是一个函数。
app.get("/one",function (req,res,next) {console.log(11111111);// res.end("one1");next();// 该回调执行完成后,通过运行next函数可以继续向下查找符合条件的路由。
})
app.get("/one",function (req,res) {console.log(22222222222);res.end("one2");
})

2.5 Request对象

2.5.1 Request对象是什么

Request对象是路由回调函数中的第一个参数,代表了用户发送给服务器的请求信息

通过Request对象可以读取用户发送的请求包括URL地址中的查询字符串中的参数,和post请求的请求体中的参数。

2.5.2 Request对象属性和方法

属性/方法 描述
request.query 获取get请求查询字符串的参数,拿到的是一个对象
request.params 获取get请求参数路由的参数,拿到的是一个对象
request.body 获取post请求体,拿到的是个对象(要借助中间件)bodyparser
request.get(xxxx) 获取请求头中指定key对应的value
request.get(“host”) 127.0.0.1
req.method get
req.httpVersion 版本号 1.1
req.headers 请求头信息
// http://127.0.0.1/my/1/2?userName=zhangsan&age=100
app.get("/my/:a/:b",function (req,res) {// console.log(req.url);// /my/1/2?userName=zhangsan&age=100// console.log(req.httpVersion);//  1.1// console.log(req.query);//  {userName:"zhangsan",age:100}// console.log(req.params);// {a:"1",b:"2"}// console.log(req.method);// GET// console.log(req.body);//undefined  * 需要与 body-parser结合使用。// console.log(req.headers);// 请求头// console.log(req.get("host"));// 127.0.0.1res.writeHead(200,{"content-type":"text/html;charset=utf-8;"})res.end("我的")
})

2.6 Response对象

2.6.1Response对象是什么

Response对象是路由回调函数中的第二个参数,代表了服务器发送给用户的响应信息。

通过Response对象可以设置响应报文中的各个内容,包括响应头和响应体。

2.6.2 Response对象的属性和方法

属性/方法 描述
response.send() 给浏览器做出一个响应 百度, 可以自动加格式,写对象
response.end() (不会自动追加响应头),结束响应,设置响应体的内容
response.download() 告诉浏览器下载一个文件
response.sendFile() 可以设置响应的文件
response.redirect() 输入a页面,打开b页面,认为a页面重定向到b页面 301:永久重定向 http://taobao.com -----> https 302:临时重定向 个人中心
response.set(header,value) 自定义响应头内容 set setHeader hearder
res.status(code) 设置响应状态码
res.json 专门处理json数据,比send执行效率高些
// http://127.0.0.1/my/1/2?userName=zhangsan&age=100
app.get("/my/:a/:b",function (req,res) {// console.log(req.url);// /my/1/2?userName=zhangsan&age=100// console.log(req.httpVersion);//  1.1// console.log(req.query);//  {userName:"zhangsan",age:100}// console.log(req.params);// {a:"1",b:"2"}// console.log(req.method);// GET// console.log(req.body);//undefined  * 需要与 body-parser结合使用。// console.log(req.headers);// 请求头// console.log(req.get("host"));// 127.0.0.1res.writeHead(200,{"content-type":"text/html;charset=utf-8;"})res.end("我的")
})

3 ajax:get和post

3.1 ajax:get接收参数

通过ajax 设置路由器接收参数 页面不需要刷新,更改局部内容

get接收参数,query形式传参

 btn.onclick = function() {const xhr = new XMLHttpRequest();xhr.open("get","http://127.0.0.1/sum?a="+document.myForm.a.value+"&b="+ document.myForm.b.value+"")xhr.send();xhr.onload = function() {document.myForm.sum.value = xhr.responseText;}}
app.get("/sum",function(req,res) {// http://127.0.0.1/sum?a=1&b=2console.log(req.query);//{} const {a,b} = req.query;const sum = a/1+b/1; //转为数字res.end(sum+"")//转为字符串或者res.end(sum.toString())
})

:a /:b 在地址栏中出现,说明a和b不是固定的 是一个变量,可以存放不同的值,可以传参

用req.params来接收参数

 btn.onclick = function () {const xhr = new XMLHttpRequest();// http://127.0.0.1/sum/100/200        xhr.open("get","http://127.0.0.1/sum/"+document.myForm.a.value+"/"+document.myForm.b.value);xhr.send();xhr.onload = function () {// console.log(xhr.responseText);document.myForm.sum.value = xhr.responseText;}}
app.get("/sum/:a/:b",function(req,res) {// http://127.0.0.1/sum/1/2console.log(req.params);//{ a: '1', b: '2' }const {a,b} = req.params;const sum = a/1+b/1; //转为数字res.end(sum.toString())
})

指定后缀(扩展名) 也是用req.params接收,和上面的方式有冲突,只能用其一

// http://127.0.0.1/sum/1/2.html
app.get("/sum/:a/:b.html",function (req,res) {console.log(req.params);// {a:1,b:2}res.end("over");
})
// http://127.0.0.1/sum/1-2.html
app.get("/sum/:a-:b.html",function (req,res) {console.log(req.params);// { a: '1', b: '2' }res.end("/sum/:a-:b.html");
})

3.2 ajax:post接收参数

地址栏里按回车都是get请求 send接收的是一个字符串

当数据格式为:x-www-form-urlencoded

依赖模块bodyParse ,不是内置模块,是第三方模块(node-modules中有)使用中间件,内容在请求体中

bodyParse作用:接收post放置在请求体的内容,并将其放置到req.body当中

有警告,设置extended:false true 代表的是深度解析,解析成数组

btn.onclick = function () {const xhr = new XMLHttpRequest();xhr.open("post","http://127.0.0.1/sum");xhr.setRequestHeader("content-type","application/x-www-form-urlencoded")// send接收的是一个字符串   xhr.send("a="+document.myForm.a.value+"&b="+document.myForm.b.value+"&c[0]=3&c[1]=4");
}
const express = require("express");
// 1、依赖上body-parser模块
const bodyParser = require("body-parser");
const app = express();
// 2、将接收的数据格式设置为urlencoded
// bodyParser作用:接收post放置在请求体的内容。并将其放置到req.body当中。
app.use(bodyParser.urlencoded({// false: a=1&b=2&c[0]=3&c[1]=4  ===> {a:1,b:2,c[0]:3,c[1]:4}// true: a=1&b=2&c[0]=3&c[1]=4  ===> { a: '1', b: '2', c: [ '3', '4' ] }extended:true,// 是否深度解析,一般设置为false
}));
app.use(express.static(__dirname+"/ajax"))
// 要求以post方式访问/sum
app.post("/sum",function (req,res) {console.log(req.body);const {a,b} = req.body;const sum = a/1+b/1;res.end(sum.toString());
})
app.listen(80,function () {console.log("success");
})

当数据格式为:application/json

btn.onclick = function () {const xhr = new XMLHttpRequest();xhr.open("post","http://127.0.0.1/sum");xhr.setRequestHeader("content-type","application/json")// send接收的是一个字符串xhr.send(JSON.stringify({a:document.myForm.a.value,b:document.myForm.b.value}));xhr.onload = function () {document.myForm.sum.value = xhr.responseText;}
}
const express = require("express");
// 1、依赖上body-parser模块
const bodyParser = require("body-parser");
const app = express();
// 2、将接收的数据格式设置为json
// bodyParser作用:接收post放置在请求体的内容。并将其放置到req.body当中。
app.use(bodyParser.json());
app.use(express.static(__dirname+"/ajax"))
// 要求以post方式访问/sum
app.post("/sum",function (req,res) {console.log(req.body);const {a,b} = req.body;const sum = a/1+b/1;res.end(sum.toString());
})
app.listen(80,function () {console.log("success");
})

4 Route的运行流程(all)

当Express服务器接收到一个HTTP请求时,它会查找已经为适当的HTTP方法和路径定义的路由

如果找到一个,Request和Response对象会被创建,并被传递给路由的回调函数

我们便可以通过Request对象读取请求,通过Response对象返回响应

Express中还提供了all()方法,可以处理两种请求。

uri可以写成 ***** 不限制地址

// 限制必须为post请求,但是请求地址不限制
app.post("*",function (req,res) {res.send("post->*")
})
// 限制必须为get请求,但是请求地址不限制
app.get("*",function (req,res) {res.send("get->*")
})

all:不限制请求方式 地址必须为定义的/my

*与all都写,请求方式与地址都不限制

// 不限制请求方式,地址必须为/my
app.all("/my",function (req,res) {res.send("all->我的")
})
// 请求方式与地址不限制。
app.all("*",function (req,res) {res.send("all->我的")
})

以上的代码等于use的使用

app.use(function (req,res,next) {// res.send("use")next();
})
// 相当于
app.all("*",function (req,res,next) {// res.send("all->我的")next();
})

all 案例

应用:404案例 放在最后面 当输入不是文件的名字时,显示404或者定向到指定的页面

app.all("*",function (req,res) {// res.send("404");//  res.sendFile(__dirname+"/site/404.html");res.redirect("/");// 重定向到首页
})

应用:解决跨域 放在最前面 或者哪些页面需要就在哪一行添加比如添加广告页

app.all("*",function (req,res,next) {res.set("Access-Control-Allow-Origin","*");next();
})
app.use(function (req,res,next) {res.set("Access-Control-Allow-Origin","*");next();
})
app.get("/addAdv",function (req,res) {// res.set("Access-Control-Allow-Origin","*");res.send("添加广告")
})

将中间件封装成函数,在程序中引入

const utils = require("./utils");
const fs = require("fs");
module.exports = {over(req,res,next){res.set("Access-Control-Allow-Origin","*");next();}
const middleware = require("./module/middleware");
app.use(middleware.over)

传递参数,要有返回值,否则是undefined,闭包

const utils = require("./utils");
const fs = require("fs");
module.exports = {over(req,res,next){res.set("Access-Control-Allow-Origin","*");next();}fn(origin){return function (req,res,next) {res.set("Access-Control-Allow-Origin",origin);next();}},
app.use(middleware.fn("http://localhost:10241"))

应用:权限设置:重定向redirect

 app.use(function (req,res,next) {if(req.query.vip) next()else res.redirect("/");})

用以上的方法,404始终执行不到,所以封装next,再引入

const utils = require("./utils");
const fs = require("fs");
module.exports = {vipLogin(req,res,next){if(req.query.vip) next();else res.redirect("/")}
app.get("/addGoods",vipLogin,function (req,res) {res.send("添加商品")
})
app.get("/upGoods",vipLogin,function (req,res) {res.send("修改商品")
})

应用:用户的记录功能(访问地址,时间,IP),用next 引入封装的时间

IP:在端口号后面设置格式为初始值,得到的就是IP4版本

const express = require("express");
const utils = require("./module/utils");
const middleware = require("./module/middleware");
const fs = require("fs");
const app = express();
app.use(middleware.createLog(__dirname+"/my.log"))
app.use(function (req,res,next) {let str = "";str+="访问地址:"+req.url+"\n";str+="访问IP:"+req.connection.remoteAddress+"\n";str+="访问时间:"+utils.getNowTime()+"\n";str+="*************************************************\n";fs.writeFile(__dirname+"/data.log",str,{flag:"a"},function (err) {next();})// console.log(req.connection.remoteAddress);//})
app.get("/",middleware.createLog(__dirname+"/my.log"),function (req,res) {res.send("首页")
})
app.get("/reg",function (req,res) {res.send("注册")
})
....

简化,封装,引用

return function (req,res,next) {let str = "";str+="访问地址:"+req.url+"\n";str+="访问IP:"+req.connection.remoteAddress+"\n";str+="访问时间:"+utils.getNowTime()+"\n";str+="*************************************************\n";fs.writeFile(url,str,{flag:"a"},function (err) {next();})

route 模块化

内置;express.router

const express = require("express");
const app = express();
const userRouter = express.Router();
const advRouter = express.Router();
const goodsRouter = express.Router();
// 路由模块化:将拥有相同特点的路由放置到一个JS当中。
userRouter.get("/",function (req,res) {res.send("首页")
})
userRouter.get("/reg",function (req,res) {res.send("注册")
})
userRouter.get("/login",function (req,res) {res.send("登陆")
})
userRouter.get("/my",function (req,res) {res.send("个人中心")
})advRouter.get("/addAdv",function (req,res) {res.send("添加广告")
})goodsRouter.get("/addGoods",function (req,res) {res.send("添加商品")
})
goodsRouter.get("/upGoods",function (req,res) {res.send("修改商品")
})
goodsRouter.get("/delGoods",function (req,res) {res.send("删除商品")
})app.use(userRouter);
app.use(goodsRouter);
app.use(advRouter);
app.all("*",function (req,res) {// res.send("404");// res.sendFile(__dirname+"/site/404.html");res.redirect("/");// 重定向
})
app.listen(80,function () {console.log("success");
})

优化版:各种封装,再引入

const express = require("express");
const userRouter = require("./module/router/user");
const advRouter = require("./module/router/adv");
const goodsRouter = require("./module/router/goods");
const app = express();
app.use(userRouter);
app.use(goodsRouter);
app.use(advRouter);
app.all("*",function (req,res) {// res.send("404");// res.sendFile(__dirname+"/site/404.html");res.redirect("/");// 重定向
})
app.listen(80,function () {console.log("success");
})

adv.js

const router = require("express").Router();router.get("/addAdv",function (req,res) {res.send("添加广告")
})router.get("/upAdv",function (req,res) {res.send("修改广告")
})module.exports = router;

good.js

const router = require("express").Router();
router.get("/addGoods",function (req,res) {res.send("添加商品")
})
router.get("/upGoods",function (req,res) {res.send("修改商品")
})
router.get("/delGoods",function (req,res) {res.send("删除商品")
})module.exports  = router;

user.js

const router = require("express").Router();
router.get("/",function (req,res) {res.send("首页")
})
router.get("/reg",function (req,res) {res.send("注册")
})
router.get("/login",function (req,res) {res.send("登陆")
})
router.get("/my",function (req,res) {res.send("个人中心")
})
module.exports = router;

5 中间件

5.1中间件简介

Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件。

中间件(Middleware) 是一个函数,它可以访问请求对象(request), 响应对象(response), 和 web 应用中处于请求-响应循环流程中的中间件,一般被命名为 next 的变量。

5.2中间件功能

  1. 执行任何代码。

  2. 修改请求和响应对象。

  3. 终结请求-响应循环。

  4. 调用堆栈中的下一个中间件。

5.3 中间件的分类

  1. 应用级中间件(过滤非法的请求,例如防盗链)

  2. 第三方中间件(通过npm下载的中间件,例如body-parser)

  3. 内置中间件(express内部封装好的中间件)

  4. 路由器中间件 (Router)

5.4中间件实例

//引入express
var express = require('express')
//创建应用对象
var app = express()
//配置静态资源
app.use(express.static('public'))
//中间件,没有挂载路径,应用的每个请求都会执行该中间件
app.use(function (req, res, next) {console.log('这是中间件的响应~~~')//如果不调用next方法,下面路由将不起作用next()
})
//配置路由
app.get('/index', function (req, res) {console.log('路由index收到get请求')res.send('这里是路由返回的信息,/hello收到了get请求')
})app.post('/index', function (req, res) {console.log('路由index收到post请求')res.send('这里是路由返回的信息,/hello收到了post请求')
})//启动服务器
app.listen(3000, function () {console.log('服务器启动成功,监听3000端口')
})

6 Router路由器

6.1 Router是什么

Router 是一个完整的中间件和路由系统,也可以看做是一个小型的app对象。

6.2 为什么使用Router

Router—路由器 Route–路由

为了更好的分类管理route

6.3 Router的使用

//引入express模块
var express = require('express');
//引入body-parser模块
var bodyParser = require('body-parser');
//引入Users模型对象
var Users = require('../models/Users');
//创建router对象
var router = express.Router();
//解析请求体,将参数挂在到req.body
router.use(bodyParser.urlencoded({extended: false}));
router.post('/login', function (req, res) {var username = req.body.username;var password = req.body.password;Users.findOne({username: username}, function (err, data) {if (!err && data && data.password === password) {res.send('恭喜您登录成功~~~');} else {res.send('用户名或密码错误~~~');}})
})
router.post('/regist', function (req, res) {//获取用户提交的参数var username = req.body.username;var password = req.body.password;var rePassword = req.body.rePassword;var email = req.body.email;/*1. 正则验证(-)2. 密码和确认密码是否一致3. 去数据库中查找有无此用户名4. 插入数据*///判断密码和确认密码是否一致if (password !== rePassword) {res.send('两次密码输入不一致,请重新输入~~');return}//去数据库中查找有无此用户名Users.findOne({username: username}, function (err, data) {if (!err) {/*data如果查到了  返回文档对象如果没找到  返回null*/if (data) {// 查到了指定用户名res.send(data.username + '用户名已被注册~~请重新输入');} else {// 没有找到指定有户名,将用户信息插入到数据库中Users.create({username: username,password: password,email: email}, function (err) {if (!err) {res.send('恭喜您,注册成功了~~');} else {res.send('error');}})}} else {res.send('error');}})
})
//暴露路由器对象
module.exports = router

7 EJS模板(了解)

7.1 EJS是什么

EJS是一个高效的 JavaScript 模板引擎。

模板引擎是为了使用户界面与业务数据(内容)分离而产生的。

简单来说,使用EJS模板引擎就能动态渲染数据。(服务器端渲染)

7.2 EJS的使用

  1. 下载安装

npm i ejs --save

  1. 配置模板引擎

app.set(“view engine” , “ejs”);

  1. 配置模板的存放目录

app.set(“views”,"./views")

  1. 在views目录下创建模板文件

xxx.ejs

  1. 使用模板,通过response来渲染模板

response.render(‘模板名称’, 数据对象)

7.3 EJS语法

ejs.render():第一个参数是一个字符串,第二个参数是数据,数据的格式为对象

字符串当中可以直接使用对象的属性

以下是一个ejs文件:

const ejs = require("ejs");const arr = ["一","二"];
const pageSum = 12;
const str = `<div><%=num%>   //12<%for(let i=0;i<num;i++) {%><h3><%= i%></h3>  //<h3>0-11</h3><%}%></div>`console.log(ejs.render(str,{arr,           num:pageSum}))

通过服务使用ejs

const express = require("express");
const ejs = require("ejs");
const bookList = require("./data");
const app = express();
app.get("/getBookList",function (req,res) {const htmlStr = ejs.render( `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>1服务端渲染下的index.html</title></head><body><%=bookList.length%></body><script></script></html>`,{bookList})res.send(htmlStr);})
app.listen(80,function () {console.log("success");
})

将界面与数据进行分离

home.js

<table><tr><td>id</td><td>作者</td><td>作品</td></tr><%for(let i=0;i<bookList.length;i++){%><tr><td><%=bookList[i].id%></td><td><%=bookList[i].author%></td><td><%=bookList[i].bookName%></td></tr><%}%></table>
const express = require("express");
const ejs = require("ejs");
const bookList = require("./data");
const app = express();
app.get("/getBookList",function (req,res) {// home.ejs--->views->home.ejs  默认会去views文件夹当中查找文件。// res.render("home.ejs",{//     a:1,//     b:2,//     bookList// })// 将默认文件夹views更改为当前目录下的html文件夹app.set("views",__dirname+"/html");app.set("view engine","html");// .ejs ----> .html  更改扩展名app.engine("html",ejs.renderFile);// 将html通过ejs的解析数据方法来使用res.render("my.html",{a:1,b:2,bookList})
})
app.listen(80,function () {console.log("success");
})

8 会话控制session

8.1会话控制是什么

HTTP协议是一个无状态的协议,它无法区分多次请求是否发送自同一客户端。

而我们在实际的使用中,却又大量的这种需求,我们需要通过会话的控制来解决该问题。

8.2 cookie

8.2.1 cookie是什么

cookie本质是一个存储在浏览器的文本,随着http请求自动传递给服务器。

也可以说cookie是一个头(请求头/响应头):

服务器以响应头的形式将Cookie发送给浏览器

浏览器收到以后会自动将Cookie保存

浏览器再次访问服务器时,会以请求头的形式将Cookie发回

服务器就可以通过检查浏览器发回的Cookie来识别出不同的浏览器

① cookie来自于服务器,cookie是在服务端生成的

通过浏览器打开某个网址,在响应头当中增加Set-cookie

② 会将cookie保存在本地

③ 当你再次发送请求时,会将保存的cookie以请求头的形式发送给服务端

④ 服务端可以接收cookie,可以对cookie进行验证,从而可以识别用户是谁

app.get("/setCookie",function(req,res) {// 设置一个cookie,第一个参数为设置,第二个参数为值res.set("Set-cookie","userName=laodai")res.send("设置cookie成功")
})

**注意:**创建多个cookie,不能单独创建,要以数组的形式来设置

app.get("/setCookie",function(req,res) {res.set("Set-cookie",["userName=laodai","age=25"])res.send("设置cookie成功")
})

获取值

app.get("/getCookie",function(req,res) {console.log(req.header.cookie)res.send("获取cookie成功")
})

8.2.2 cookie的不足

各个浏览器对cookie的数量和大小都有不同的限制,这样就导致我们不能在Cookie中保存过多的信息。一般数量不超过50个,单个大小不超过4kb。

cookie是由服务器发送给浏览器,再由浏览器将cookie发回,如果cookie较大会导致发送速度非常慢,降低用户的体验。

8.2.3 cookie的使用

通过配置cookie-parser中间件,可以将cookie解析为一个对象,并且添加为req的cookies属性,使用步骤:

  1. 下载安装
npm i cookie-parser --save
  1. 引入
var cookieParser = require("cookie-parser");
  1. 设置为中间件
app.use(cookieParser());
  1. 创建Cookie
 res.cookie("username","laodai")res.cookie("age","12",{maxAge:20*1000,//单位毫秒})

//设置一个有效期为1天的cookie

res.cookie("username","sunwukong" , {maxAge:1000*60*60*24});

//设置一个永久有效的cookie

res.cookie("username","sunwukong" , {maxAge:1000*60*60*24*365*10});
  1. 修改Cookie

​ //Cookie一旦发送给浏览器,就不能再修改了

​ //但是我们可以使用同名的cookie来替换已有cookie

res.cookie("username","zhubajie");
  1. 删除Cookie

//可以通过通过使用一个立即失效的cookie来替换cookie的形式来删除cookie

res.cookie("username","",{maxAge:0});

//用来删除一个cookie

res.clearCookie(“username”)//用来删除一个指定cookie

获取值:

app.get("/getCookie",function(req,res) {console.log(req.cookies)//接收res.send("获取cookie成功")
})

8.2.4 cookie的属性

属性:

max-age:指定过期时间 单位为秒 默认为session

expires:指的是utc时间,当前时间超过指定时间为过期

如果max-age与expires同时指定的话,听max-age的

如何指定UTC时间:

function getUtcTime(s=10) {const da = new Date()da.setTime(Date.now+s*1000)//指定时间return da.toUTCString()//转换为UTC时间
}age=12;max-age=3600;expires=${getUtcTime()};path=/abc

③ ***path:***指定使用cookie的目录,如果值为/abc,说明值允许在/abc目录下使用cookie

④***domain:***域名,如果设置为.xxx.com,那么不限制二级域名,如果设置为api.xxx.com,那么只能够在api.xxx.com中访问

⑤ max-age:0 将过期时间设置为0

8.3 session

8.3.1 session是什么

Session 是一个对象,存储特定用户会话所需的属性及配置信息。

8.3.2 session运作流程

我们可以在服务器中为每一次会话创建一个对象,然后每个对象都设置一个唯一的id,并将该id以cookie的形式发送给浏览器,然后将会话中产生的数据统一保存到这个对象中,这样我们就可以将用户的数据全都保存到服务器中,而不需要保存到客户端,客户端只需要保存一个id即可。

8.3.3 session的使用

  1. 下载安装

npm i connect-mongo express-session --save

  1. 引入模块

var session = require(“express-session”);

  1. 设置为中间件
app.use(session({name: 'id22',  //设置cookie的name,默认值是:connect.sidsecret: 'atguigu', //参与加密的字符串(又称签名)saveUninitialized: false, //是否设置初始值valueresave: true ,//是否在每次请求时重新保存sessioncookie: {httpOnly: true, // 开启后前端无法通过 JS 操作maxAge: 1000*30 // 这一条 是控制 sessionID 的过期时间的!!!path:"/abc"domain:".wx.com"},
}));

4)设置值

app.get("/setSession",function (req,res) {req.session.userName = "laodai";req.session.age = 25;res.send("设置成功")
})

5)获取值

app.get("/getSession",function (req,res) {console.log(req.session.userName,req.session.sge)//获取值res.send("获取成功")
})

6)删除值

app.get("/delSession",function (req,res) {// 第一种方法req.session.cookie.maxAge=0;// 第二种方法req.session.destroy(function(err) {res.send("删除成功")})

6.3.4 cookie和session的区别

  1. 存在的位置:

cookie 存在于客户端,临时文件夹中

session 存在于服务器的内存中,一个session域对象为一个用户浏览器服务

  1. 安全性:

cookie是以明文的方式存放在客户端的,安全性低,可以通过一个加密算法进行加密后存放

session存放于服务器的内存中,所以安全性好

  1. 网络传输量:

cookie会传递消息给服务器

session本身存放于服务器,但是通过cookie传递id,会有少量的传送流量

  1. 生命周期(以20分钟为例):

cookie的生命周期是累计的,从创建时,就开始计时,20分钟后,cookie生命周期结束

session的生命周期是间隔的,从创建时,开始计时如在20分钟,没有访问session,那么session生命周期被销毁;但是,如果在20分钟内(如在第19分钟时)访问过session,那么,将重新计算session的生命周期;关机会造成session生命周期的结束,但是对cookie没有影响

  1. 大小:

cookie 保存的数据不能超过4K,很多浏览器都限制一个站点最多保存50个cookie

session 保存数据理论上没有任何限制(内存有多大就能有多大)

9 jwt:json web token

前后端通讯,进行加密

第三方模块:npm install jwt-simple 先进行安装,再引用

encode加密 decode解密

解密流程:

1 用户登录成功时,服务端生成token(令牌),返回给前端

2 前端保存token

3 当前端请求有权限限制的接口时,将token传递给服务端

4 服务端接收token,并解析

验证token(authorization授权)是否正确:

① 是否可以正常解析

② 时间是否过期

server.js

const jwt = require("jwt-simple");
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(express.static(__dirname));
app.use(bodyParser.json())
// userName,passWord
const KEY = "%^&*()_";
app.get("/main",function (req,res) {// console.log(jwt.decode(req.headers.authorization,KEY));console.log(req.headers.cookie.split("=")[1]);const {userName,overTime} = jwt.decode(req.headers.cookie.split("=")[1],KEY);console.log(userName,overTime)res.json({ok:1,msg:"成功"})// const {userName,overTime} = jwt.decode(req.headers.authorization,KEY);// if(Date.now()>overTime){//     res.send({//         ok:-1,//         msg:"已过期"//     })// }else{//     res.send({//         ok:1,//         msg:"成功"//     })// }})
app.post("/login",function (req,res) {const {userName,passWord} = req.body;if(userName === "admin" && passWord === "123456"){const token = jwt.encode({userName:"admin",overTime:Date.now()+10*1000},KEY);res.set("Set-cookie","connect.id="+token);res.json({ok:1,// token})}else{res.json({ok:-1,msg:"登陆失败"})}
})
app.listen(80,function () {console.log("success");
})

login.html

const btn = document.querySelector("button");btn.onclick = function () {const xhr = new XMLHttpRequest();xhr.open("post","http://127.0.0.1/login");xhr.setRequestHeader("content-type","application/json");xhr.send(JSON.stringify({userName:"admin",passWord:"123456"}));xhr.onload = function () {const {ok,token,msg} = JSON.parse(xhr.responseText);if(ok === 1){localStorage.userName = "admin";// localStorage.token = token;// 页面之间的跳转window.location.href = "/main.html"}else{alert(msg);}}}

main.html

if(localStorage.token){const xhr = new XMLHttpRequest();xhr.open("get","http://127.0.0.1/main");// xhr.setRequestHeader("authorization",localStorage.token);xhr.send();xhr.onload = function () {const {ok,msg} = JSON.parse(xhr.responseText);if(ok === -1){location.href="/login.html";}// console.log(xhr.responseText);}}else{location.href="/login.html"}

Express-静态资源-路由-ajax-session相关推荐

  1. 前端学习(1378):express静态资源处理

    const express = require('express'); const path=require('path'); const app = express();app.use(expres ...

  2. 实战react技术栈+express前后端博客项目(3)-- 后端路由、代理以及静态资源托管等配置说明...

    项目地址:github.com/Nealyang/Re- 本想等项目做完再连载一波系列博客,随着开发的进行,也是的确遇到了不少坑,请教了不少人.遂想,何不一边记录踩坑,一边分享收获呢.分享当然是好的, ...

  3. Spring Boot 静态资源映射与上传文件路由配置

    默认静态资源映射目录 默认映射路径 在平常的 web 开发中,避免不了需要访问静态资源,如常规的样式,JS,图片,上传文件等;Spring Boot 默认配置对静态资源映射提供了如下路径的映射 /st ...

  4. node.js学习笔记3 express基本使用、托管静态资源、express中间件

    内容 1. 什么是express 1.1 http模块和express的关系 2. express能做什么 3. express的基本使用 3.1 安装 3.2 创建最基本的web服务器 3.3 监听 ...

  5. 关于使用NodeJS+Express搭建服务器访问静态资源的一些填坑经验

    前言 NodeJs是一个能让前端开发工程师变成全栈工程师的神器.最近在搞一个私活,需要上传图片到服务器存储.按照以前的想法,是用Java写代码搭服务器.奈何,大学毕业后就一直在搞前端和安卓开发.Jav ...

  6. Koa 学习 01 Koa 介绍和基本使用(路由、静态资源托管、中间件)

    Koa 介绍 Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造,致力于成为 web 应用和 API 开发领域中的一个更小.更富有表现力.更健壮的基石. 官网:https://k ...

  7. 渲染静态页面、get请求、post请求、express框架、路由、中间件

    1. 渲染静态页面 const http = require('http'); const fs = require('fs'); const url = require('url'); const ...

  8. Express请求处理-静态资源的处理

    场景 Node的Web应用框架Express的简介与搭建HelloWorld: Node的Web应用框架Express的简介与搭建HelloWorld_霸道流氓气质的博客-CSDN博客 注: 博客: ...

  9. Express与传统Web应用(服务端渲染、art-template模板引擎、配置静态资源托管)

    一.服务端渲染相关的概念 什么是渲染? 例如对于我们前端开发者来说最常见的一种场景就是:请求后端接口数据,然后将数据通过模板绑定语法绑定到页面中,最终呈现给用户. 数据: 模板: 渲染(数据+模板)结 ...

  10. nodejs 创建一个静态资源服务器 +路由

    0.补充 1.Node.js 创建的第一个应用 1.引入 http 模块 var http = require("http"); 2.创建服务器 接下来我们使用 http.crea ...

最新文章

  1. 微信8.0.6正式发布,新增了7大变化,个个实用~
  2. android屏幕适配详解
  3. [MyBatisPlus]模拟多数据源环境及测试
  4. mongoose $sum
  5. FireEye:GreedyWonk行动针对经济和外交政策网站
  6. 动态图制作软件设计(二)
  7. gdb调试出现“no debugging symbols found”
  8. 黑马程序员-学习日志-文件的合并
  9. Excel查询颜色RGB值
  10. python中的snip用法_--snip--总是报错,找了好久不知道问题出在哪,望大佬求解(python-pygame)...
  11. 记dubbo consumer服务因订阅其他有异常的服务导致超时的问题
  12. 爬虫(二) 豆瓣音乐评论爬虫 文末附完整代码
  13. 菜鸟知识-五大智能手机操作系统
  14. 博通wifi驱动详解
  15. 编码器基础知识大扫盲
  16. 余弦相似度:通过计算两个向量的夹角余弦值来评估他们的相似度
  17. java如何将mp4写入光盘_iOS - 读取/写入mp4视频的XMP元数据
  18. cityscapes数据处理
  19. web前端项目上线流程是怎样的
  20. 从N986和A199看华为中兴

热门文章

  1. mysql text 函数的使用方法_MySQL空间数据操作:GeomFromText()和astext()函数报错解决...
  2. Jenkins ssh 发布jar 时区不对
  3. Beyond Compare 4
  4. JDK时区与电脑系统时区不一致,导致时间new date不对
  5. linux 真实内存,Linux计算真实可用内存
  6. MySQL笔记(四)多表连接查询
  7. 小汤学编程之JavaScript学习day01——认识JS、JS基础语法
  8. 小汤学编程之JAVA基础day15——枚举、注解和Properties
  9. 剑指前端(前端入门笔记系列)——数组(基本语法)
  10. python 对redis key的基本操作