express
express 主要包含三个核心概念:路由、中间件、模板引擎
- 中间件:可以毫不夸张的说,在 express 应用中,一切皆中间件。各种应用逻辑,如 cookie 解析、会话处理、日志记录、权限校验等,都是通过中间件来完成的。
- 路由:地球人都知道,负责寻址的。比如用户发送了个 http 请求,该定位到哪个资源,就是路由说了算。
- 模板引擎:负责视图动态渲染。下面会介绍相关配置,以及如何开发自己的模板引擎。
项目搭建
- 安装 express 模块
bash
npm install express --save
npm install nodemon -D
npm install express --save
npm install nodemon -D
- 创建 app.js 文件
js
const express = require("express");
const app = express();
app.listen(3000, () => {
console.log("服务器启动成功,端口号为3000");
});
const express = require("express");
const app = express();
app.listen(3000, () => {
console.log("服务器启动成功,端口号为3000");
});
- 启动服务器
bash
# script添加nodemon命令
"scripts": {
"dev": "nodemon app.js"
}
# 启动服务器
npm run dev
# script添加nodemon命令
"scripts": {
"dev": "nodemon app.js"
}
# 启动服务器
npm run dev
API 总结
路由
js
// 路由的基本使用
app.get("/api/users", (req, res) => {
res.json({
msg: "hello world",
});
});
// 路由的中间件
app.get("/api/users", (req, res, next) => {
console.log("请求进来了");
next();
});
// 路由的基本使用
app.get("/api/users", (req, res) => {
res.json({
msg: "hello world",
});
});
// 路由的中间件
app.get("/api/users", (req, res, next) => {
console.log("请求进来了");
next();
});
常用中间件
- body-parser
- compression
- serve-static
- session
- cookie-parser
- morgan
静态资源
js
// 静态资源的使用
app.use(express.static("public"));
// 静态资源的配置
app.use(
express.static("public", {
maxAge: 30 * 24 * 60 * 60, // 缓存时间
setHeaders(res) {
res.setHeader("Access-Control-Allow-Origin", "*");
},
})
);
// 静态资源的使用
app.use(express.static("public"));
// 静态资源的配置
app.use(
express.static("public", {
maxAge: 30 * 24 * 60 * 60, // 缓存时间
setHeaders(res) {
res.setHeader("Access-Control-Allow-Origin", "*");
},
})
);
错误处理
js
// 错误处理的使用
app.use((err, req, res, next) => {
res.status(500).json({
msg: "服务器错误",
err,
});
});
// 错误处理的使用
app.use((err, req, res, next) => {
res.status(500).json({
msg: "服务器错误",
err,
});
});
跨域
js
// 跨域的使用
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS"
if (req.method === "OPTIONS") {
res.sendStatus(200);
} else {
next();
}
next();
)
next();
});
// 跨域的使用
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS"
if (req.method === "OPTIONS") {
res.sendStatus(200);
} else {
next();
}
next();
)
next();
});
日志记录
js
// 日志记录的使用
const morgan = require("morgan");
app.use(morgan("dev"));
// 日志记录的使用
const morgan = require("morgan");
app.use(morgan("dev"));
数据库
js
// 数据库的使用
const mongoose = require("mongoose");
mongoose.connect(, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on("error", console.error.bind(console, "连接数据库失败"));
db.once("open", () => {
console.log("连接数据库成功");
});
// 数据库的使用
const mongoose = require("mongoose");
mongoose.connect(, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on("error", console.error.bind(console, "连接数据库失败"));
db.once("open", () => {
console.log("连接数据库成功");
});
模板引擎
js
// 模板引擎的使用
const express = require("express");
const path = require("path");
const ejs = require("ejs");
const app = express();
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
app.get("/", (req, res) => {
res.render("index", {
title: "首页",
});
});
app.listen(3000, () => {
console.log("服务器启动成功,端口号为3000");
});
// views:模版文件放在哪里,默认是在项目根目录下。举个例子:app.set('views', './views')
// view engine:使用什么模版引擎,举例:app.set('view engine', 'jade')
// 模板引擎的使用
const express = require("express");
const path = require("path");
const ejs = require("ejs");
const app = express();
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
app.get("/", (req, res) => {
res.render("index", {
title: "首页",
});
});
app.listen(3000, () => {
console.log("服务器启动成功,端口号为3000");
});
// views:模版文件放在哪里,默认是在项目根目录下。举个例子:app.set('views', './views')
// view engine:使用什么模版引擎,举例:app.set('view engine', 'jade')
开发模板引擎
通过 app.engine(engineExt, engineFunc)来注册模板引擎。其中
engineExt:模板文件后缀名。比如 jade。
engineFunc:模板引擎核心逻辑的定义,一个带三个参数的函数(如下)
js
// filepath: 模板文件的路径
// options:渲染模板所用的参数
// callback:渲染完成回调
app.engine(engineExt, function (filepath, options, callback) {
// 参数一:渲染过程的错误,如成功,则为null
// 参数二:渲染出来的字符串
return callback(null, "Hello World");
});
// filepath: 模板文件的路径
// options:渲染模板所用的参数
// callback:渲染完成回调
app.engine(engineExt, function (filepath, options, callback) {
// 参数一:渲染过程的错误,如成功,则为null
// 参数二:渲染出来的字符串
return callback(null, "Hello World");
});
request 对象
Request 对象 - request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性。常见属性有:
txt
req.app:当callback为外部文件时,用req.app访问express的实例
req.baseUrl:获取路由当前安装的URL路径
req.body / req.cookies:获得「请求主体」/ Cookies
req.fresh / req.stale:判断请求是否还「新鲜」
req.hostname / req.ip:获取主机名和IP地址
req.originalUrl:获取原始请求URL
req.params:获取路由的parameters
req.path:获取请求路径
req.protocol:获取协议类型
req.query:获取URL的查询参数串
req.route:获取当前匹配的路由
req.subdomains:获取子域名
req.accepts():检查可接受的请求的文档类型
req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一个可接受字符编码
req.get():获取指定的HTTP请求头
req.is():判断请求头Content-Type的MIME类型
req.app:当callback为外部文件时,用req.app访问express的实例
req.baseUrl:获取路由当前安装的URL路径
req.body / req.cookies:获得「请求主体」/ Cookies
req.fresh / req.stale:判断请求是否还「新鲜」
req.hostname / req.ip:获取主机名和IP地址
req.originalUrl:获取原始请求URL
req.params:获取路由的parameters
req.path:获取请求路径
req.protocol:获取协议类型
req.query:获取URL的查询参数串
req.route:获取当前匹配的路由
req.subdomains:获取子域名
req.accepts():检查可接受的请求的文档类型
req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages:返回指定字符集的第一个可接受字符编码
req.get():获取指定的HTTP请求头
req.is():判断请求头Content-Type的MIME类型
response 对象
Response 对象 - response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据。常见属性有:
txt
res.app:同req.app一样
res.append():追加指定HTTP头
res.set()在res.append()后将重置之前设置的头
res.cookie(name,value [,option]):设置Cookie
opition: domain / expires / httpOnly / maxAge / path / secure / signed
res.clearCookie():清除Cookie
res.download():传送指定路径的文件
res.get():返回指定的HTTP头
res.json():传送JSON响应
res.jsonp():传送JSONP响应
res.location():只设置响应的Location HTTP头,不设置状态码或者close response
res.redirect():设置响应的Location HTTP头,并且设置状态码302
res.render(view,[locals],callback):渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
res.send():传送HTTP响应
res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
res.set():设置HTTP头,传入object可以一次设置多个头
res.status():设置HTTP状态码
res.type():设置Content-Type的MIME类型
res.app:同req.app一样
res.append():追加指定HTTP头
res.set()在res.append()后将重置之前设置的头
res.cookie(name,value [,option]):设置Cookie
opition: domain / expires / httpOnly / maxAge / path / secure / signed
res.clearCookie():清除Cookie
res.download():传送指定路径的文件
res.get():返回指定的HTTP头
res.json():传送JSON响应
res.jsonp():传送JSONP响应
res.location():只设置响应的Location HTTP头,不设置状态码或者close response
res.redirect():设置响应的Location HTTP头,并且设置状态码302
res.render(view,[locals],callback):渲染一个view,同时向callback传递渲染后的字符串,如果在渲染过程中有错误发生next(err)将会被自动调用。callback将会被传入一个可能发生的错误以及渲染后的页面,这样就不会自动输出了。
res.send():传送HTTP响应
res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
res.set():设置HTTP头,传入object可以一次设置多个头
res.status():设置HTTP状态码
res.type():设置Content-Type的MIME类型
总结
进程管理 会话管理 日志管理 性能优化 调试 错误处理 负载均衡 数据库支持 HTTPS 支持 业务实践