在现代Web应用开发中,API(Application Programming Interface)扮演着至关重要的角色。API允许前端应用与后端服务器进行数据交互,实现动态内容展示和用户交互功能。本教程将指导您如何在Express应用中创建API路由,并将所有API路由组织在/api路径下,以保持项目结构的清晰性和可维护性。
API路由的概念
API路由是Web服务器上处理特定URL路径并返回数据的端点。与传统网页路由不同,API路由通常返回结构化数据(如JSON格式),而不是完整的HTML页面[1]。
将API路由组织在特定路径下(如/api)有以下优势:
- 清晰的分离:将API端点与网站页面路由明确分开
- 易于维护:统一管理所有API端点
- 版本控制:便于未来进行API版本升级(如
/api/v1、/api/v2)
- 安全性:可以针对API路由实施专门的安全措施
创建API路由目录结构
为了更好地组织代码,我们建议创建专门的目录来存放路由相关文件。
创建routes目录
在项目根目录下创建routes目录:
创建API子目录
在routes目录下创建api子目录,用于存放所有API路由:

最终的目录结构如下:
1 2 3 4 5 6 7
| my-express-app/ ├── routes/ │ └── api/ ├── public/ ├── index.js ├── package.json └── package-lock.json
|
创建北京时间API
现在让我们创建一个返回北京时间的API端点。北京时间是东八区时间(UTC+8),在国际项目中经常需要提供时区相关的服务。
创建时间API路由文件
在routes/api/目录下创建一个名为time.js的文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| const express = require('express'); const router = express.Router();
router.get('/beijing-time', (req, res) => { const now = new Date(); const beijingTime = new Date(now.getTime() + (8 * 60 * 60 * 1000)); res.json({ currentTime: beijingTime.toISOString(), formattedTime: beijingTime.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }), timezone: 'Asia/Shanghai', utcOffset: '+08:00' }); });
module.exports = router;
|
代码解释:
express.Router():创建一个新的路由器实例
router.get('/beijing-time', ...):定义处理GET请求的路由
new Date():创建当前时间对象
getTime() + (8 * 60 * 60 * 1000):将UTC时间转换为北京时间(加8小时)
res.json():以JSON格式返回数据
module.exports = router:导出路由器以供其他文件使用
API响应数据说明
API返回的JSON数据包含以下字段:
currentTime:ISO格式的北京时间
formattedTime:格式化的北京时间字符串
timezone:时区标识符
utcOffset:相对于UTC的偏移量
集成API路由到主应用
创建了API路由文件后,需要将其集成到主Express应用中。
更新主应用文件
修改项目根目录下的index.js文件,添加API路由:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const express = require('express'); const path = require('path'); const timeRoutes = require('./routes/api/time');
const app = express(); const port = 3000;
app.use(express.static('public'));
app.use('/api', timeRoutes);
app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); });
app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`); });
|

代码解释:
const timeRoutes = require('./routes/api/time'):引入时间API路由模块
app.use('/api', timeRoutes):将所有以/api开头的请求路由到timeRoutes处理器
- 这意味着
/api/beijing-time路径将由我们在time.js中定义的路由处理
API路由路径解析
通过以上配置,API端点的完整路径为:
- 北京时间API:
http://localhost:3000/api/beijing-time
当用户访问该路径时,请求处理流程如下:
- Express接收到
/api/beijing-time请求
app.use('/api', timeRoutes)匹配到/api前缀
- 剩余路径
/beijing-time被传递给timeRoutes路由器
- timeRoutes中的
router.get('/beijing-time', ...)处理该请求
- 返回JSON格式的北京时间数据
测试API路由
启动服务器
确保所有文件都已正确配置后,启动Express应用:
访问API端点
打开浏览器或使用curl命令访问API端点:
1
| curl http://localhost:3000/api/beijing-time
|
您应该会收到类似以下格式的JSON响应:
1 2 3 4 5 6
| { "currentTime": "2025-10-30T10:30:45.123Z", "formattedTime": "2025/10/30 18:30:45", "timezone": "Asia/Shanghai", "utcOffset": "+08:00" }
|

在浏览器中测试
您也可以直接在浏览器地址栏中输入以下URL来测试API:
1
| http://localhost:3000/api/beijing-time
|

现代浏览器通常会格式化显示JSON数据,便于查看。
扩展API路由
添加更多时间相关API
可以在同一个路由文件中添加更多时间相关的API端点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| const express = require('express'); const router = express.Router();
router.get('/beijing-time', (req, res) => { const now = new Date(); const beijingTime = new Date(now.getTime() + (8 * 60 * 60 * 1000)); res.json({ currentTime: beijingTime.toISOString(), formattedTime: beijingTime.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false }), timezone: 'Asia/Shanghai', utcOffset: '+08:00' }); });
router.get('/utc-time', (req, res) => { const now = new Date(); res.json({ currentTime: now.toISOString(), formattedTime: now.toUTCString(), timezone: 'UTC', utcOffset: '+00:00' }); });
router.get('/world-time', (req, res) => { const now = new Date(); const timeZones = { 'Asia/Shanghai': now.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }), 'America/New_York': now.toLocaleString('zh-CN', { timeZone: 'America/New_York' }), 'Europe/London': now.toLocaleString('zh-CN', { timeZone: 'Europe/London' }), 'Asia/Tokyo': now.toLocaleString('zh-CN', { timeZone: 'Asia/Tokyo' }) }; res.json({ currentTime: now.toISOString(), timeZones: timeZones }); });
module.exports = router;
|
创建独立的API路由文件
对于更复杂的项目,建议为不同功能创建独立的路由文件:
1 2 3 4 5 6
| routes/ └── api/ ├── time.js ├── user.js ├── product.js └── order.js
|
然后在主应用文件中统一引入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| const express = require('express'); const path = require('path'); const timeRoutes = require('./routes/api/time'); const userRoutes = require('./routes/api/user'); const productRoutes = require('./routes/api/product');
const app = express(); const port = 3000;
app.use(express.static('public'));
app.use('/api/time', timeRoutes); app.use('/api/user', userRoutes); app.use('/api/product', productRoutes);
app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); });
app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`); });
|
API路由最佳实践
- 统一前缀:所有API路由使用统一前缀(如
/api)
- 版本控制:考虑为API添加版本号(如
/api/v1)
- 语义化路径:使用清晰、语义化的路径命名
- HTTP状态码:正确使用HTTP状态码表示请求结果
- 错误处理:实现统一的错误处理机制
- 数据格式:统一使用JSON格式返回数据
- 安全性:对敏感API实施身份验证和授权
在前端使用API
可以在前端JavaScript中使用API获取数据并更新页面内容:
1 2 3 4 5 6 7 8 9
| fetch('/api/beijing-time') .then(response => response.json()) .then(data => { document.getElementById('time-display').innerText = data.formattedTime; }) .catch(error => { console.error('Error fetching time:', error); });
|
总结
通过本教程,我们学习了如何:
- 理解API路由的概念和优势
- 创建合理的API路由目录结构
- 编写返回北京时间的API端点
- 将API路由集成到Express主应用中
- 测试API路由功能
- 扩展API路由功能
- 遵循API路由最佳实践
这些技能为构建功能完整的Web应用奠定了基础,使您的应用能够提供动态数据服务。
参考文献
[1] Express.js, “Express - Node.js web application framework,” 2023. [Online]. Available: https://expressjs.com/. [Accessed: Oct. 30, 2025].