|
| 1 | +# 短链API |
| 2 | + |
| 3 | +<cite> |
| 4 | +**本文档引用文件** |
| 5 | +- [ShortUrlController.java](file://src/main/java/com/layor/tinyflow/Controller/ShortUrlController.java) |
| 6 | +- [ShortenRequest.java](file://src/main/java/com/layor/tinyflow/entity/ShortenRequest.java) |
| 7 | +- [ShortUrlDTO.java](file://src/main/java/com/layor/tinyflow/entity/ShortUrlDTO.java) |
| 8 | +- [UrlListResponseDTO.java](file://src/main/java/com/layor/tinyflow/entity/UrlListResponseDTO.java) |
| 9 | +- [Result.java](file://src/main/java/com/layor/tinyflow/entity/Result.java) |
| 10 | +- [ShortUrlService.java](file://src/main/java/com/layor/tinyflow/service/ShortUrlService.java) |
| 11 | +- [shortener-core.md](file://web/docs/shortener-core.md) |
| 12 | +- [ShortenerForm.vue](file://web/src/components/ShortenerForm.vue) |
| 13 | +- [application.yml](file://src/main/resources/application.yml) |
| 14 | +</cite> |
| 15 | + |
| 16 | +## 目录 |
| 17 | +1. [简介](#简介) |
| 18 | +2. [核心API端点](#核心api端点) |
| 19 | +3. [请求与响应结构](#请求与响应结构) |
| 20 | +4. [短码生成与缓存机制](#短码生成与缓存机制) |
| 21 | +5. [限流与高可用策略](#限流与高可用策略) |
| 22 | +6. [前端集成示例](#前端集成示例) |
| 23 | +7. [错误模型与状态码](#错误模型与状态码) |
| 24 | + |
| 25 | +## 简介 |
| 26 | +TinyFlow短链服务提供高并发、高可用的短链创建与跳转功能。本API文档详细说明了`ShortUrlController`中实现的核心端点,包括短链创建、列表获取和跳转重定向。系统结合了本地缓存(Caffeine)、分布式缓存(Redis)和熔断降级机制,确保在高负载下的稳定性和低延迟。 |
| 27 | + |
| 28 | +**Section sources** |
| 29 | +- [shortener-core.md](file://web/docs/shortener-core.md#L1-L155) |
| 30 | + |
| 31 | +## 核心API端点 |
| 32 | + |
| 33 | +### 创建短链(POST /api/shorten) |
| 34 | +用于将长链接转换为短链接。 |
| 35 | + |
| 36 | +- **HTTP方法**: `POST` |
| 37 | +- **URL路径**: `/api/shorten` |
| 38 | +- **请求头**: `Content-Type: application/json;charset=utf-8` |
| 39 | +- **成功响应**: HTTP 200 |
| 40 | +- **失败响应**: 400(参数错误)、409(别名冲突)、500(服务器错误) |
| 41 | + |
| 42 | +### 获取短链列表(GET /api/urls) |
| 43 | +获取当前用户创建的所有短链及其统计信息。 |
| 44 | + |
| 45 | +- **HTTP方法**: `GET` |
| 46 | +- **URL路径**: `/api/urls` |
| 47 | +- **分页参数**: 支持标准分页(page, size) |
| 48 | +- **成功响应**: HTTP 200 |
| 49 | +- **失败响应**: 500(服务器错误) |
| 50 | + |
| 51 | +### 短链跳转(GET /r/{code}) |
| 52 | +通过短码进行302重定向到原始长链接。 |
| 53 | + |
| 54 | +- **HTTP方法**: `GET` |
| 55 | +- **URL路径**: `/r/{code}` |
| 56 | +- **行为**: 302重定向,设置`Location`头 |
| 57 | +- **成功响应**: HTTP 302 |
| 58 | +- **失败响应**: 404(未找到)、429(限流) |
| 59 | + |
| 60 | +**Section sources** |
| 61 | +- [ShortUrlController.java](file://src/main/java/com/layor/tinyflow/Controller/ShortUrlController.java#L24-L81) |
| 62 | + |
| 63 | +## 请求与响应结构 |
| 64 | + |
| 65 | +### 请求体结构(ShortenRequest) |
| 66 | +| 字段名 | 类型 | 是否必填 | 说明 | |
| 67 | +|--------|------|----------|------| |
| 68 | +| longUrl | string | 是 | 原始长链接,必须以http://或https://开头 | |
| 69 | +| customAlias | string | 否 | 自定义短码,支持中文,若已存在则返回409冲突 | |
| 70 | + |
| 71 | +```mermaid |
| 72 | +classDiagram |
| 73 | +class ShortenRequest { |
| 74 | ++String longUrl |
| 75 | ++String customAlias |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +**Diagram sources** |
| 80 | +- [ShortenRequest.java](file://src/main/java/com/layor/tinyflow/entity/ShortenRequest.java#L8-L17) |
| 81 | + |
| 82 | +### 响应体结构 |
| 83 | +#### 创建短链响应(Result<ShortUrlDTO>) |
| 84 | + |
| 85 | +```mermaid |
| 86 | +classDiagram |
| 87 | +class Result~T~ { |
| 88 | ++int code |
| 89 | ++String message |
| 90 | ++T data |
| 91 | ++boolean success |
| 92 | ++static <T> Result<T> success(T data) |
| 93 | ++static <T> Result<T> error(int code, String message) |
| 94 | +} |
| 95 | +class ShortUrlDTO { |
| 96 | ++String shortCode |
| 97 | ++String shortUrl |
| 98 | ++String longUrl |
| 99 | ++LocalDateTime createdAt |
| 100 | +} |
| 101 | +Result --> ShortUrlDTO : "泛型" |
| 102 | +``` |
| 103 | + |
| 104 | +**Diagram sources** |
| 105 | +- [Result.java](file://src/main/java/com/layor/tinyflow/entity/Result.java#L11-L34) |
| 106 | +- [ShortUrlDTO.java](file://src/main/java/com/layor/tinyflow/entity/ShortUrlDTO.java#L11-L16) |
| 107 | + |
| 108 | +#### 获取短链列表响应(Result<PageResponseDTO<UrlListResponseDTO>>) |
| 109 | + |
| 110 | +```mermaid |
| 111 | +classDiagram |
| 112 | +class UrlListResponseDTO { |
| 113 | ++String shortCode |
| 114 | ++String longUrl |
| 115 | ++Long totalVisits |
| 116 | ++Integer todayVisits |
| 117 | ++LocalDateTime createdAt |
| 118 | +} |
| 119 | +class PageResponseDTO~T~ { |
| 120 | ++T[] content |
| 121 | ++long totalElements |
| 122 | ++int totalPages |
| 123 | ++int size |
| 124 | ++int number |
| 125 | ++boolean first |
| 126 | ++boolean last |
| 127 | ++boolean empty |
| 128 | +} |
| 129 | +Result --> PageResponseDTO : "data" |
| 130 | +PageResponseDTO --> UrlListResponseDTO : "content" |
| 131 | +``` |
| 132 | + |
| 133 | +**Diagram sources** |
| 134 | +- [UrlListResponseDTO.java](file://src/main/java/com/layor/tinyflow/entity/UrlListResponseDTO.java#L10-L17) |
| 135 | +- [PageResponseDTO.java](file://src/main/java/com/layor/tinyflow/entity/PageResponseDTO.java) |
| 136 | + |
| 137 | +**Section sources** |
| 138 | +- [ShortUrlController.java](file://src/main/java/com/layor/tinyflow/Controller/ShortUrlController.java#L46-L68) |
| 139 | + |
| 140 | +## 短码生成与缓存机制 |
| 141 | + |
| 142 | +### 短码生成策略 |
| 143 | +- **自定义优先**: 用户可指定`customAlias`,系统会校验其唯一性。 |
| 144 | +- **自动生成**: 若未指定别名,使用`HashidsStrategy`基于ID生成6位Base62短码。 |
| 145 | +- **冲突处理**: 生成时检查数据库,若冲突则重试最多3次,失败则抛出异常。 |
| 146 | + |
| 147 | +### 多级缓存架构 |
| 148 | +系统采用L1-L2-L3三级缓存架构,显著提升读取性能: |
| 149 | + |
| 150 | +```mermaid |
| 151 | +flowchart TD |
| 152 | +A["/r/{code} 请求"] --> B{L1: Caffeine<br/>本地缓存} |
| 153 | +B --> |命中| C[返回长链接] |
| 154 | +B --> |未命中| D{L2: Redis<br/>分布式缓存} |
| 155 | +D --> |命中| E[回填L1<br/>返回长链接] |
| 156 | +D --> |未命中| F{L3: 数据库} |
| 157 | +F --> |找到| G[回填L2和L1<br/>返回长链接] |
| 158 | +F --> |未找到| H[返回404] |
| 159 | +``` |
| 160 | + |
| 161 | +**Diagram sources** |
| 162 | +- [ShortUrlService.java](file://src/main/java/com/layor/tinyflow/service/ShortUrlService.java#L304-L353) |
| 163 | +- [CacheConfig.java](file://src/main/java/com/layor/tinyflow/config/CacheConfig.java) |
| 164 | + |
| 165 | +**Section sources** |
| 166 | +- [shortener-core.md](file://web/docs/shortener-core.md#L82-L90) |
| 167 | +- [application.yml](file://src/main/resources/application.yml#L141-L147) |
| 168 | + |
| 169 | +## 限流与高可用策略 |
| 170 | + |
| 171 | +### IP维度限流 |
| 172 | +`/r/{code}`端点应用了令牌桶限流,防止恶意刷量。 |
| 173 | + |
| 174 | +```mermaid |
| 175 | +sequenceDiagram |
| 176 | +participant Client as "客户端" |
| 177 | +participant RateLimiter as "限流器" |
| 178 | +participant Service as "短链服务" |
| 179 | +Client->>RateLimiter : 请求 /r/abc123 |
| 180 | +RateLimiter->>RateLimiter : 检查令牌 |
| 181 | +alt 令牌充足 |
| 182 | +RateLimiter->>Service : 转发请求 |
| 183 | +Service->>Service : 执行重定向 |
| 184 | +Service-->>Client : 302 Location : longUrl |
| 185 | +else 令牌不足 |
| 186 | +RateLimiter-->>Client : 429 Too Many Requests |
| 187 | +end |
| 188 | +``` |
| 189 | + |
| 190 | +**Diagram sources** |
| 191 | +- [ShortUrlService.java](file://src/main/java/com/layor/tinyflow/service/ShortUrlService.java#L288-L290) |
| 192 | +- [application.yml](file://src/main/resources/application.yml#L149-L155) |
| 193 | + |
| 194 | +### 熔断与降级 |
| 195 | +当Redis服务不可用时,系统自动降级到数据库查询,保证核心功能可用。 |
| 196 | + |
| 197 | +```mermaid |
| 198 | +stateDiagram-v2 |
| 199 | +[*] --> Closed |
| 200 | +Closed --> Open : "失败率 > 50%" |
| 201 | +Open --> HalfOpen : "等待30s" |
| 202 | +HalfOpen --> Closed : "半开状态下调用成功" |
| 203 | +HalfOpen --> Open : "半开状态下调用失败" |
| 204 | +``` |
| 205 | + |
| 206 | +**Diagram sources** |
| 207 | +- [ShortUrlService.java](file://src/main/java/com/layor/tinyflow/service/ShortUrlService.java#L302-L304) |
| 208 | +- [application.yml](file://src/main/resources/application.yml#L156-L176) |
| 209 | + |
| 210 | +**Section sources** |
| 211 | +- [shortener-core.md](file://web/docs/shortener-core.md#L93-L97) |
| 212 | + |
| 213 | +## 前端集成示例 |
| 214 | + |
| 215 | +### curl命令示例 |
| 216 | +创建一个带自定义别名的短链: |
| 217 | + |
| 218 | +```bash |
| 219 | +curl -X POST http://localhost:8080/api/shorten \ |
| 220 | + -H "Content-Type: application/json;charset=utf-8" \ |
| 221 | + -d '{ |
| 222 | + "longUrl": "https://www.example.com", |
| 223 | + "customAlias": "我的短链" |
| 224 | + }' |
| 225 | +``` |
| 226 | + |
| 227 | +### 前端组件调用 |
| 228 | +`ShortenerForm.vue`组件通过axios调用API: |
| 229 | + |
| 230 | +```mermaid |
| 231 | +sequenceDiagram |
| 232 | +participant User as "用户" |
| 233 | +participant Form as "ShortenerForm.vue" |
| 234 | +participant API as "POST /api/shorten" |
| 235 | +User->>Form : 输入长链接和别名 |
| 236 | +Form->>Form : 校验输入 |
| 237 | +Form->>API : 发送POST请求 |
| 238 | +API-->>Form : 返回Result<ShortUrlDTO> |
| 239 | +Form->>Form : 显示短链和二维码 |
| 240 | +Form-->>User : 展示结果 |
| 241 | +``` |
| 242 | + |
| 243 | +**Diagram sources** |
| 244 | +- [ShortenerForm.vue](file://web/src/components/ShortenerForm.vue#L107-L125) |
| 245 | + |
| 246 | +**Section sources** |
| 247 | +- [ShortenerForm.vue](file://web/src/components/ShortenerForm.vue) |
| 248 | + |
| 249 | +## 错误模型与状态码 |
| 250 | + |
| 251 | +### HTTP状态码 |
| 252 | +| 状态码 | 含义 | 说明 | |
| 253 | +|--------|------|------| |
| 254 | +| 200 | OK | 请求成功 | |
| 255 | +| 302 | Found | 重定向到长链接 | |
| 256 | +| 400 | Bad Request | 参数错误 | |
| 257 | +| 404 | Not Found | 短码不存在 | |
| 258 | +| 409 | Conflict | 自定义别名冲突 | |
| 259 | +| 429 | Too Many Requests | 超过限流阈值 | |
| 260 | +| 500 | Internal Server Error | 服务器内部错误 | |
| 261 | + |
| 262 | +### 通用错误模型 |
| 263 | +```json |
| 264 | +{ |
| 265 | + "code": 1, |
| 266 | + "message": "自定义别名已存在", |
| 267 | + "success": false, |
| 268 | + "data": null |
| 269 | +} |
| 270 | +``` |
| 271 | + |
| 272 | +**Section sources** |
| 273 | +- [shortener-core.md](file://web/docs/shortener-core.md#L70-L78) |
| 274 | +- [Result.java](file://src/main/java/com/layor/tinyflow/entity/Result.java) |
0 commit comments