您现在的位置是:网站首页 > Express框架核心文章详情
Express框架核心
陈川
【
Node.js
】
22185人已围观
6055字
Express框架是Node.js中最流行的Web应用框架之一,以其轻量级、灵活性和强大的中间件机制著称。它简化了HTTP请求处理、路由管理和模板渲染等常见任务,成为构建高效后端服务的首选工具。
Express框架的核心概念
Express的核心设计围绕中间件(Middleware)和路由(Router)展开。中间件是处理HTTP请求的函数,可以访问请求对象(req)、响应对象(res)和下一个中间件函数(next)。路由则定义了URL路径与处理逻辑之间的映射关系。
const express = require('express');
const app = express();
// 最简单的中间件示例
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
// 基本路由
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000);
中间件工作机制
Express中间件按照声明顺序执行,形成所谓的"中间件栈"。每个中间件可以决定是否终止请求-响应循环,或者将控制权交给下一个中间件。
常见中间件类型包括:
- 应用级中间件:通过app.use()或app.METHOD()绑定
- 路由级中间件:通过router.use()绑定
- 错误处理中间件:接收四个参数(err, req, res, next)
- 内置中间件:如express.static
- 第三方中间件:如body-parser
// 多个中间件串联示例
app.use('/user/:id', (req, res, next) => {
console.log('Request URL:', req.originalUrl);
next();
}, (req, res, next) => {
console.log('Request Type:', req.method);
next();
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
路由系统详解
Express的路由系统支持动态路由参数、正则表达式匹配和链式路由定义。路由处理器可以接受多个回调函数,这些函数行为类似中间件。
// 路由参数示例
app.get('/users/:userId/books/:bookId', (req, res) => {
res.send(req.params); // 返回 { userId: '123', bookId: '456' }
});
// 路由链示例
app.route('/book')
.get((req, res) => {
res.send('Get a random book');
})
.post((req, res) => {
res.send('Add a book');
});
请求和响应对象
Express扩展了Node.js原生的HTTP请求和响应对象,添加了许多实用方法和属性。
请求对象(req)常用属性:
- req.params:路由参数
- req.query:查询字符串
- req.body:请求体(需要body-parser中间件)
- req.cookies:客户端cookies
响应对象(res)常用方法:
- res.send():发送响应
- res.json():发送JSON响应
- res.render():渲染视图模板
- res.status():设置状态码
app.post('/login', (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).json({ error: 'Missing credentials' });
}
// 验证逻辑...
res.json({ token: 'generated-jwt-token' });
});
模板引擎集成
Express支持多种模板引擎,如EJS、Pug和Handlebars。通过app.set()方法配置视图引擎和视图目录。
// 配置EJS模板引擎
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
// 渲染视图
app.get('/profile', (req, res) => {
res.render('profile', { user: 'John' });
});
高级路由技巧
Express Router可以创建模块化的路由处理器,适合大型应用开发。
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/', (req, res) => {
res.send('User list');
});
router.get('/:id', (req, res) => {
res.send(`User ID: ${req.params.id}`);
});
module.exports = router;
// app.js
const userRouter = require('./routes/users');
app.use('/users', userRouter);
性能优化实践
Express应用可以通过以下方式优化性能:
- 使用helmet增强安全性
- 启用gzip压缩
- 实现请求限流
- 使用集群模式利用多核CPU
const compression = require('compression');
const helmet = require('helmet');
app.use(helmet());
app.use(compression());
// 限流中间件示例
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100 // 每个IP限制100个请求
});
app.use(limiter);
错误处理最佳实践
完善的错误处理机制对生产环境应用至关重要。Express支持同步错误自动捕获,但异步错误需要显式传递。
// 同步错误自动处理
app.get('/error', (req, res) => {
throw new Error('BROKEN'); // Express会自动捕获
});
// 异步错误需要next
app.get('/async-error', (req, res, next) => {
fs.readFile('/file-not-exist', (err, data) => {
if (err) {
next(err); // 手动传递错误
} else {
res.send(data);
}
});
});
// 最终错误处理器
app.use((err, req, res, next) => {
console.error(err);
res.status(500).render('error', { error: err });
});
Express与现代化JavaScript
现代Express应用可以结合ES6+特性如async/await,使代码更简洁。
app.get('/api/data', async (req, res, next) => {
try {
const data = await fetchDataFromDB();
const processed = await processData(data);
res.json(processed);
} catch (err) {
next(err);
}
});
测试Express应用
测试是保证应用质量的关键环节。可以使用Jest、Mocha等测试框架配合supertest进行HTTP测试。
const request = require('supertest');
const app = require('../app');
describe('GET /api/users', () => {
it('responds with JSON', async () => {
const response = await request(app)
.get('/api/users')
.expect('Content-Type', /json/)
.expect(200);
expect(response.body).toBeInstanceOf(Array);
});
});
部署注意事项
部署Express应用需要考虑环境变量管理、进程管理和日志记录等。
// 使用dotenv管理环境变量
require('dotenv').config();
// 生产环境配置
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
// 使用winston记录日志
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
app.use((req, res, next) => {
logger.info(`${req.method} ${req.url}`);
next();
});
Express生态系统
围绕Express形成了丰富的生态系统,包括各种中间件和扩展:
- 身份验证:passport.js
- 请求解析:body-parser、multer
- 会话管理:express-session
- API文档:swagger-ui-express
- 数据库集成:各种ORM/ODM
// 使用passport进行认证
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
(username, password, done) => {
User.findOne({ username }, (err, user) => {
if (err) return done(err);
if (!user) return done(null, false);
if (!user.verifyPassword(password)) return done(null, false);
return done(null, user);
});
}
));
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login' }),
(req, res) => {
res.redirect('/');
}
);
Express 5的新特性
虽然仍处于beta阶段,Express 5带来了一些改进:
- 路由方法返回promise
- 移除已弃用的方法
- 改进的错误处理
- 更好的异步支持
// Express 5中路由处理器可以返回promise
app.get('/async-route', async (req, res) => {
const data = await fetchData();
res.json(data);
});