跳到主要内容

API 参考文档 (API Reference)

本文档提供文章模块所有REST API的完整说明,包括请求参数、响应格式和错误处理。


📋 目录


用户端API (Art icleController)

基础路径: /api/v1/articles

权限: 公开(部分需要登录)

GET /api/v1/articles

说明: 分页查询文章列表

请求参数:

参数类型必填说明示例
pageInteger页码(从1开始)1
sizeInteger每页数量(默认10,最大100)20
categoryIdLong分类ID筛选1234567890123456789
keywordString关键词搜索(标题/摘要)"Spring Boot"

请求示例:

curl -X GET "http://localhost:8080/api/v1/articles?page=1&size=10&categoryId=1234567890123456789"

响应示例:

{
"code": 200,
"message": "操作成功",
"data": {
"records": [
{
"id": "1234567890123456789",
"title": "MySQL 9.4 向量搜索实战",
"summary": "深入探讨 MySQL 9.4 的 VECTOR 类型...",
"coverImage": "https://example.com/cover.jpg",
"authorId": "9876543210987654321",
"categoryId": "1111111111111111111",
"publishTime": "2024-01-15T10:30:00",
"isTop": 0
}
],
"total": 100,
"page": 1,
"size": 10,
"pages": 10
}
}

GET /api/v1/articles/{id}

说明: 查询文章详情(包含完整内容)

路径参数:

参数类型说明
idLong文章ID

请求示例:

curl -X GET "http://localhost:8080/api/v1/articles/1234567890123456789"

响应示例:

{
"code": 200,
"message": "操作成功",
"data": {
"id": "1234567890123456789",
"title": "MySQL 9.4 向量搜索实战",
"content": "# 引言\n\nMySQL 9.4引入了VECTOR类型...",
"contentHtml": "<h1>引言</h1><p>MySQL 9.4引入了VECTOR类型...</p>",
"summary": "深入探讨 MySQL 9.4 的 VECTOR 类型",
"coverImage": "https://example.com/cover.jpg",
"authorId": "9876543210987654321",
"categoryId": "1111111111111111111",
"status": 1,
"isTop": 0,
"isFeatured": 1,
"isCommentDisabled": 0,
"publishTime": "2024-01-15T10:30:00",
"tocJson": "[{\"level\":1,\"title\":\"引言\"}]",
"createTime": "2024-01-10T08:00:00",
"updateTime": "2024-01-15T10:30:00"
}
}

GET /api/v1/articles/{id}/related

说明: 获取相关文章推荐(基于向量搜索)

路径参数:

参数类型说明
idLong文章ID

查询参数:

参数类型必填说明默认值
limitInteger推荐数量5

推荐策略:

  1. Level 1: 向量相似度搜索(COSINE_DISTANCE)
  2. ⬇️ Level 2: 同分类文章(categoryId相同)
  3. ⬇️ Level 3: 最新发布文章(保底)

请求示例:

curl -X GET "http://localhost:8080/api/v1/articles/1234567890123456789/related?limit=5"

响应示例:

{
"code": 200,
"message": "操作成功",
"data": [
{
"id": "2222222222222222222",
"title": "PostgreSQL vs MySQL 向量搜索对比",
"summary": "两大数据库向量搜索能力横评",
"coverImage": "https://example.com/cover2.jpg",
"publishTime": "2024-01-20T14:00:00"
},
{
"id": "3333333333333333333",
"title": "向量数据库性能优化指南",
"summary": "从索引到查询的全方位优化",
"coverImage": "https://example.com/cover3.jpg",
"publishTime": "2024-01-18T09:30:00"
}
]
}

COSINE_DISTANCE 说明:

  • 值域: [0, 2]
  • 0 = 完全相同
  • 1 = 正交(无关)
  • 2 = 完全相反
  • 查询按距离升序排列(越小越相似)

🏷️ 分类API (CategoryController)

基础路径: /api/v1/categories

权限: 公开(只读)

GET /api/v1/categories/tree

说明: 获取分类树结构

请求示例:

curl -X GET "http://localhost:8080/api/v1/categories/tree"

响应示例:

{
"code": "200",
"message": "success",
"data": [
{
"id": "1111111111111111111",
"name": "技术",
"slug": "tech",
"description": "技术相关文章",
"sortOrder": 1,
"articleCount": 25,
"parentId": null,
"children": [
{
"id": "2222222222222222222",
"name": "后端开发",
"slug": "backend",
"description": "后端技术栈",
"sortOrder": 1,
"articleCount": 15,
"parentId": "1111111111111111111",
"children": []
}
]
}
]
}

GET /api/v1/categories

说明: 获取扁平分类列表(按排序权重升序)

请求示例:

curl -X GET "http://localhost:8080/api/v1/categories"

响应示例:

{
"code": "200",
"message": "success",
"data": [
{
"id": "1111111111111111111",
"name": "技术",
"slug": "tech",
"description": "技术相关文章",
"sortOrder": 1,
"articleCount": 25,
"parentId": null
},
{
"id": "2222222222222222222",
"name": "后端开发",
"slug": "backend",
"description": "后端技术栈",
"sortOrder": 1,
"articleCount": 15,
"parentId": "1111111111111111111"
}
]
}

GET /api/v1/categories/slug/{slug}

说明: 根据 slug 获取分类详情

路径参数:

参数类型说明
slugString分类 URL slug

请求示例:

curl -X GET "http://localhost:8080/api/v1/categories/slug/backend"

响应示例:

{
"code": "200",
"message": "success",
"data": {
"id": "2222222222222222222",
"name": "后端开发",
"slug": "backend",
"description": "后端技术栈",
"sortOrder": 1,
"articleCount": 15,
"parentId": "1111111111111111111"
}
}

错误响应 (分类不存在):

{
"code": "404",
"message": "分类不存在",
"data": null
}

🔖 标签API (TagController)

基础路径: /api/v1/tags

权限: 公开(只读)

GET /api/v1/tags

说明: 获取标签列表(支持排序和数量限制)

查询参数:

参数类型必填说明默认值可选值
orderByString排序方式article_countarticle_count, create_time, name
limitInteger限制数量无限制1-100

请求示例:

# 获取所有标签(按文章数量排序)
curl -X GET "http://localhost:8080/api/v1/tags?orderBy=article_count"

# 获取前20个热门标签
curl -X GET "http://localhost:8080/api/v1/tags?orderBy=article_count&limit=20"

# 按名称排序
curl -X GET "http://localhost:8080/api/v1/tags?orderBy=name"

# 按创建时间倒序
curl -X GET "http://localhost:8080/api/v1/tags?orderBy=create_time"

响应示例:

{
"code": "200",
"message": "success",
"data": [
{
"id": "3333333333333333333",
"name": "Spring Boot",
"slug": "spring-boot",
"color": "#6db33f",
"articleCount": 42
},
{
"id": "4444444444444444444",
"name": "Java",
"slug": "java",
"color": "#007396",
"articleCount": 38
}
]
}

GET /api/v1/tags/hot

说明: 获取热门标签(按文章数量倒序)

查询参数:

参数类型必填说明默认值
limitInteger数量限制10

请求示例:

curl -X GET "http://localhost:8080/api/v1/tags/hot?limit=10"

响应示例:

{
"code": "200",
"message": "success",
"data": [
{
"id": "3333333333333333333",
"name": "Spring Boot",
"slug": "spring-boot",
"color": "#6db33f",
"articleCount": 42
},
{
"id": "4444444444444444444",
"name": "Java",
"slug": "java",
"color": "#007396",
"articleCount": 38
}
]
}

GET /api/v1/tags/slug/{slug}

说明: 根据 slug 获取标签详情

路径参数:

参数类型说明
slugString标签 URL slug

请求示例:

curl -X GET "http://localhost:8080/api/v1/tags/slug/spring-boot"

响应示例:

{
"code": "200",
"message": "success",
"data": {
"id": "3333333333333333333",
"name": "Spring Boot",
"slug": "spring-boot",
"color": "#6db33f",
"articleCount": 42
}
}

错误响应 (标签不存在):

{
"code": "404",
"message": "标签不存在",
"data": null
}

管理端API (ArticleAdminController)

基础路径: /api/v1/admin/articles

权限: 需要 ROLE_ADMIN 权限

请求头:

Authorization: Bearer YOUR_JWT_TOKEN

POST /api/v1/admin/articles

说明: 创建文章(默认草稿状态)

请求体:

{
"title": "文章标题",
"content": "# Markdown 内容\n\n正文...",
"summary": "文章摘要(可选,不填会自动提取)",
"coverImage": "https://example.com/cover.jpg",
"categoryId": "1111111111111111111",
"tagIds": ["2222222222222222222", "3333333333333333333"],
"isTop": 0,
"isFeatured": 1,
"isCommentDisabled": 0
}

字段说明:

字段类型必填说明默认值
titleString标题(1-200字符)-
contentStringMarkdown内容-
summaryString摘要(最多500字符)自动提取
coverImageString封面图URLnull
categoryIdLong分类IDnull
tagIdsLong[]标签ID数组[]
isTopInteger是否置顶0
isFeaturedInteger是否精选0
isCommentDisabledInteger是否禁用评论0

响应示例:

{
"code": 200,
"message": "创建成功",
"data": "1234567890123456789"
}

后台处理流程:

  1. ✅ 参数校验(title/content必填)
  2. XSS过滤 - 防止脚本注入
  3. Markdown解析 - 转换为HTML
  4. TOC生成 - 提取标题结构
  5. 摘要提取 - 自动生成(如未提供)
  6. ✅ 保存到数据库(status=0草稿)

PUT /api/v1/admin/articles/{id}

说明: 更新文章

路径参数:

参数类型说明
idLong文章ID

请求体: 同创建接口

响应示例:

{
"code": 200,
"message": "更新成功",
"data": true
}

PUT /api/v1/admin/articles/{id}/publish

说明: 发布文章

前置条件: status = DRAFT (0)

状态变更: DRAFT → PUBLISHED

触发事件: ArticlePublishedEvent

路径参数:

参数类型说明
idLong文章ID

请求示例:

curl -X PUT "http://localhost:8080/api/v1/admin/articles/1234567890123456789/publish" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"

响应示例:

{
"code": 200,
"message": "发布成功",
"data": null
}

后台处理流程:

  1. ✅ 验证状态(必须是草稿)
  2. ✅ 更新状态为 PUBLISHED
  3. ✅ 设置发布时间
  4. ✅ 发布 ArticlePublishedEvent
  5. 异步处理 (不阻塞响应):
    • 清理缓存
    • 初始化统计
    • 生成向量 (Embedding)
    • 发送通知

PUT /api/v1/admin/articles/{id}/archive

说明: 归档文章

前置条件: status = PUBLISHED (1)

状态变更: PUBLISHED → ARCHIVED

请求示例:

curl -X PUT "http://localhost:8080/api/v1/admin/articles/1234567890123456789/archive" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"

响应示例:

{
"code": 200,
"message": "归档成功",
"data": null
}

PUT /api/v1/admin/articles/{id}/unarchive

说明: 恢复归档文章

前置条件: status = ARCHIVED (2)

状态变更: ARCHIVED → PUBLISHED

请求示例:

curl -X PUT "http://localhost:8080/api/v1/admin/articles/1234567890123456789/unarchive" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"

响应示例:

{
"code": 200,
"message": "恢复成功",
"data": null
}

DELETE /api/v1/admin/articles/{id}

说明: 删除文章(逻辑删除)

前置条件: 任何状态都可删除

逻辑删除: is_deleted = 0 → 1 (软删除)

请求示例:

curl -X DELETE "http://localhost:8080/api/v1/admin/articles/1234567890123456789" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"

响应示例:

{
"code": 200,
"message": "删除成功",
"data": true
}

通用响应格式

所有API遵循统一的响应格式:

{
"code": 200, // HTTP状态码
"message": "操作成功", // 提示信息
"data": { ... } // 业务数据
}

成功响应

状态码说明
200操作成功
201创建成功

错误响应

状态码说明示例
400参数错误title不能为空
401未登录Token缺失或过期
403权限不足需要ADMIN角色
404资源不存在文章不存在
409业务冲突草稿不能归档
500服务器错误系统异常

错误响应示例:

{
"code": 400,
"message": "参数错误:title不能为空",
"data": null
}

错误码说明

通用错误码 (System)

错误码HTTP状态说明
PARAM_ERROR400参数校验失败
UNAUTHORIZED401未登录或Token过期
ACCESS_DENIED403无权限访问
NOT_FOUND404资源不存在
INVALID_OPERATION409非法操作(如草稿归档)
SYSTEM_ERROR500系统内部错误

业务错误码 (Article)

错误码说明示例场景
ARTICLE_NOT_FOUND文章不存在查询不存在的ID
ARTICLE_STATUS_INVALID文章状态不允许此操作草稿不能归档
ARTICLE_ALREADY_PUBLISHED文章已发布重复发布
ARTICLE_ALREADY_ARCHIVED文章已归档重复归档

错误响应示例:

{
"code": 409,
"message": "业务冲突:草稿不能归档",
"data": null,
"errorCode": "ARTICLE_STATUS_INVALID"
}

🔒 权限说明

用户端 (公开)

文章接口:

  • GET /api/v1/articles - 匿名可访问
  • GET /api/v1/articles/{id} - 匿名可访问
  • GET /api/v1/articles/{id}/related - 匿名可访问

分类接口:

  • GET /api/v1/categories/tree - 匿名可访问
  • GET /api/v1/categories - 匿名可访问
  • GET /api/v1/categories/slug/{slug} - 匿名可访问

标签接口:

  • GET /api/v1/tags - 匿名可访问
  • GET /api/v1/tags/hot - 匿名可访问
  • GET /api/v1/tags/slug/{slug} - 匿名可访问

管理端 (需要登录 + ADMIN角色)

  • 🔐 POST /api/v1/admin/articles - 需要 ROLE_ADMIN
  • 🔐 PUT /api/v1/admin/articles/{id} - 需要 ROLE_ADMIN
  • 🔐 PUT /api/v1/admin/articles/{id}/publish - 需要 ROLE_ADMIN
  • 🔐 PUT /api/v1/admin/articles/{id}/archive - 需要 ROLE_ADMIN
  • 🔐 PUT /api/v1/admin/articles/{id}/unarchive - 需要 ROLE_ADMIN
  • 🔐 DELETE /api/v1/admin/articles/{id} - 需要 ROLE_ADMIN

Token获取: 参考 认证文档


📊 字段类型说明

ArticleStatus (文章状态)

枚举说明允许操作
0DRAFT草稿发布、删除
1PUBLISHED已发布归档、删除
2ARCHIVED已归档恢复、删除

布尔字段

字段类型说明值域
isTopInteger是否置顶0=否 1=是
isFeaturedInteger是否精选0=否 1=是
isCommentDisabledInteger是否禁用评论0=否 1=是

🎯 最佳实践

1. 文章发布流程(推荐)

# Step 1: 创建草稿
curl -X POST /api/v1/admin/articles \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "标题",
"content": "# 内容"
}'

# 响应: {"data": "1234567890123456789"}

# Step 2: 预览(可选)
curl -X GET /api/v1/articles/1234567890123456789

# Step 3: 发布
curl -X PUT /api/v1/admin/articles/1234567890123456789/publish \
-H "Authorization: Bearer $TOKEN"

# Step 4: 验证相关推荐
curl -X GET /api/v1/articles/1234567890123456789/related?limit=5

2. 避免重复请求

使用乐观锁:

// ArticleEntity 自动包含 version 字段
@Version
private Integer version; // 每次更新自动+1

// 并发更新时,version不匹配会抛出 OptimisticLockException

3. 性能优化建议

  • ✅ 使用分页查询(避免一次加载所有文章)
  • ✅ 缓存文章详情(Redis,TTL 30分钟)
  • ✅ 缓存相关推荐(向量搜索较慢)
  • ✅ 定时预热热门文章

🔗 相关文档

需要更多帮助? 访问 Swagger UI 在线测试API。