express
- 使用express框架来搭建服务器无需再配置过多服务器端内容,其底层已经将其为我们配置。
express
框架的中间件、基本路由的底层实现了路由代码封装,根据不同的写法去实现不同的功能- 在
express
框架的路由使用中,若想让页面正常显示,必须要在中间件/路由的回调函数中调用res.send(...)
,否则页面会一直加载
一、 使用express创建一个工程
- 创建
app.js
文件 - 初始化:
npm init
后得到package.json
文件 - 安装
express
:npm install express --save-dev
- 搭建服务器:
① 在app.js
中引入express
:const express = require("express")
;
② 创建app
对象:let app = new express()
/let app = express()
③ 配置当前服务器的路由:app.get("/",(req,res)=>{res.send("express")})
④ 给app
配置监听端口号:app.listen(port,callback)
//搭建服务器demo
//打开localhost:8100页面显示express
const express = require("express");
let app = new express();
app.get("/",(req,res)=>{
res.send("express")
})
app.listen(8100,()=>{
console.log("server start")
})
二、基本路由
- 路由的url可以为字符串、字符串模式以及正则表达式
- 如果需要在路径中加上
$
,需要用([\$])
转义。eg:"/data/([\$])book"
最后会解析为/data/$book
- 当在路径中输入
.txt
等带有文件标识时,如果当前目录并不是静态资源目录,则会直接将其当做普通的字符串解析,而并不是去访问该目录下的文件。
app.all(url,(req,res)=>{})
:访问地址为url(无论什么类型的请求都可以)app.get(url,(req,res)=>{})
:访问地址为url且为get请求app.post(url,(req,res)=>{})
:访问地址为url且为post请求app.put(url,(req,res)=>{})
:访问地址为url且为put请求app.delete(url,(req,res)=>{})
:访问地址为url且为delete请求
路由回调函数中可用的方法
url基于字符串模式:
1. 与acd
和abcd
相匹配
app.get('/ab?cd', function (req, res) {
res.send('ab?cd')
})
2. 与abcd
,abbcd
,abbbcd
等等相匹配
app.get('/ab+cd', function (req, res) {
res.send('ab+cd')
})
3. 与abcd
,abxcd
,abRANDOMcd
,ab123cd
等匹配
app.get('/ab*cd', function (req, res) {
res.send('ab*cd')
})
4. 与/abe
和/abcde
相匹配
app.get('/ab(cd)?e', function (req, res) {
res.send('ab(cd)?e')
})
三、express中配置静态资源文件
app.use(express.static(url))
- url为要配置的静态资源目录
- eg:
app.use(express.static("public/static"))
代表根目录下的public
,public
目录下的static
文件为静态资源。当输入网址为https://localhost:8100/1.png
时,实际上取的是https://localhost:8100/public/static/1.png
文件(若直接输入这个网址是无法取到1.png
的)
app.use(输入的url,express.static(实际访问的资源目录))
- 第一个参数为虚拟路径,第二个参数中的的路径为实际配置的静态资源目录
eg:app.use("/static",express.static("public/static"))
:当输入localhost:8100/static
时,实际上进入的是localhost:8100/public/static
文件夹
四、中间件
- 对于同一个路由,每个中间件的req和res是完全相同的(所指向的指针相同)
- 所有中间件的执行都在请求收到回复后。
- 所有中间件中只能有一个res.send()
- 如果对于同一个路由有多个中间件,则会按照路由配置的顺序执行不同的中间件(如果要执行下一个中间件,必须在当前中间件中调用
next()
)
1. 中间件的任务
- 执行任何代码。
- 更改请求和响应对象(不能更改已经请求过的内容,eg:操作req的请求头,会报
Cannot set headers after they are sent to the client
的错误) - 结束请求-响应周期。
- 调用堆栈中的下一个中间件。
2. 应用层中间件
- 应用层中间件如果没有拦截
url
,只有一个回调函数,则所有路由都会执行(全局)- 通过
app.use(url,(req,res)=>{})
方法将应用层中间件绑定在app
实例上。该方法拦截请求路径为url
的所有类型的请求- 通过
app.get(url,(req,res)=>{})/aqq.post(url,(req,res)=>{})
来拦截路径为url
的get
/post
请求。
4.== 当请求当前路由对应的子路由时,也会执行当前路由的中间件==- 若当前请求的路由不存在时,不会执行其父路由对应的回调函数,而是会报错。但会执行
/
路由对应的回调函数以及全局路由对应的回调函数
//请求http://localhost:8100/test/test时输出:
//我是第一层中间件
//第一层
//第二层
//我是子路由
app.use("/",(req,res,next)=>{
console.log("我是第一层中间件");
next();
})
app.use("/test",(req,res,next)=>{
console.log("第一层");
next();
},(req,res,next)=>{
console.log("第二层");
next();
})
app.use("/test/test",(req,res,next)=>{
console.log("我是子路由");
res.send(123);
})
3. 路由中间件
router.get(url,(req,res,next)=>{})
:拦截路由为url
且为get
类型的http
请求,不拦截其get
请求的子路由的http
请求router.get("/",(req,res,next)=>{})
:拦截路由为/
的get
类型的http
请求router.use("/",(req,res,next)=>{})
:拦截所有路由的所有类型的请求,包括路由为/
以及其子路由的http请求router.use(url,(req,res,next)=>{})
:若请求路由为其子路由且该子路由未配置,则会执行该路由的回调函数。若其子路由配置,则不会执行。拦截路由为url
的所有类型的http
请求- 对于4中的子路由未配置的情况不会报错,会执行其父路由的回调函数
//当输入https://localhost:8100/login/hello/hello时会输出:
//所有都执行
//hello执行
//1执行
let router = express.Router();
router.use("/",function(req,res,next){
console.log("所有都执行");
next();
})
router.get("/hello",(req,res,next)=>{
console.log("get请求");
next()
})
router.use("/hello",(req,res,next)=>{
//http://localhost:8100/login/hello
console.log("hello执行")
next();
},(req,res,next)=>{
console.log("1执行")
res.send("hello")
})
router.use("/login",(req,res,next)=>{
//http://localhost:8100/login/login
res.send("login")
})
// //路由和app关联
app.use('/login',router)
//当输入https://localhost:8100/login/hello/hello时会输出:
//所有都执行
//子组件
let router = express.Router();
router.use("/",function(req,res,next){
console.log("所有都执行");
next();
})
router.get("/hello",(req,res,next)=>{
console.log("get请求");
next()
})
router.use("/hello",(req,res,next)=>{
//http://localhost:8100/login/hello
console.log("hello执行")
next();
},(req,res,next)=>{
console.log("1执行")
res.send("hello")
})
router.use("/hello/hello",(req,res,next)=>{
console.log("子组件")
res.send("hello子组件")
})
// //路由和app关联
app.use('/login',router)
步骤:
- 获取路由对象:
let router = express.Router();
- 配置路由:
router.use/router.get/router.post
- 路由与app绑定:
app.use(url,router)
(第一个参数为在哪个路径下配置路由。eg:若url为“/login”,则对于第二步的所有路由配置,其相对根目录为https://localhost:8100/login
,而不是https://localhost:8100
)
//下面示例中,当输入http://localhost:8100/login时执行路由为/的中间件
//当输入http://localhost:8100/login/hello时执行路由为hello的中间件
let router = express.Router();
router.use("/",function(req,res,next){
console.log("所有都执行");
next();
})
router.get("/hello",(req,res,next)=>{
console.log("get请求");
res.send("123");
})
app.use('/login',router)
4. 第三方中间件
①body-parser
当
http
请求为post
方式时,需要用到body-parser
(req.body)来提取出请求体里面的数据,否则在express
中是无法取出来值的。
使用:
- 安装:
npm install body-parser --save-dev
- 引入:
let bodyparser = require("body-parser")
- 在
express
中配置:
① 配置请求编码格式:app.use(bodyparser.urlencoded({extended:false}))
② 配置返回数据方式:app.use(bodyparser.json())
- 通过
req.body
提取到提交的值(json值)
②cookie-parser
可将数据存入在浏览器缓存中,标记后的数据并不是加密,而是被加工过的标记字符分隔开了
使用
- 安装:
npm install cookie-parser --save-dev
- 引入:
let cookieparser = require("cookie-parser")
- 与
app
关联:app.use(cookieparser())
属性
属性 | 解释 |
---|---|
res.cookies |
获取未标记的cookie ,返回的是json数据 |
res.signedCookies |
获取标记的cookie ,返回的是json数据 |
方法
res.cookie(key,value,options)
- 设置cookie
- option:
maxAge
设置存活时长 、signed
设置是否被标记(true为被标记,false为不被标记)
- 当
signed
为true时,需要在cookie-parser
与app
关联时添加标记字符(eg:app.use(cookieparser("123"))
,标记字符为123)
5. express的get
传值
①动态传值
- 对路径有要求,必须在路由配置时给路由添加
:
- 通过
req.params
获取动态路由传递的参数,参数名为路由配置时:
后的参数名。
② get传值
取值:
url.parse(req.url,true).query
6. express
框架里面的ejs
- 通过设置
ejs
模板引擎和html
模板引擎都可以让express
识别ejs
语法。- 若设置
html
模板引擎,则可以在html
中写ejs
语法。且renderFile
中path
为html
文件的路径。
步骤:
- 安装
ejs
:npm install ejs --save-dev
- 设置
ejs
模板引擎:app.set("view engine","ejs")
(让express识别ejs语法) - 使用
ejs
ejs.renderFile("view/index.ejs",{
data:123
},(err,str)=>{
res.send(str)
})
})
添加html
模板引擎
app.engine('html',ejs.renderFile)
(或者app.engine('html',ejs.__express)
)app.set("view engine","html")
- 使用
ejs
ejs.renderFile("view/index.html",{
data:123
},(err,str)=>{
res.send(str)
})
})