路由基础 #

一、路由概念 #

1.1 什么是路由? #

路由是指确定应用程序如何响应客户端对特定端点的请求。每个路由可以有一个或多个处理函数,当路由匹配时执行。

1.2 路由结构 #

javascript
app.METHOD(PATH, HANDLER)
组成部分 说明
app Express实例
METHOD HTTP请求方法
PATH 服务器上的路径
HANDLER 路由处理函数

1.3 基本示例 #

javascript
const express = require('express');
const app = express();

app.get('/', (req, res) => {
    res.send('GET请求 - 首页');
});

app.post('/', (req, res) => {
    res.send('POST请求 - 首页');
});

app.listen(3000);

二、路由方法 #

2.1 支持的HTTP方法 #

Express支持以下HTTP方法:

方法 说明
get 获取资源
post 创建资源
put 更新资源(完整更新)
patch 更新资源(部分更新)
delete 删除资源
head 获取响应头
options 获取支持的HTTP方法
all 匹配所有方法

2.2 GET请求 #

javascript
app.get('/users', (req, res) => {
    res.json({ users: [] });
});

app.get('/users/:id', (req, res) => {
    res.json({ id: req.params.id });
});

2.3 POST请求 #

javascript
app.use(express.json());

app.post('/users', (req, res) => {
    const user = req.body;
    res.status(201).json(user);
});

2.4 PUT请求 #

javascript
app.put('/users/:id', (req, res) => {
    const { id } = req.params;
    const userData = req.body;
    res.json({ id, ...userData, updated: true });
});

2.5 DELETE请求 #

javascript
app.delete('/users/:id', (req, res) => {
    res.json({ message: `用户 ${req.params.id} 已删除` });
});

2.6 app.all() #

匹配所有HTTP方法:

javascript
app.all('/secret', (req, res, next) => {
    console.log('访问secret路径');
    next();
});

app.get('/secret', (req, res) => {
    res.send('Secret内容');
});

三、路由路径 #

3.1 字符串路径 #

javascript
app.get('/', (req, res) => {
    res.send('根路径');
});

app.get('/about', (req, res) => {
    res.send('关于页面');
});

app.get('/random.text', (req, res) => {
    res.send('random.text');
});

3.2 字符串模式 #

javascript
app.get('/ab?cd', (req, res) => {
    res.send('ab?cd - b可选');
});

app.get('/ab+cd', (req, res) => {
    res.send('ab+cd - b可重复');
});

app.get('/ab*cd', (req, res) => {
    res.send('ab*cd - 中间任意字符');
});

app.get('/ab(cd)?e', (req, res) => {
    res.send('ab(cd)?e - cd可选');
});

3.3 正则表达式 #

javascript
app.get(/a/, (req, res) => {
    res.send('包含a的路径');
});

app.get(/.*fly$/, (req, res) => {
    res.send('以fly结尾的路径');
});

app.get(/^\/users\/\d+$/, (req, res) => {
    res.send('数字用户ID');
});

四、路由参数 #

4.1 路径参数 #

使用 :参数名 定义路径参数:

javascript
app.get('/users/:id', (req, res) => {
    res.json({ userId: req.params.id });
});

app.get('/posts/:postId/comments/:commentId', (req, res) => {
    res.json({
        postId: req.params.postId,
        commentId: req.params.commentId
    });
});

4.2 可选参数 #

使用 ? 表示可选参数:

javascript
app.get('/users/:id?', (req, res) => {
    if (req.params.id) {
        res.json({ userId: req.params.id });
    } else {
        res.json({ users: [] });
    }
});

4.3 参数验证 #

使用正则表达式验证参数:

javascript
app.get('/users/:id(\\d+)', (req, res) => {
    res.json({ userId: req.params.id });
});

4.4 参数中间件 #

javascript
app.param('id', (req, res, next, id) => {
    console.log(`ID参数: ${id}`);
    req.user = { id };
    next();
});

app.get('/users/:id', (req, res) => {
    res.json(req.user);
});

五、查询参数 #

5.1 获取查询参数 #

javascript
app.get('/search', (req, res) => {
    const { q, page, limit, sort } = req.query;
    
    res.json({
        query: q,
        page: parseInt(page) || 1,
        limit: parseInt(limit) || 10,
        sort: sort || 'desc'
    });
});

访问 /search?q=express&page=2&limit=20&sort=asc

json
{
    "query": "express",
    "page": 2,
    "limit": 20,
    "sort": "asc"
}

5.2 处理数组参数 #

javascript
app.get('/filter', (req, res) => {
    const { tags } = req.query;
    
    const tagList = Array.isArray(tags) ? tags : [tags].filter(Boolean);
    
    res.json({ tags: tagList });
});

访问 /filter?tags=node&tags=express&tags=javascript

json
{
    "tags": ["node", "express", "javascript"]
}

六、多个处理函数 #

6.1 多个回调函数 #

javascript
app.get('/example', (req, res, next) => {
    console.log('第一个处理函数');
    next();
}, (req, res) => {
    console.log('第二个处理函数');
    res.send('响应');
});

6.2 使用数组 #

javascript
const middleware1 = (req, res, next) => {
    console.log('中间件1');
    next();
};

const middleware2 = (req, res, next) => {
    console.log('中间件2');
    next();
};

app.get('/protected', [middleware1, middleware2], (req, res) => {
    res.send('受保护的内容');
});

6.3 混合使用 #

javascript
app.get('/mixed', 
    middleware1,
    [middleware2, (req, res, next) => {
        console.log('中间件3');
        next();
    }],
    (req, res) => {
        res.send('混合使用');
    }
);

七、响应方法 #

7.1 常用响应方法 #

方法 说明
res.send() 发送响应
res.json() 发送JSON响应
res.status() 设置状态码
res.redirect() 重定向
res.render() 渲染模板
res.sendFile() 发送文件
res.download() 下载文件
res.end() 结束响应

7.2 链式调用 #

javascript
app.get('/user', (req, res) => {
    res.status(200)
       .set('X-Custom-Header', 'value')
       .json({ name: 'Express' });
});

7.3 设置响应头 #

javascript
app.get('/headers', (req, res) => {
    res.set({
        'Content-Type': 'application/json',
        'X-Powered-By': 'Express'
    });
    res.json({ message: 'Headers set' });
});

八、路由组织 #

8.1 按功能分组 #

javascript
const users = [
    { id: 1, name: '张三' },
    { id: 2, name: '李四' }
];

app.get('/users', (req, res) => {
    res.json(users);
});

app.get('/users/:id', (req, res) => {
    const user = users.find(u => u.id === parseInt(req.params.id));
    res.json(user);
});

app.post('/users', (req, res) => {
    const user = { id: users.length + 1, ...req.body };
    users.push(user);
    res.status(201).json(user);
});

app.put('/users/:id', (req, res) => {
    const index = users.findIndex(u => u.id === parseInt(req.params.id));
    users[index] = { ...users[index], ...req.body };
    res.json(users[index]);
});

app.delete('/users/:id', (req, res) => {
    const index = users.findIndex(u => u.id === parseInt(req.params.id));
    users.splice(index, 1);
    res.status(204).send();
});

8.2 路由链 #

javascript
app.route('/articles')
    .get((req, res) => {
        res.send('获取文章列表');
    })
    .post((req, res) => {
        res.send('创建文章');
    });

app.route('/articles/:id')
    .get((req, res) => {
        res.send(`获取文章 ${req.params.id}`);
    })
    .put((req, res) => {
        res.send(`更新文章 ${req.params.id}`);
    })
    .delete((req, res) => {
        res.send(`删除文章 ${req.params.id}`);
    });

九、路由匹配顺序 #

9.1 匹配规则 #

Express按照定义顺序匹配路由:

javascript
app.get('/users/special', (req, res) => {
    res.send('特殊用户');
});

app.get('/users/:id', (req, res) => {
    res.send(`用户ID: ${req.params.id}`);
});

访问 /users/special 会匹配第一个路由。

9.2 注意事项 #

javascript
app.get('/users/:id', (req, res) => {
    res.send(`用户ID: ${req.params.id}`);
});

app.get('/users/special', (req, res) => {
    res.send('特殊用户');
});

此时访问 /users/special 会匹配第一个路由,因为 special 被当作 :id 的值。

9.3 正确顺序 #

javascript
app.get('/users/special', (req, res) => {
    res.send('特殊用户');
});

app.get('/users/admin', (req, res) => {
    res.send('管理员');
});

app.get('/users/:id', (req, res) => {
    res.send(`用户ID: ${req.params.id}`);
});

十、错误处理 #

10.1 同步错误 #

javascript
app.get('/error', (req, res) => {
    throw new Error('出错了!');
});

app.use((err, req, res, next) => {
    res.status(500).json({ error: err.message });
});

10.2 异步错误 #

javascript
app.get('/async-error', async (req, res, next) => {
    try {
        const data = await someAsyncFunction();
        res.json(data);
    } catch (error) {
        next(error);
    }
});

10.3 404处理 #

javascript
app.get('/', (req, res) => {
    res.send('首页');
});

app.use((req, res) => {
    res.status(404).json({ error: '路由未找到' });
});

十一、总结 #

路由基础要点:

概念 说明
路由结构 app.METHOD(PATH, HANDLER)
HTTP方法 get、post、put、delete等
路径模式 字符串、正则表达式
路径参数 :param定义参数
查询参数 req.query获取
处理函数 单个或多个函数

下一步,让我们深入学习路由方法!

最后更新:2026-03-28