如何编写RESTful风格路由?

wen PHP项目 66

本文目录导读:

如何编写RESTful风格路由?

  1. RESTful路由核心原则
  2. 各种后端框架实现
  3. RESTful路由设计模板
  4. 最佳实践
  5. 注意事项

我来详细讲解如何编写RESTful风格路由,包括概念、设计原则和具体实现。

RESTful路由核心原则

资源命名

  • 使用名词(复数形式)表示资源
  • 使用HTTP方法表示操作
  • 使用URL层级表示关系

各种后端框架实现

Node.js (Express)

const express = require('express');
const router = express.Router();
// 获取所有用户
router.get('/users', (req, res) => {
  res.json({ users: [] });
});
// 获取单个用户
router.get('/users/:id', (req, res) => {
  res.json({ user: { id: req.params.id } });
});
// 创建用户
router.post('/users', (req, res) => {
  res.status(201).json({ message: 'Created' });
});
// 更新用户(全量更新)
router.put('/users/:id', (req, res) => {
  res.json({ message: 'Updated' });
});
// 部分更新用户
router.patch('/users/:id', (req, res) => {
  res.json({ message: 'Partially updated' });
});
// 删除用户
router.delete('/users/:id', (req, res) => {
  res.status(204).send();
});
module.exports = router;

Express 路由分组最佳实践

// routes/users.js
const router = require('express').Router();
router.route('/')
  .get(getUsers)
  .post(createUser);
router.route('/:id')
  .get(getUser)
  .put(updateUser)
  .patch(partialUpdateUser)
  .delete(deleteUser);
// 嵌套资源
router.route('/:userId/posts')
  .get(getUserPosts)
  .post(createUserPost);
router.route('/:userId/posts/:postId')
  .get(getUserPost)
  .put(updateUserPost)
  .delete(deleteUserPost);
module.exports = router;

Python (Flask)

from flask import Flask, request, jsonify
from flask_restful import Api, Resource
app = Flask(__name__)
api = Api(app)
class UserList(Resource):
    def get(self):
        return {'users': []}
    def post(self):
        data = request.get_json()
        return {'message': 'Created'}, 201
class UserDetail(Resource):
    def get(self, user_id):
        return {'user': {'id': user_id}}
    def put(self, user_id):
        return {'message': 'Updated'}
    def delete(self, user_id):
        return '', 204
api.add_resource(UserList, '/users')
api.add_resource(UserDetail, '/users/<int:user_id>')
if __name__ == '__main__':
    app.run(debug=True)

Python (Django REST Framework)

# urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter()
router.register(r'users', views.UserViewSet)
urlpatterns = [
    path('', include(router.urls)),
]
# views.py
from rest_framework import viewsets
from .models import User
from .serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    # 自定义动作
    @action(detail=True, methods=['post'])
    def activate(self, request, pk=None):
        user = self.get_object()
        user.is_active = True
        user.save()
        return Response({'status': 'activated'})

Java (Spring Boot)

@RestController
@RequestMapping("/api/users")
public class UserController {
    @GetMapping
    public ResponseEntity<List<User>> getAllUsers() {
        return ResponseEntity.ok(userService.findAll());
    }
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        return ResponseEntity.ok(userService.findById(id));
    }
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody @Valid User user) {
        User created = userService.save(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(created);
    }
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        return ResponseEntity.ok(userService.update(id, user));
    }
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.delete(id);
        return ResponseEntity.noContent().build();
    }
}

Ruby on Rails

# config/routes.rb
Rails.application.routes.draw do
  resources :users do
    resources :posts, shallow: true
    member do
      get :activate
    end
    collection do
      get :search
    end
  end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    @users = User.all
    render json: @users
  end
  def show
    @user = User.find(params[:id])
    render json: @user
  end
  def create
    @user = User.new(user_params)
    if @user.save
      render json: @user, status: :created
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end
end

RESTful路由设计模板

CRUD操作映射

HTTP方法 路由 操作 状态码
GET /users 获取所有用户 200
GET /users/:id 获取单个用户 200
POST /users 创建用户 201
PUT /users/:id 更新用户 200
PATCH /users/:id 部分更新 200
DELETE /users/:id 删除用户 204

高级路由模式

// 搜索和过滤
GET /api/users?status=active&role=admin
GET /api/users?page=1&limit=20&sort=-createdAt
// 关系资源
GET /api/users/:userId/orders
GET /api/users/:userId/orders/:orderId
// 操作动作
POST /api/users/:userId/activate
POST /api/orders/:orderId/cancel
// 批量操作
POST /api/users/batch
DELETE /api/users/batch

最佳实践

版本控制

// URL版本控制
/api/v1/users
/api/v2/users
// 请求头版本控制
Accept: application/vnd.company.v1+json
// 子域名版本控制
v1.api.example.com/users

错误处理

// 统一的错误响应格式
{
  "error": {
    "code": "USER_NOT_FOUND",
    "message": "User with ID 123 not found",
    "details": {
      "userId": "123"
    }
  }
}
// 错误状态码使用
200 - 成功
201 - 创建成功
204 - 删除成功
400 - 请求参数错误
401 - 未认证
403 - 无权限
404 - 资源不存在
422 - 验证失败
429 - 请求过多
500 - 服务器错误

分页实现

// 请求
GET /api/users?page=2&limit=20
// 响应
{
  "data": [...],
  "pagination": {
    "page": 2,
    "limit": 20,
    "total": 100,
    "totalPages": 5,
    "next": "/api/users?page=3&limit=20",
    "prev": "/api/users?page=1&limit=20"
  }
}

关联数据

// 包含关联数据
GET /api/users/123?include=posts,settings
// 响应
{
  "id": 123,
  "name": "John",
  "posts": [...],
  "settings": {...}
}

注意事项

  1. 一致性:保持命名和格式的统一
  2. 安全性:始终验证和清理输入
  3. 文档:使用Swagger/OpenAPI规范文档
  4. 测试:为每个路由编写单元测试
  5. 性能:添加缓存、限制和过滤

这样设计的路由清晰、可维护,符合RESTful最佳实践。

抱歉,评论功能暂时关闭!