[TOC]html
Express 是一个基于 Node.js 封装的上层服务框架,它提供了更简洁的 API 更实用的新功能。它经过中间件和路由让程序的组织管理变的更加容易;它提供了丰富的 HTTP 工具;它让动态视图的渲染变的更加容易;它还定义了一组可拓展标准。前端
npm install express -S
复制代码
let express = require('express')
let app = express()
app.get('/',(req,res) => res.end('hello world'))
app.listen(3000,() => console.log('Server is running...'))
复制代码
运行示例node
在web网站后端开发的过程当中,咱们每每须要把一些静态文件夹暴露出去,用户能够根据url地址去访问到其中的内容,这些静态文件每每也称之为公共资源,利用express框架能够方便地托管静态文件。git
public
静态资源的文件夹方法一(推荐)github
app.use('/public/',express.static('./public'))
复制代码
为 app.use()
方法传递两个参数,第一个参数为访问的URL前缀,第二个为要托管的目录即要暴露的文件目录web
let express = require('express');
let app = express()
//设置静态资源
// 方法一
app.use('/public/',express.static('./public'))
app.listen(3000,() => console.log('Server is running...'))
复制代码
示例shell
方法二数据库
app.use(express.static('./public'))
复制代码
方法二在方法一的基础上,省略第一个参数,直接指定暴露的静态资源文件夹express
let express = require('express');
let app = express()
//设置静态资源
// 方法二
app.use(express.static('./public'))
app.listen(3000,() => console.log('Server is running...'))
复制代码
示例npm
方法三
app.use('/static/',express.static('./public'))
复制代码
同方法一传参相似,只不过将第一个参数设置为你想访问的URL前缀,即指定前缀的别名
let express = require('express');
let app = express()
//设置静态资源
// 方法三
app.use('/static/',express.static('./public'))
app.listen(3000,() => console.log('Server is running...'))
复制代码
示例
在post请求中,请求的参数包含在 请求的body中,咱们要获取post请求的数据,便是要获取request.body里面的数据
可是,在默认状况下,咱们使用 req.body获取到的内容为undefine,这里须要使用一个中间件
body-parser
来解析传入的请求主体,使req.body能够被访问
1. 安装 body-parser
npm install body-parser express -S
复制代码
2. 建立server.js
// server.js
//引入模块
const express = require('express')
const bodyParse = require('body-parser')
// 建立服务器对象
const app = express()
/** * 经过 body-parser中间件解析req.body * 根据不一样的 Content-Type分别有以下两种不一样的配置 * post请求体中的Content—Type为:application/x-www-form-urlencoded,使用配置1 * post请求体中的Content-Type为:application/json,使用配置2 */
app.use(bodyParse.urlencoded({extended:false}))
app.use(bodyParse.json())
//配置访问路由,返回post请求中的name参数
app.post('/post',(req,res)=>{
const result = req.body
console.log(result)
res.end(result.name)
})
app.listen(3000,()=>console.log('Server is running on localhost:3000'))
复制代码
3. 开启服务器,可经过postman访问URL,自行配置body里面的参数信息,以及指定Content-Type
4. 最后点击左下角的body,便可查看咱们服务器中的返回信息
前面咱们学习了如何在Nodejs中使用
art-template
,在express一样可使用,接下来咱们就来看看,如何在express中使用art-template
1. 在express中使用art-template,首先要安装以下两个模块
npm install art-template express-art-template -S
复制代码
2. 添加模版界面
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>{{ title }}</title>
</head>
<body>
<h1>{{ title }}</h1>
<p>My name is {{ name }}</p>
<p>I come from {{ from }}</p>
<p>I like {{each hobbies}} {{ $value }} {{ /each }}</p>
</body>
</html>
复制代码
3. 添加server.js文件
const express = require('express')
const app = express()
// 配置 express-art-template模版引擎,
//配置以后,服务器请求事件的回调函数的响应对象上会增长一个 render方法,用于渲染模版字符串返回渲染以后的结果
// 第一个参数 html 为模版文件拓展名,表示模版文件必须是HTML文件
app.engine('html',require('express-art-template'))
app.get('/',(req,res)=>{
res.render('./index.html',{
title: '我的介绍',
name: 'Kobe',
form: 'America',
bobbies: ['basketball','swimming']
})
})
app.listen(8000,()=>console.log('Server is running on localhost:3000'))
复制代码
4. 启动服务器,调用URL,咱们发现,报以下错误
Error: Failed to lookup view "./index.html" in views directory "C:\Users\admin\Desktop\work\ForStudy\8.Node.js\DemoFolder\express-art-template-demo\views"
复制代码
错误分析
app.set('views', '替换的文件路径') // 第一个参数必须为:views
复制代码
路由分为前端路由和后端路由,这里咱们主要谈论的过后端路由,即URL地址
后端路由
对于普通网站,全部的连接都是URL地址,URL地址即对应服务器上面的资源
前端路由
前端路由主要经过hash(#)来实现,经过hash值的改变来切换界面,同同时,hash值的改变并不会带来http请求的从新响应,使得加载页面的性能更好
经过前面的学习咱们知道,能够经过express的get和post方法,对不一样的URL地址作出响应,最终将结果返回給客户端
**问题描述:**一旦咱们的项目界面多了起来,须要处理的请求路径就会比较多,若是所有写在一个文件,就会使得文件难以维护,因而咱们能够提取路由文件,专门用来配置路由,最后把路由对象导出挂载到服务器上便可
实现:
使用 npm init -y 初始化,而且安装 express 模块
npm init -y
npm install express -S
复制代码
建立server.js文件
// server.js
const express = require('express')
const server = express()
server.listen(3000,()=>{
console.log('Server is running on localhost:3000')
})
复制代码
路由文件
// router.js
// 引入express而且获取路由对象
const app = require('express')
const router = app.Router()
// 配置路由对象
router.get('/',(req,res)=>{
res.send('主页')
})
router.get('/login',(req,res)=>{
res.send('登录')
})
router.get('/register',(req,res)=>{
res.send('注册')
})
// 导出路由对象
module.exports = router
复制代码
在server.js文件中挂载路由对象
// server.js
const express = require('express')
const server = express()
//挂载路由对象
const router = require('./router')
server.use(router)
server.listen(3000,()=>{
console.log('Server is running on localhost:3000')
})
复制代码
演示
在这里,咱们一块儿经过express框架,来实现一个拥有增删改查功能的简易版学生管理系统
一共有以下几个文件
// db.json
{
"students": [
{
"id": 1,
"name": "YaoMing",
"sex": "M",
"hobbies": [
"Basketball",
"ComputerGame",
"eating"
]
},
{
"id": 2,
"name": "YiJianLian",
"sex": "M",
"hobbies": [
"Basketball",
"earnMoney",
"coding"
]
},
{
"id": 3,
"name": "Kobe",
"sex": "M",
"hobbies": [
"basketball",
"swimming",
"sleep"
]
}
]
}
复制代码
// StudentApi.js
/** * 提供一个简单的CRUD接口 * 可经过以下增删改查的接口,实现一个简易的学生管理系统 * 同时,可做为nodejs增删改查的模板 */
const fs = require('fs')
// 提取数据源地址,方便后续维护
const dataBase = './db.json'
/** * 新增学生信息 * Param:要新增的学生对象 * 调用:add(student) * */
exports.add = (student)=>{
fs.readFile(dataBase,(err,data)=>{
// 错误处理
if(err){
return console.log('readFiel db.json error...')
}
// 获取学生数组
var students = JSON.parse(data).students
// 为新增的学生对象设置id值
if(students.length === 0){
student.id = 1
}
student.id = students[students.length-1].id + 1
// 将新增的学生对象添加到学生数组
students.push(student)
let dataStr = JSON.stringify({studnets:studnets})
// 将新增完成的学生数组写入文件
fs.writeFile(dataBase,dataStr,(err)=>{
if(err){
return console.log('write to db.json failed...')
}
return console.log('添加成功')
})
})
}
/** * 更新学生信息 * Param: 要修改的学生对象 */
exports.update = (student)=>{
fs.readFile(dataBase,(err,data)=>{
// 错误处理
if(err){
return console.log('readFiel db.json error...')
}
// 获取学生数组
var students = JSON.parse(data).students
// 更新标识,用来判断是否有数据被更新
var isUpdate = false
// 遍历学生数组,找到要更新的那一个学生信息
for(var i = 0;i<students.length;i++){
// 当学生信息都没有发生变化的时候,不作更新
if(students[i].id === student.id){
if(students[i].name == student.name && students[i].sex == student.sex && students[i].hobbies.toString() == student.hobbies.toString()){
console.log('未作任何更新,没法提交学生信息')
}else{
students[i].name = student.name
students[i].sex = student.sex
students[i].hobbies = student.hobbies
isUpdate = true
}
}
}
// 根据 isUpdata标识,判断是否有数据更新
if(isUpdate){
let dataStr = JSON.stringify({students:students})
fs.writeFile(dataBase,dataStr,(err)=>{
if(err){
return console.log('write to db.json failed...')
}
return console.log('跟新成功!')
})
}else{
console.log('跟新失败')
}
})
}
/** * 查找全部学生信息,经过callback回调函数将students数组返回 */
exports.searchAll = (callback)=>{
fs.readFile(dataBase,(err,data)=>{
if(err){
return console.log('read file db.json err...')
}
callback(JSON.parse(data).students)
})
}
/** * 经过id删除学生信息 * Param: id:要删除的学生id */
exports.delete = (id)=>{
fs.readFile(dataBase,(err,data)=>{
if(err){
return console.log('readFiel db.json error...')
}
var students = JSON.parse(data).students
var isDelete = false
// 遍历学生数组,删除指定id的学生信息
for(var i = 0;i<students.length;i++){
if(students[i].id === id){
students.splice(i,1)
isDelete = true
}
}
// 经过 isDelete标识判断是否删除成功
if(isDelete){
let dataStr = JSON.stringify({students:students})
fs.writeFile(dataBase,dataStr,(err)=>{
if(err){
return console.log('write to db.json failed...')
}
return console.log('删除成功!')
})
}else{
console.log('没有找到要删除的数据')
}
})
}
复制代码
// test.js
const api = require('./StudentApi')
var student = {
"id": 3,
"name": "Kobe",
"sex": "M",
"hobbies": [
"basketball",
"swimming",
"sleep"
]
}
// api.add(student,null)
// api.searchAll((data)=>{
// console.log(data)
// })
// api.delete(4)
// api.update(student)
复制代码
**middleware:**即中间件,在express中是很重要的一个概念
**官网的介绍:**Express 是一个路由和中间件 Web 框架,其自身只具备最低程度的功能:Express 应用程序基本上是一系列中间件函数调用。
**做用:**简单来讲,就是当咱们在浏览器中发送URL请求开始,到咱们在浏览器接收到数据和看到界面渲染为止,这中间的全部过程都是经过 express中间件来完成的
其实在咱们以前的学习过程当中,咱们已经使用过express中间件了,如今咱们来一块儿回顾一下
这两种场景都用到了express中间件,咱们发现,他们都有一个共同的特征,即都是经过 app.use方法来调用的
const express = reuire('express')
const app = express()
// 开放静态资源
app.use('/public/',express.static('./public'))
// 获取post请求参数配置
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
复制代码
分类:
express应用程序能够执行以下几种类型的中间件
基础:(重要)
中间件简单来讲就是一系列函数,就是在请求返回以前,咱们对数据进行的一系列处理逻辑的执行函数
每个函数都包含三个参数:req,res,next
req:包含请求对象相关信息
res:包含相应对象相关信息
next():控制中间件传播流程
// 这里拿一个中间件作示范
// 以下,use方法里面的多个函数即为中间件的堆栈,能够经过next方法,让他们按照顺序执行,若是前面的方法没有调用next()方法,则后面的函数就不会执行,请求将会停留在该中间件中,不会继续执行
app.use('./demo',function(req,res,next){
console.log('第一个中间件函数')
next()
},function(req,res,next){
console.log('第二个中间件函数')
// next()
},function(req,res,next){
console.log('第三个中间件函数,若是上面的方法没有调用next(),则这里不会执行')
next()
})
// demo路径的第二个路由,可否执行要依赖于前面的中间件是否调用了next()方法
app.use('./demo',function(req,res,next){
console.log('第二个路由的中间件1')
next()
},function(req,res,next){
console.log('第二个路由的中间件2')
// next()
},function(req,res,next){
res.send('hello world')
})
复制代码
使用
app.use()
或者app.METHOD()
函数将 中间件绑定到应用程序对象的实例,其中METHOD是中间函数处理的请求的小写HTTP方法
**Demo1:**未指定路径的中间件,全部的请求都会先执行该方法
const app = express()
app.use(function(req,res,next){
console.log(Date.now())
next()
})
复制代码
**Demo2:**指定路径上的中间件,只有符合指定路径的请求才会调用该中间件
const app = express()
// 只有指定路径下的请求才会调用该中间件
app.use('/a',function(req,res,next){
console.log(Date.now())
next()
})
复制代码
**Demo3:**能够经过添加多个function,实现中间件堆栈的调用效果
const app = express()
app.use('/user', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next();
}, function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
app.get('/user',(req,res)=>{
console.log('user目录')
res.send('user目录')
})
复制代码
结果:
Request URL: /user
Request Type: GET
user目录
复制代码
**Demo4:**为同一个路径定义多个路由,若是前面路由使请求结束,则后面路由不会调用,不然会按顺序调用
// Demo4:为同一个路径定义多个路由,若是前面路由使请求结束,则后面路由不会调用,不然会按顺序调用
app.get('/more',(req,res,next)=>{
console.log('more第一个路由的第一次调用')
next()
},function(req,res,next){
// console.log('随便打印点什么')
// next()
res.send('这里使请求结束,后续的路由将不会调用')
})
app.get('/more',(req,res,next)=>{
console.log('more第二个路由的第一次调用')
next()
},function(req,res,next){
res.send('more第二个路由的第二次调用')
})
复制代码
Demo5:
// Demo5:经过 next('route')方法跳出堆栈,将控制权交给下一个路由
app.get('/demo5',(req,res,next)=>{
console.log('demo5第一个路由的第一次调用')
next()
},function(req,res,next){
console.log('welcome to demo5')
//next()
next('route')
},function(req,res,next){
console.log("若是前面调用了next('route')方法,这里将不会调用")
next()
})
app.get('/demo5',(req,res,next)=>{
console.log('demo5第二个路由的第一次调用')
next()
},function(req,res,next){
res.send('demo5第二个路由的第二次调用')
})
复制代码
结果:
demo5第一个路由的第一次调用
welcome to demo5
demo5第二个路由的第一次调用
//浏览器展现
demo5第二个路由的第二次调用
复制代码
路由中间件相似于应用层中间件,只不过在应用层中间件的基础上,将路由模块抽离出来,实现方法同上
这里只作简单Demo示例
Demo
const express = require('require')
const app = express()
const router = app.Router()
router.use('/user', function(req, res, next) {
console.log('Request URL:', req.originalUrl);
next();
}, function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
router.use('/user', function(req, res, next) {
console.log(Date.now());
next();
}, function (req, res, next) {
res.end('hello world')
});
复制代码
错误处理中间件用法同上,只有一点不一样
错误处理中间件始终采用四个自变量。必须提供四个自变量,以将函数标识为错误处理中间件函数。即便无需使用
next
对象,也必须指定该对象以保持特征符的有效性。不然,next
对象将被解释为常规中间件,从而没法处理错误。
Demo:
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
复制代码
Express 中惟一内置的中间件函数是
express.static
**语法:**express.static(root, [options])
参数:
root
自变量指定从其中提供静态资源的根目录。- options包含一系列的参数配置
**做用:**配置应用程序的静态文件目录,可经过静态路径直接在浏览器获取静态文件目中的文件
**Demo:**对于应用程序,能够配置多个静态目录
app.use(express.static('public'));
app.use(express.static('uploads'));
app.use(express.static('files'));
复制代码
使用:
- 第三方中间件属于nodejs模块,须要先安装
- 经过在应用层或路由器层的应用程序中将其加装入
**Demo:**第三方中间件 cookie-parser的使用
npm i cookie-parser -S
复制代码
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
// load the cookie-parsing middleware
app.use(cookieParser());
复制代码