Appearance
Express路由系统
路由定义了应用如何响应客户端对特定端点的请求,包括请求的URL路径和HTTP方法。每个路由可以有一个或多个处理函数,当路由匹配时执行。
路由定义
路由在Express中定义为:
javascript
app.METHOD(PATH, HANDLER)
app- Express应用实例METHOD- HTTP请求方法 (get, post, put, delete等)PATH- 路由路径(端点)HANDLER- 路由匹配时执行的处理函数
基本路由
简单路由
javascript
const express = require('express');
const app = express();
// GET请求
app.get('/', (req, res) => {
res.send('Hello World!');
});
// POST请求
app.post('/users', (req, res) => {
res.send('Creating a user');
});
// PUT请求
app.put('/users/:id', (req, res) => {
res.send(`Updating user ${req.params.id}`);
});
// DELETE请求
app.delete('/users/:id', (req, res) => {
res.send(`Deleting user ${req.params.id}`);
});
路由路径
静态路径
javascript
app.get('/users', (req, res) => {
res.send('Users list');
});
app.get('/users/profile', (req, res) => {
res.send('User profile');
});
路由参数
使用冒号(:)定义路由参数:
javascript
// 单个参数
app.get('/users/:userId', (req, res) => {
res.send(`User ID: ${req.params.userId}`);
});
// 多个参数
app.get('/users/:userId/books/:bookId', (req, res) => {
res.send(`User: ${req.params.userId}, Book: ${req.params.bookId}`);
});
// 可选参数
app.get('/users/:userId?', (req, res) => {
if (req.params.userId) {
res.send(`User ID: ${req.params.userId}`);
} else {
res.send('No user ID provided');
}
});
路径模式
javascript
// 模式匹配 - ? 表示可选字符
app.get('/ab?cd', (req, res) => {
res.send('ab?cd - matches /acd or /abcd');
});
// 模式匹配 - + 表示一个或多个
app.get('/ab+cd', (req, res) => {
res.send('ab+cd - matches /abcd, /abbcd, /abbbcd, etc');
});
// 模式匹配 - * 表示零个或多个
app.get('/ab*cd', (req, res) => {
res.send('ab*cd - matches /abcd, /abxcd, /abRANDOMcd, etc');
});
// 模式匹配 - () 表示组
app.get('/ab(cd)?e', (req, res) => {
res.send('/ab(cd)?e - matches /abe or /abcde');
});
正则表达式路径
javascript
// 匹配以a开头的路径
app.get(/a/, (req, res) => {
res.send('Path contains "a"');
});
// 匹配以fly结尾的路径
app.get(/.*fly$/, (req, res) => {
res.send('Path ends with "fly"');
});
// 匹配数字ID
app.get(/\/users\/(\d+)/, (req, res) => {
res.send('User with numeric ID');
});
路由处理函数
单个处理函数
javascript
app.get('/example', (req, res) => {
res.send('Hello from a single handler');
});
多个处理函数
javascript
// 多个中间件函数
const handler1 = (req, res, next) => {
console.log('Handler 1');
next();
};
const handler2 = (req, res) => {
res.send('Hello from multiple handlers');
};
app.get('/example', handler1, handler2);
数组处理函数
javascript
const middleware1 = (req, res, next) => {
console.log('Middleware 1');
next();
};
const middleware2 = (req, res, next) => {
console.log('Middleware 2');
next();
};
app.get('/example', [middleware1, middleware2], (req, res) => {
res.send('Hello from array handlers');
});
路由方法
Express支持所有HTTP方法:
javascript
app.get('/', (req, res) => { /* GET */ });
app.post('/users', (req, res) => { /* POST */ });
app.put('/users/:id', (req, res) => { /* PUT */ });
app.delete('/users/:id', (req, res) => { /* DELETE */ });
app.patch('/users/:id', (req, res) => { /* PATCH */ });
app.options('/users', (req, res) => { /* OPTIONS */ });
app.head('/users', (req, res) => { /* HEAD */ });
响应方法
路由处理函数中可以使用多种响应方法:
javascript
app.get('/responses', (req, res) => {
// res.send() - 发送响应
// res.json() - 发送JSON响应
// res.jsonp() - 发送JSONP响应
// res.redirect() - 重定向响应
// res.render() - 渲染视图模板
// res.end() - 结束响应
// res.download() - 提示下载文件
// res.sendFile() - 发送文件
// res.sendStatus() - 设置状态码并发送响应
res.json({
message: 'Hello World',
timestamp: new Date()
});
});
路由参数详解
req.params
包含路由路径中指定的键值对:
javascript
// GET /users/123/books/456
app.get('/users/:userId/books/:bookId', (req, res) => {
console.log(req.params.userId); // 123
console.log(req.params.bookId); // 456
res.send(req.params);
});
req.query
包含URL查询字符串中的键值对:
javascript
// GET /search?q=express&sort=asc
app.get('/search', (req, res) => {
console.log(req.query.q); // express
console.log(req.query.sort); // asc
res.send(req.query);
});
req.body
包含请求体中的数据(需要中间件):
javascript
app.use(express.json()); // 解析JSON请求体
app.post('/users', (req, res) => {
console.log(req.body.name); // 从请求体获取数据
res.json({ message: 'User created', user: req.body });
});
Router对象
使用express.Router()创建模块化路由:
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('Router homepage');
});
router.get('/about', (req, res) => {
res.send('Router about page');
});
// 将路由器挂载到应用
app.use('/api', router);
路由模块化
创建路由模块
javascript
// routes/users.js
const express = require('express');
const router = express.Router();
// GET /users
router.get('/', (req, res) => {
res.json({ message: 'Users list' });
});
// GET /users/:id
router.get('/:id', (req, res) => {
res.json({ id: req.params.id, name: 'User name' });
});
// POST /users
router.post('/', (req, res) => {
res.json({ message: 'User created', user: req.body });
});
module.exports = router;
在主应用中使用路由模块
javascript
// app.js
const express = require('express');
const userRoutes = require('./routes/users');
const app = express();
app.use('/users', userRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
路由前缀和嵌套
javascript
const express = require('express');
const app = express();
// 带前缀的路由
app.use('/api/v1', (req, res, next) => {
console.log('API version 1 middleware');
next();
});
// 嵌套路由
const apiRouter = express.Router();
const userRouter = express.Router();
userRouter.get('/', (req, res) => res.send('Users'));
userRouter.get('/:id', (req, res) => res.send(`User ${req.params.id}`));
apiRouter.use('/users', userRouter);
app.use('/api', apiRouter);
路由重定向
javascript
// 临时重定向 (302)
app.get('/old-path', (req, res) => {
res.redirect('/new-path');
});
// 永久重定向 (301)
app.get('/old-page', (req, res) => {
res.redirect(301, '/new-page');
});
// 重定向到外部URL
app.get('/external', (req, res) => {
res.redirect('https://example.com');
});
错误路由处理
javascript
// 404处理
app.use((req, res, next) => {
res.status(404).send('Route not found');
});
// 错误处理中间件
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
高级路由模式
路由参数验证
javascript
// 使用正则表达式验证参数
app.get('/users/:userId(\\d+)', (req, res) => {
// 只匹配数字类型的userId
res.send(`User ID: ${req.params.userId}`);
});
// 自定义参数验证中间件
app.param('userId', (req, res, next, id) => {
if (id.length !== 24) {
next(new Error('Invalid user ID'));
} else {
next();
}
});
Express的路由系统非常灵活和强大,通过合理使用路由参数、模式匹配和中间件,可以构建复杂而高效的Web应用路由结构。