【Javaweb】Restful开发规范
一、核心原则(REST 架构风格的基石)
无状态
每个来自客户端的请求都必须包含服务器处理该请求所需的所有信息。服务器不应存储客户端的任何会话状态。这意味着不应使用服务器端的 Session,而应使用客户端的 Token(如 JWT)来传递身份和状态信息。面向资源
将数据和行为抽象为“资源”。API 的核心是操作资源,而不是执行动作。URI 应该指向资源,而不是操作。好的例子:
GET /users
(获取用户列表)坏的例子:
GET /getUsers
(包含了动词)
统一接口
这是 REST 设计的关键,它简化了架构。具体体现为:资源的标识: 每个资源都有一个唯一的 URI(如
/users/123
)。通过表述操作资源: 客户端通过 HTTP 方法(GET, POST, PUT, DELETE 等)来操作资源。
自描述的消息: 每个消息(请求/响应)都包含足够的信息来描述如何处理自己(如使用
Content-Type
头)。超媒体作为应用状态引擎(HATEOAS): 在响应中提供链接,使得客户端可以发现可执行的操作。这是最高级的 REST 约束,但在实际 API 中常常被简化。
可缓存
服务器响应应明确指示资源是否可以被缓存,以及缓存多长时间。这可以通过 HTTP 头(如Cache-Control
,Expires
,ETag
)来实现,以提高性能。
二、具体设计规范
1. 域名与版本
域名: 应尽量将 API 部署在专用域名下。
https://api.example.com
版本: 版本号应包含在 URI 或 HTTP 头中,推荐使用 URI 路径,更直观。
URI 路径:
https://api.example.com/v1/users
Accept 头(不常用但更规范):
Accept: application/vnd.example.v1+json
2. 端点(Endpoint / URI)设计
使用名词的复数形式: URI 表示资源的地址,应该使用名词,而不是动词。
获取用户:
GET /users
创建用户:
POST /users
获取单个用户:
GET /users/123
更新用户:
PUT /users/123
(全量更新)或PATCH /users/123
(部分更新)删除用户:
DELETE /users/123
资源层级关系: 如果资源有关联关系,应在 URI 中体现。
获取某个用户的所有文章:
GET /users/123/articles
获取某用户某篇文章的详情:
GET /users/123/articles/456
注意:层级不宜过深,过深可考虑使用查询参数扁平化。例如
GET /articles?user_id=123
使用连字符(-)提高可读性: 避免使用下划线(_)。
GET /user-roles
(推荐)GET /user_roles
(不推荐)
使用小写字母: URI 应全部使用小写字母。
3. HTTP 方法(动词)的正确使用
HTTP 方法 | 含义 | 对应 SQL | 幂等性 | 安全性 |
---|---|---|---|---|
GET | 获取资源(一个或多个) | SELECT | 是 | 是 |
POST | 创建新资源 | INSERT | 否 | 否 |
PUT | 完整更新资源(客户端提供完整资源) | UPDATE | 是 | 否 |
PATCH | 部分更新资源(客户端提供需要修改的字段) | UPDATE | 否 | 否 |
DELETE | 删除资源 | DELETE | 是 | 否 |
幂等性: 对同一资源的多次相同请求,效果与一次请求相同。例如,
PUT /users/123
无论调用多少次,结果都一样。这在网络不稳定时非常重要。安全性: 不会修改服务器资源的操作是安全的,如 GET 和 HEAD。
4. 查询、分页、过滤和排序
对于获取资源集合(如 GET /articles
),通常需要这些功能。
查询: 使用查询参数进行搜索。
GET /articles?title=restful
过滤: 指定返回哪些字段。
GET /articles?fields=title,author,publish_date
分页: 使用
limit
和offset
或page
和size
。GET /articles?page=2&size=20
响应中应包含分页元数据:
json
{"data": [...],"pagination": {"page": 2,"size": 20,"total": 100,"total_pages": 5} }
排序: 使用
sort
参数。GET /articles?sort=-publish_date,title
(-
表示降序)
5. 状态码(Status Codes)
服务器必须返回恰当的 HTTP 状态码,让客户端能明确知道请求结果。
2xx(成功)
200 OK
- GET、PUT、PATCH 请求成功。201 Created
- POST 成功创建资源。响应头Location
应包含新资源的 URI。204 No Content
- DELETE 成功或请求成功但无内容返回(如 POST 操作无需返回数据时)。
4xx(客户端错误)
400 Bad Request
- 请求格式错误(如参数解析失败)。401 Unauthorized
- 未认证(身份验证失败)。403 Forbidden
- 已认证,但无权限访问该资源。404 Not Found
- 请求的资源不存在。405 Method Not Allowed
- 不允许的 HTTP 方法。429 Too Many Requests
- 请求过于频繁(限流)。
5xx(服务器错误)
500 Internal Server Error
- 服务器内部通用错误。502 Bad Gateway
- 网关或代理服务器从上游服务器收到无效响应。503 Service Unavailable
- 服务暂时不可用(如维护中)。
6. 响应体(Response Body)
数据格式: 推荐使用 JSON。设置
Content-Type: application/json
。命名约定: 使用 蛇形命名法(snake_case) 是 JSON 属性名最常见的约定,与 JavaScript 的驼峰命名法(camelCase)相对应。保持一致性即可。
错误处理: 发生错误时,应返回结构化的错误信息。
json
{"error": {"code": "invalid_parameter","message": "The 'email' parameter is invalid.","details": {...} // 可选,更详细的错误信息} }
7. 安全相关
使用 HTTPS: 所有 API 请求都必须通过 HTTPS 进行,以保证数据传输安全。
身份认证: 常用方式有 API Token、JWT(JSON Web Tokens)、OAuth 2.0。认证信息通常放在 HTTP 请求头
Authorization
中(如Authorization: Bearer <token>
)。限流(Rate Limiting): 为防止滥用,应对 API 进行调用频率限制。可以在响应头中告知客户端限制信息:
X-RateLimit-Limit
: 一段时间内允许的最大请求数。X-RateLimit-Remaining
: 当前时间段内剩余的请求数。X-RateLimit-Reset
: 限制重置的时间戳。
三、示例:一个完整的用户管理 API
操作 | HTTP 方法 | 端点 | 描述 | 成功状态码 |
---|---|---|---|---|
获取用户列表 | GET | /v1/users | 可能带分页和过滤 | 200 OK |
创建新用户 | POST | /v1/users | 请求体包含用户信息 | 201 Created |
获取单个用户 | GET | /v1/users/{id} | 200 OK | |
完整更新用户 | PUT | /v1/users/{id} | 请求体包含完整用户信息 | 200 OK |
部分更新用户 | PATCH | /v1/users/{id} | 请求体包含要更新的字段 | 200 OK |
删除用户 | DELETE | /v1/users/{id} | 204 No Content |
创建用户请求示例:
http
POST /v1/users HTTP/1.1 Host: api.example.com Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Content-Type: application/json{"user": {"name": "John Doe","email": "john@example.com"} }
创建用户成功响应示例:
http
HTTP/1.1 201 Created Location: /v1/users/123 Content-Type: application/json{"data": {"id": 123,"name": "John Doe","email": "john@example.com","created_at": "2023-10-27T08:00:00Z"} }
总结:最佳实践清单
URI 用名词,不用动词。
HTTP 方法用对(GET查,POST增,PUT改,DELETE删)。
返回恰当的状态码。
数据格式用 JSON。
API 版本化。
API 是无状态的。
提供过滤、排序、分页。
使用 HTTPS 和认证。
清晰的错误信息。
良好的文档! 这是最重要的实践之一,可以使用 Swagger/OpenAPI 等工具自动生成。