一、Express的简单介绍
Express是什么?
express是一个基于node平台的web应用开发框架(后端)
Express框架特性?
- 简洁的接口定义
- http请求参数获取简单
- 模板引擎,方便渲染html页面
- 中间件机制有效的控制请求
二、Express的安装与构建
检查nodejs版本
node -v
是否安装Express
express --version
在本地新建一个文件夹(myapp),作为项目的存放路径,在该路径下使用cmd命令:
生成package.json文件
npm init
一直enter即可
在myapp目录下安装Express并将其保存到依赖列表中
npm i express –save
Express 应用程序生成器,可以通过 express-generator 快速的创建一个应用骨架,运行Express应用程序生成器
npx express-generator
在myapp目录下安装依赖包
npm install
启动应用
npm start
默认的端口是3000,可以在浏览器输入:localhost:3000 访问,出现下图内容,表示成功:
用vscode打开创建的项目(myapp):目录结构如下:
三、中间件的使用
中间件是什么?
- 中间件就是一堆方法,接收客户端发来的请求,对请求做出响应
- 中间件由两部分构成,中间件方法和请求处理函数,中间件方法由Express提供,负责拦截请求,请求处理函数自己提供,负责处理请求
- 可以对一个请求设置多个中间件,对同一个请求进行多次处理,按代码的顺序“由上到下”依次匹配,匹配成功,终止匹配,可以使用next函数将控制权交给下一个中间件,指定请求处理结束
总结:
中间件的使用:
在routes中新建一个js文件(demo.js)
//demo.js
//导入express模块
const express = require('express')
//创建服务器
const app = express.Router()
//定义中间件
app.get("/get_data",(req,res,next) => {
req.name = '张三'
next(); //向下执行
})
app.get("/get_data",(req,res) => {
res.send(req.name)
})
中间件执行过程:代码顺序,由上至下
app.use()中间件的使用:
- 当参数中只有一个处理函数时,代表匹配所有请求
- 指定了url,接收指定的请求
例:
//导入express模块
const express = require('express')
//创建服务器
const app = express.Router()
//处理全部请求
app.use((req,res,next)=>{
console.log('请求走了')
next()
})
//处理get_data请求
app.use('/get_data',(req,res,next) => {
console.log("get_data 请求走了")
next()
})
错误中间件定义:
在demo.js的底部定义一个中间件:
//错误处理中间件
//导入express模块
const express = require('express')
//创建服务器
const app = express.Router()
app.use((err,req,res,next) => {
//设置错误码(状态),并响应请求
res.status(500).send(err.message)
})
例:
//导入express模块
const express = require('express')
//创建服务器
const app = express.Router()
const fs = require('fs')
//处理index请求
//项目中没有demo.txt文件,会出现错误
app.get('/index',(req,res,next) => {
fs.readFile("./demo.text",'utf8',(err,result) => {
if(err != null){
//文件读取失败,向下传递错误对象
next(err)
}else{
res.send(result)
}
})
})
//错误处理中间件
app.use((err,req,res,next) => {
//设置错误码(状态)
res.status(500).send(err.message)
})
module.exports = app
如果想要这些请求和中间件生效,那么需要在app.js中定义如下代码:
//导入模块
var demoRouter = require('./routes/demo')
//第一个参数,请求名称,第二个参数,路由模板
app.use('/demo',demoRouter) // localhost:3000/demo/index
四、捕获错误
- nodejs中,异步的api的错误信息都是通过回调函数获取的
- try catch可以捕获异步函数和同步代码执行过程中发生的错误,但是不能捕获“回调函数的错误”,“promise对象的错误”
app.get("/demo",async (req,res,next) => {
try{
await fs.readFile('./demo.js')
} catch(ex) {
console.log(ex)
//传递错误信息
next(ex)
}
})
五、get请求以及参数的获取
同样的需要在routes中创建文件,并在app.js中导入并使用,之后才能使用(请求接口)
get参数获取:
req.query,返回一个普通对象
const express = require('express')
//创建服务器
const app = express.Router()
//请求处理
app.get("/index",(req,res) => {
res.send("欢迎来到德莱联盟")
})
//参数的获取:
//get参数的获取,localhost:3000/main?name=zs
app.get("/main",(req,res) => {
// 设置头部信息,如跨域
// res.header()
console.log(req.query)
// res.send("欢迎"+req.query.name+"来到德莱联盟")
res.send(req.query)
})
module.exports = app
六、post请求以及参数的获取
post参数获取:
- 需要配合 bodyParser 模块才能获取
在app.js中添加如下代码:
//导入模块
var express = require('express');
const bodyParser = require('body-parser');
// 拦截所有请求
// extended: false 方法内部使用 querystring 模块处理请求参数的格式
// extended: true 方法内部使用第三方模块 qs 来处理请求参数的格式
// 建议使用false
app.use(bodyParser.urlencoded({extended: false}));
定义请求:
//post请求参数的获取:借助body-parser
app.post("/home",(req,res) => {
console.log(req.body)
res.send(req.body)
})
发起请求时,请求参数的类型如下:
七、路由参数获取
//localhost:3000/route/123/tom
//路由参数:
app.get("/route/:id/:name",(req,res) => {
console.log(req.params)// {"id": "123","name": "tom"}
res.send(req.params)
})
五六七的完整代码:
记得在app.js中配置
const express = require('express')
//创建服务器
const app = express.Router()
//请求处理
app.get("/index",(req,res) => {
res.send("欢迎来到德莱联盟")
})
//参数的获取:
//get参数的获取
app.get("/main",(req,res) => {
// 设置头部信息,如跨域
// res.header()
console.log(req.query)
// res.send("欢迎"+req.query.name+"来到德莱联盟")
res.send(req.query)
})
//post请求参数的获取:借助body-parser
app.post("/home",(req,res) => {
console.log(req.body)
res.send(req.body)
})
//路由参数:
app.get("/route/:id/:name",(req,res) => {
console.log(req.params)// {"id": "123","name": "tom"}
res.send(req.params)
})
module.exports = app
八、连接mysql数据库
新建一个目录:包含如下文件
config.js中:
//db.js
const mysql = require('mysql')
const config = require('./config').db
//连接数据库
module.exports = mysql.createConnection(config)
在api.js中定义操作数据库的方法:
connection.query():
- 第一个参数:sql语句 — 字符串
- 第二个参数:参数值 — 数组
- 第三个参数:操作数据库之后执行的回调函数 (err:查询错误,data:查询结果) — function
注意:第二个参数可以没有,既当不需要任何参数时,我们可以不传;如果回调函数中的 err 为 null ,则操作数据库成功
增删改查:
//api.js
const connection = require('./db')
//查询
const getAccount = () => {
return new Promise((resolve, reject) => {
//第一个参数:sql语句
//第二个参数:回调函数(err:查询错误,data:查询结果)
connection.query("select * from account",(err,data) => {
resolve(data)
})
})
}
//添加
const insertAccount = (param) => {
return new Promise((resolve,reject) => {
connection.query("insert into account(username,phone,password) values(?,?,?)",param,(err,data) => {
//如果err为null则成功
resolve(data)
})
})
}
//改
const updateAccount = (param) => {
return new Promise((resolve,reject) => {
connection.query("update account set username = ? where phone = ?",param,(err,data) => {
//如果err为null则成功
resolve(data)
})
})
}
//删除
const deleteAccount = (param) => {
return new Promise((resolve,reject) => {
connection.query("delete from account where id = ?",param,(err,data) => {
resolve(data)
})
})
}
//导出方法,在需要使用到的模块中导入
module.exports = {
getAccount,
insertAccount,
updateAccount,
deleteAccount
}
在接口中调用操作数据库的方法:
//data.js
// 记得在app.js中配置
const express = require('express')
//创建服务器
const app = express.Router()
const {getAccount,insertAccount,updateAccount,deleteAccount} = require('../dataBase/api')
app.get("/get_account",(req,res,next) => {
getAccount()
.then(response => {
res.send(response)
})
})
app.post("/insert_account",(req,res,next) => {
let param = req.body
let {username,phone,password} = param
insertAccount([username,phone,password])
.then(response => {
res.send(response)
})
})
app.post("/update_account",(req,res,next) => {
let param = req.body
let {username,phone} = param
updateAccount([username,phone])
.then(response => {
res.send(response)
})
})
app.get("/delete_account",(req,res,next) => {
let id = req.query.id
deleteAccount([id])
.then(response => {
res.send(response)
})
})
module.exports = app
九、暴露静态文件
在app.js中配置:
//暴露静态文件:可访问 , 如:http://localhost:3000/images/logo.png
//把public路径下的所有静态文件暴露出来,既可以访问
app.use(express.static(path.join(__dirname, 'public')));
十、app.js源码
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const bodyParser = require('body-parser')
//导入路由,接口
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var loginRouter = require('./routes/login')
var demoRouter = require('./routes/demo')
var accountRouter = require('./routes/data')
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
//暴露静态文件:可访问 , 如:http://localhost:3000/images/logo.png
app.use(express.static(path.join(__dirname, 'public')));
//配置新增的路由(接口),如此便可以在postman中发起请求
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/',loginRouter)
app.use('/demo',demoRouter)
app.use('/',accountRouter)
// 拦截所有请求
// extended: false 方法内部使用 querystring 模块处理请求参数的格式
// extended: true 方法内部使用第三方模块 qs 来处理请求参数的格式
app.use(bodyParser.urlencoded({extended: false}));
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
//监听端口
app.listen(5000) //请求时的端口:localhost:5000
console.log("服务启动成功!")
module.exports = app;
十一、热加载
安装模块:nodemon
- -g : 全局
- -s:本地
npm install -g nodemon
在package.json中配置:
如上两步完成之后,即可热更新,改变代码,保存,无须重启