Appearance
Express 框架实战
Express 是一个基于 Node.js 平台的 Web 应用框架,它提供了简洁而灵活的 API,用于构建 Web 应用和 API。本文将介绍 Express 框架的核心概念和使用方法。
1. 安装 Express
bash
# 初始化项目
npm init -y
# 安装 Express
npm install express2. 基本使用
创建服务器
javascript
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});路由
javascript
// 基本路由
app.get('/', (req, res) => {
res.send('Home page');
});
app.post('/submit', (req, res) => {
res.send('Form submitted');
});
app.put('/update', (req, res) => {
res.send('Resource updated');
});
app.delete('/delete', (req, res) => {
res.send('Resource deleted');
});
// 路由参数
app.get('/users/:id', (req, res) => {
const id = req.params.id;
res.send(`User ID: ${id}`);
});
// 查询参数
app.get('/search', (req, res) => {
const query = req.query;
res.send(`Search query: ${JSON.stringify(query)}`);
});中间件
javascript
// 内置中间件
app.use(express.json()); // 解析 JSON 请求体
app.use(express.urlencoded({ extended: true })); // 解析 URL 编码的请求体
app.use(express.static('public')); // 提供静态文件
// 自定义中间件
app.use((req, res, next) => {
console.log('Request received');
next(); // 调用 next() 继续处理请求
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});3. 路由系统
基本路由
javascript
app.get('/', (req, res) => {
res.send('Home page');
});
app.post('/submit', (req, res) => {
res.send('Form submitted');
});路由参数
javascript
app.get('/users/:id', (req, res) => {
const id = req.params.id;
res.send(`User ID: ${id}`);
});
app.get('/users/:id/posts/:postId', (req, res) => {
const { id, postId } = req.params;
res.send(`User ID: ${id}, Post ID: ${postId}`);
});路由处理函数
javascript
// 单个处理函数
app.get('/users', (req, res) => {
res.send('Users list');
});
// 多个处理函数
app.get('/users', (req, res, next) => {
console.log('First handler');
next();
}, (req, res) => {
res.send('Users list');
});
// 处理函数数组
const middleware1 = (req, res, next) => {
console.log('Middleware 1');
next();
};
const middleware2 = (req, res, next) => {
console.log('Middleware 2');
next();
};
app.get('/users', [middleware1, middleware2], (req, res) => {
res.send('Users list');
});路由模块
javascript
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.send('Users list');
});
router.get('/:id', (req, res) => {
res.send(`User ID: ${req.params.id}`);
});
module.exports = router;
// app.js
const express = require('express');
const app = express();
const usersRouter = require('./routes/users');
app.use('/users', usersRouter);
app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});4. 中间件
应用级中间件
javascript
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
app.use('/users', (req, res, next) => {
console.log('Request to /users');
next();
});路由级中间件
javascript
const express = require('express');
const router = express.Router();
router.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
router.get('/', (req, res) => {
res.send('Users list');
});
app.use('/users', router);错误处理中间件
javascript
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});内置中间件
javascript
app.use(express.json()); // 解析 JSON 请求体
app.use(express.urlencoded({ extended: true })); // 解析 URL 编码的请求体
app.use(express.static('public')); // 提供静态文件第三方中间件
bash
# 安装中间件
npm install morgan cors helmetjavascript
const express = require('express');
const morgan = require('morgan');
const cors = require('cors');
const helmet = require('helmet');
const app = express();
app.use(morgan('dev')); // 日志中间件
app.use(cors()); // 跨域中间件
app.use(helmet()); // 安全中间件
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});5. 请求与响应
请求对象 (req)
javascript
app.get('/users/:id', (req, res) => {
// 路由参数
const id = req.params.id;
// 查询参数
const query = req.query;
// 请求头
const headers = req.headers;
// 请求体
const body = req.body;
// 请求方法
const method = req.method;
// 请求路径
const path = req.path;
// 完整 URL
const url = req.originalUrl;
res.send(`User ID: ${id}`);
});响应对象 (res)
javascript
app.get('/users', (req, res) => {
// 发送文本
res.send('Users list');
// 发送 JSON
res.json({ users: [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }] });
// 发送文件
res.sendFile(__dirname + '/index.html');
// 重定向
res.redirect('/');
// 设置状态码
res.status(200).send('OK');
// 设置头部
res.set('Content-Type', 'application/json');
// 发送状态码和消息
res.status(404).send('Not found');
});6. 模板引擎
安装模板引擎
bash
npm install ejs配置模板引擎
javascript
const express = require('express');
const app = express();
// 设置模板引擎
app.set('view engine', 'ejs');
// 设置模板目录
app.set('views', './views');
app.get('/', (req, res) => {
res.render('index', { title: 'Home', message: 'Hello World!' });
});
app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});创建模板文件
ejs
<!-- views/index.ejs -->
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h1><%= message %></h1>
<ul>
<% for (let user of users) { %>
<li><%= user.name %></li>
<% } %>
</ul>
</body>
</html>7. 静态文件
javascript
const express = require('express');
const app = express();
// 提供静态文件
app.use(express.static('public'));
// 为静态文件设置虚拟路径
app.use('/static', express.static('public'));
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});8. 错误处理
404 错误
javascript
app.use((req, res, next) => {
res.status(404).send('Not found');
});500 错误
javascript
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});自定义错误处理
javascript
class CustomError extends Error {
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
}
app.get('/error', (req, res, next) => {
next(new CustomError('Custom error', 400));
});
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
res.status(statusCode).send(err.message);
});9. 数据库集成
MongoDB
bash
npm install mongoosejavascript
const express = require('express');
const mongoose = require('mongoose');
const app = express();
// 连接数据库
mongoose.connect('mongodb://localhost:27017/myapp', {
useNewUrlParser: true,
useUnifiedTopology: true
});
// 定义模型
const User = mongoose.model('User', {
name: String,
email: String
});
app.get('/users', async (req, res) => {
try {
const users = await User.find();
res.json(users);
} catch (err) {
res.status(500).send(err.message);
}
});
app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});MySQL
bash
npm install mysql2javascript
const express = require('express');
const mysql = require('mysql2');
const app = express();
// 创建连接
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp'
});
// 连接数据库
connection.connect();
app.get('/users', (req, res) => {
connection.query('SELECT * FROM users', (err, results) => {
if (err) {
res.status(500).send(err.message);
return;
}
res.json(results);
});
});
app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});10. 认证与授权
JWT 认证
bash
npm install jsonwebtokenjavascript
const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
app.use(express.json());
// 生成 token
function generateToken(user) {
return jwt.sign({ id: user.id, name: user.name }, 'secret_key', { expiresIn: '1h' });
}
// 验证 token
function verifyToken(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).send('Access denied');
}
try {
const decoded = jwt.verify(token, 'secret_key');
req.user = decoded;
next();
} catch (err) {
res.status(401).send('Invalid token');
}
}
// 登录路由
app.post('/login', (req, res) => {
const { username, password } = req.body;
// 验证用户
const user = { id: 1, name: 'John' };
const token = generateToken(user);
res.json({ token });
});
// 受保护的路由
app.get('/protected', verifyToken, (req, res) => {
res.send(`Welcome, ${req.user.name}!`);
});
app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});11. 测试
单元测试
bash
npm install --save-dev mocha chai supertestjavascript
// test.js
const request = require('supertest');
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
describe('GET /', () => {
it('should return 200 OK', (done) => {
request(app)
.get('/')
.expect(200)
.expect('Hello World!', done);
});
});bash
# 运行测试
npx mocha test.js集成测试
javascript
// test-integration.js
const request = require('supertest');
const app = require('./app');
describe('GET /users', () => {
it('should return users list', (done) => {
request(app)
.get('/users')
.expect(200)
.expect('Content-Type', /json/)
.end((err, res) => {
if (err) return done(err);
done();
});
});
});12. 部署
本地部署
bash
# 安装依赖
npm install
# 运行应用
npm start云部署
Heroku
- 安装 Heroku CLI
- 登录 Heroku:
heroku login - 创建 Heroku 应用:
heroku create - 部署代码:
git push heroku master - 打开应用:
heroku open
AWS
- 创建 EC2 实例
- 安装 Node.js
- 上传代码
- 安装依赖
- 运行应用
Docker
dockerfile
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]13. 最佳实践
- 模块化:将代码拆分为多个模块
- 中间件:合理使用中间件
- 路由:使用路由模块组织路由
- 错误处理:统一处理错误
- 数据库:使用 ORM 或 ODM
- 认证:使用 JWT 或其他认证方式
- 测试:编写单元测试和集成测试
- 日志:使用日志中间件
- 安全:使用安全中间件
- 性能:优化性能
14. 性能优化
- 使用 gzip 压缩:
npm install compression - 使用缓存:
npm install express-cache-controller - 优化数据库查询:使用索引
- 使用连接池:减少数据库连接开销
- 使用负载均衡:分发请求
- 使用 CDN:加速静态资源
- 使用集群:利用多核 CPU
15. 总结
Express 是一个轻量级的 Web 应用框架,它提供了简洁而灵活的 API,用于构建 Web 应用和 API。通过学习 Express,我们可以快速构建高性能的后端应用程序。
Express 的核心特性包括:
- 简洁的 API
- 强大的路由系统
- 灵活的中间件
- 支持模板引擎
- 易于集成数据库
Express 已经成为 Node.js 生态系统中最流行的 Web 框架之一,许多大型公司都在使用 Express 构建他们的应用程序。掌握 Express 是现代后端开发者的必备技能。