深入理解 RESTful API:请求与响应详解及实战代码示例

1. 什么是 RESTful API?

REST(Representational State Transfer,表述性状态转移)是一种软件架构风格,用于设计网络应用程序的接口。RESTful API 是基于 REST 原则设计的 API,它使用标准的 HTTP 方法(GET、POST、PUT、DELETE 等)对资源进行操作,并通过 HTTP 状态码和媒体类型(如 JSON、XML)进行通信。

RESTful API 的核心特征包括:

  • 无状态(Stateless):每个请求都包含处理该请求所需的全部信息,服务器不保存客户端状态。
  • 统一接口(Uniform Interface):使用标准的 HTTP 方法和资源标识符(URI)。
  • 资源导向(Resource-Oriented):将数据和功能都视为资源,通过 URI 进行标识。
  • 可缓存(Cacheable):响应应明确标识是否可缓存,以提高性能。
  • 分层系统(Layered System):客户端无需知道是否直接连接到最终服务器。

2. RESTful API 请求详解

2.1 HTTP 方法(动词)

RESTful API 使用 HTTP 方法来定义对资源的操作意图:

  • GET:获取资源(安全且幂等)。
  • POST:创建新资源。
  • PUT:更新整个资源(幂等)。
  • PATCH:部分更新资源。
  • DELETE:删除资源(幂等)。
  • HEAD:获取资源的元信息。
  • OPTIONS:获取资源支持的通信选项。

2.2 请求头(Headers)

请求头携带了关于请求的元数据,常见的有:

  • Content-Type:请求体的媒体类型,如 application/jsonapplication/xml
  • Accept:客户端期望的响应媒体类型。
  • Authorization:身份验证凭证,如 Bearer Token。
  • User-Agent:客户端软件信息。

2.3 请求体(Body)

对于 POST、PUT、PATCH 请求,通常需要携带请求体来传递数据。JSON 是目前最常用的格式。

// 创建用户的请求体示例
{
  "username": "john_doe",
  "email": "john@example.com",
  "age": 30,
  "active": true
}

2.4 查询参数(Query Parameters)与路径参数(Path Parameters)

路径参数用于标识特定资源,通常作为 URI 的一部分:

GET /api/users/123
GET /api/posts/456/comments

查询参数用于过滤、排序、分页等:

GET /api/users?role=admin&active=true
GET /api/products?category=electronics&sort=price&page=2&limit=20

3. RESTful API 响应详解

3.1 HTTP 状态码(Status Codes)

状态码表示请求的处理结果:

  • 2xx 成功
    • 200 OK:请求成功。
    • 201 Created:资源创建成功。
    • 204 No Content:请求成功,但无返回内容。
  • 3xx 重定向
    • 301 Moved Permanently:资源永久移动。
    • 302 Found:资源临时移动。
  • 4xx 客户端错误
    • 400 Bad Request:请求语法错误。
    • 401 Unauthorized:未认证。
    • 403 Forbidden:无权限。
    • 404 Not Found:资源不存在。
    • 422 Unprocessable Entity:请求格式正确但语义错误。
  • 5xx 服务器错误
    • 500 Internal Server Error:服务器内部错误。
    • 502 Bad Gateway:网关错误。
    • 503 Service Unavailable:服务不可用。

3.2 响应头(Response Headers)

响应头携带了关于响应的元数据,常见的有:

  • Content-Type:响应体的媒体类型。
  • Content-Length:响应体的大小。
  • Cache-Control:缓存控制指令。
  • Location(常用于 201 Created):新创建资源的 URI。

3.3 响应体(Response Body)

响应体包含了请求的结果数据。成功的响应通常遵循一致的格式。

// 成功响应示例(包含数据)
{
  "status": "success",
  "data": {
    "id": 123,
    "username": "john_doe",
    "email": "john@example.com"
  },
  "message": "User retrieved successfully"
}
// 错误响应示例
{
"status": "error",
"code": 400,
"message": "Invalid email format",
"details": {
"field": "email",
"reason": "Must be a valid email address"
}
}

4. 实战代码示例

4.1 使用 Python Flask 创建 RESTful API

from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(name)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
db = SQLAlchemy(app)
数据模型
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def to_dict(self):
    return {
        'id': self.id,
        'username': self.username,
        'email': self.email
    }
创建数据库表
with app.app_context():
db.create_all()
获取所有用户 (GET /api/users)
@app.route('/api/users', methods=['GET'])
def get_users():
users = User.query.all()
return jsonify({
'status': 'success',
'data': [user.to_dict() for user in users],
'count': len(users)
}), 200
获取单个用户 (GET /api/users/<id>)
@app.route('/api/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
user = User.query.get(user_id)
if not user:
return jsonify({
'status': 'error',
'code': 404,
'message': f'User with id {user_id} not found'
}), 404
return jsonify({
    'status': 'success',
    'data': user.to_dict()
}), 200
创建用户 (POST /api/users)
@app.route('/api/users', methods=['POST'])
def create_user():
data = request.get_json()
# 验证必要字段
if not data or 'username' not in data or 'email' not in data:
    return jsonify({
        'status': 'error',
        'code': 400,
        'message': 'Username and email are required'
    }), 400
检查用户是否已存在
if User.query.filter_by(username=data['username']).first():
return jsonify({
'status': 'error',
'code': 409,
'message': f'Username {data["username"]} already exists'
}), 409
创建新用户
new_user = User(username=data['username'], email=data['email'])
db.session.add(new_user)
db.session.commit()
return jsonify({
'status': 'success',
'data': new_user.to_dict(),
'message': 'User created successfully'
}), 201
更新用户 (PUT /api/users/<id>)
@app.route('/api/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
user = User.query.get(user_id)
if not user:
return jsonify({
'status': 'error',
'code': 404,
'message': f'User with id {user_id} not found'
}), 404
data = request.get_json()
if 'username' in data:
user.username = data['username']
if 'email' in data:
user.email = data['email']
db.session.commit()
return jsonify({
'status': 'success',
'data': user.to_dict(),
'message': 'User updated successfully'
}), 200
删除用户 (DELETE /api/users/<id>)
@app.route('/api/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
user = User.query.get(user_id)
if not user:
return jsonify({
'status': 'error',
'code': 404,
'message': f'User with id {user_id} not found'
}), 404
db.session.delete(user)
db.session.commit()
return jsonify({
'status': 'success',
'message': f'User with id {user_id} deleted successfully'
}), 204
if name == 'main':
app.run(debug=True)

4.2 使用 JavaScript (Fetch API) 调用 RESTful API

// 基础配置
const API_BASE_URL = 'http://localhost:5000/api';
// 获取所有用户
async function fetchUsers() {
try {
const response = await fetch(${API_BASE_URL}/users);
if (!response.ok) {
throw new Error(HTTP error! status: ${response.status});
}
const result = await response.json();
console.log('Users:', result.data);
return result.data;
} catch (error) {
console.error('Error fetching users:', error);
throw error;
}
}
// 获取单个用户
async function fetchUser(userId) {
try {
const response = await fetch(${API_BASE_URL}/users/${userId});
if (!response.ok) {
if (response.status === 404) {
console.log(User ${userId} not found);
return null;
}
throw new Error(HTTP error! status: ${response.status});
}
const result = await response.json();
console.log('User:', result.data);
return result.data;
} catch (error) {
console.error(Error fetching user ${userId}:, error);
throw error;
}
}
// 创建用户
async function createUser(userData) {
try {
const response = await fetch(${API_BASE_URL}/users, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(userData)
});
    const result = await response.json();
if (!response.ok) {
    throw new Error(result.message || 'Failed to create user');
}
console.log('User created:', result.data);
return result.data;
} catch (error) {
console.error('Error creating user:', error);
throw error;
}
}
// 更新用户
async function updateUser(userId, updateData) {
try {
const response = await fetch(${API_BASE_URL}/users/${userId}, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(updateData)
});
const result = await response.json();
if (!response.ok) {
throw new Error(result.message || 'Failed to update user');
}
console.log('User updated:', result.data);
return result.data;
} catch (error) {
console.error(Error updating user ${userId}:, error);
throw error;
}
}
// 删除用户
async function deleteUser(userId) {
try {
const response = await fetch(${API_BASE_URL}/users/${userId}, {
method: 'DELETE'
});
if (!response.ok && response.status !== 204) {
const result = await response.json();
throw new Error(result.message || 'Failed to delete user');
}
console.log(User ${userId} deleted successfully);
return true;
} catch (error) {
console.error(Error deleting user ${userId}:, error);
throw error;
}
}
// 使用示例
async function exampleUsage() {
// 1. 获取所有用户
const users = await fetchUsers();
// 2. 创建新用户
const newUser = await createUser({
username: 'alice_smith',
email: 'alice@example.com'
});
// 3. 获取刚创建的用户
const user = await fetchUser(newUser.id);
// 4. 更新用户
await updateUser(newUser.id, {
email: 'alice.new@example.com'
});
// 5. 删除用户
await deleteUser(newUser.id);
}
// 运行示例
exampleUsage().catch(console.error);

4.3 使用 Java Spring Boot 创建 RESTful API

// User.java - 实体类
package com.example.restapi.model;
import jakarta.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(unique = true, nullable = false)
private String email;
// 构造方法、Getter 和 Setter
public User() {}
public User(String username, String email) {
this.username = username;
this.email = email;
}
// Getters and Setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
// ApiResponse.java - 统一响应格式
package com.example.restapi.dto;
public class ApiResponse<T> {
private String status;
private T data;
private String message;
public ApiResponse(String status, T data, String message) {
this.status = status;
this.data = data;
this.message = message;
}
// 成功响应工厂方法
public static &lt;T&gt; ApiResponse&lt;T&gt; success(T data) {
return new ApiResponse&lt;&gt;("success", data, null);
}
public static &lt;T&gt; ApiResponse&lt;T&gt; success(T data, String message) {
return new ApiResponse&lt;&gt;("success", data, message);
}
// 错误响应工厂方法
public static ApiResponse&lt;?&gt; error(String message) {
return new ApiResponse&lt;&gt;("error", null, message);
}
// Getters and Setters
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public T getData() { return data; }
public void setData(T data) { this.data = data; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
}
// UserController.java - 控制器
package com.example.restapi.controller;
import com.example.restapi.model.User;
import com.example.restapi.dto.ApiResponse;
import com.example.restapi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// GET /api/users - 获取所有用户
@GetMapping
public ResponseEntity&lt;ApiResponse&lt;List&lt;User&gt;&gt;&gt; getAllUsers() {
List&lt;User&gt; users = userService.getAllUsers();
return ResponseEntity.ok(ApiResponse.success(users, "Users retrieved successfully"));
}
// GET /api/users/{id} - 获取单个用户
@GetMapping("/{id}")
public ResponseEntity&lt;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值