溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么用Java設計一個短鏈接生成系統

發布時間:2021-12-11 15:47:49 來源:億速云 閱讀:431 作者:iii 欄目:開發技術
# 怎么用Java設計一個短鏈接生成系統

## 目錄
1. [系統概述](#系統概述)
2. [核心功能需求](#核心功能需求)
3. [技術選型](#技術選型)
4. [數據庫設計](#數據庫設計)
5. [核心算法實現](#核心算法實現)
6. [系統架構設計](#系統架構設計)
7. [詳細代碼實現](#詳細代碼實現)
8. [性能優化](#性能優化)
9. [安全考慮](#安全考慮)
10. [擴展功能](#擴展功能)

---

## 系統概述
短鏈接系統是將長URL轉換為短字符串的服務(如bit.ly/abc123),具有:
- 節省字符空間(短信/社交媒體場景)
- 便于統計訪問數據
- 隱藏原始URL等優勢

典型技術指標要求:
- 每秒千級寫入能力
- 毫秒級響應時間
- 99.9%可用性

---

## 核心功能需求
| 功能模塊       | 詳細說明                                                                 |
|----------------|--------------------------------------------------------------------------|
| URL縮短        | 將長URL轉換為6-8字符的短碼                                               |
| URL重定向      | 訪問短鏈接時302跳轉到原始URL                                             |
| 自定義短碼     | 允許用戶指定特定短碼(需校驗唯一性)                                      |
| 訪問統計       | 記錄訪問時間、IP、UserAgent等信息                                        |
| 有效期控制     | 支持設置永久/臨時鏈接                                                    |

---

## 技術選型
```mermaid
graph TD
    A[Spring Boot] --> B[Web MVC]
    A --> C[Spring Data JPA]
    D[Redis] --> E[緩存熱點數據]
    F[MySQL] --> G[持久化存儲]
    H[Zookeeper] --> I[分布式ID生成]

選型理由: - Spring Boot:快速構建RESTful服務 - Redis:應對高并發查詢(10萬+ QPS) - MySQL:可靠持久化存儲 - Zookeeper:分布式環境協調


數據庫設計

主要表結構

CREATE TABLE `short_url` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `short_code` varchar(8) NOT NULL UNIQUE,
  `original_url` varchar(2048) NOT NULL,
  `create_time` datetime NOT NULL,
  `expire_time` datetime DEFAULT NULL,
  `creator_ip` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`),
  INDEX `idx_short_code` (`short_code`)
);

CREATE TABLE `access_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `short_code` varchar(8) NOT NULL,
  `access_time` datetime NOT NULL,
  `user_agent` varchar(512) DEFAULT NULL,
  `ip_address` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id`),
  INDEX `idx_code_time` (`short_code`, `access_time`)
);

核心算法實現

短碼生成方案對比

方案 優點 缺點
自增ID+Base62 無碰撞風險 需暴露數字ID
Hash算法 分布式友好 可能沖突(需解決碰撞)
預生成池 高性能 需要維護池狀態

推薦實現

// Base62編碼示例
public class Base62Encoder {
    private static final String CHARACTERS = 
        "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    
    public static String encode(long num) {
        StringBuilder sb = new StringBuilder();
        while (num > 0) {
            sb.insert(0, CHARACTERS.charAt((int)(num % 62)));
            num /= 62;
        }
        return sb.toString();
    }
}

// 使用Snowflake生成分布式ID
public class ShortCodeGenerator {
    public String generate() {
        long id = Snowflake.nextId(); // 分布式ID
        return Base62Encoder.encode(id);
    }
}

系統架構設計

sequenceDiagram
    participant Client
    participant API
    participant Cache
    participant DB
    
    Client->>API: POST /api/shorten (原始URL)
    API->>DB: 保存映射關系
    DB-->>API: 返回短碼
    API->>Cache: 寫入緩存
    API-->>Client: 返回短鏈接
    
    Client->>API: GET /s/短碼
    API->>Cache: 查詢原始URL
    alt 緩存命中
        Cache-->>API: 返回URL
    else 緩存未命中
        API->>DB: 查詢原始URL
        DB-->>API: 返回URL
        API->>Cache: 回填緩存
    end
    API-->>Client: 302重定向

詳細代碼實現

1. 控制器層

@RestController
@RequestMapping("/api")
public class ShortUrlController {
    
    @Autowired
    private ShortUrlService service;

    @PostMapping("/shorten")
    public ResponseEntity<ShortUrlResponse> createShortUrl(
            @RequestBody ShortenRequest request) {
        
        String shortCode = service.createShortUrl(
            request.getUrl(), 
            request.getCustomCode());
        
        return ResponseEntity.ok(
            new ShortUrlResponse(shortCode));
    }

    @GetMapping("/s/{code}")
    public void redirect(
            @PathVariable String code, 
            HttpServletResponse response) throws IOException {
        
        String originalUrl = service.getOriginalUrl(code);
        response.sendRedirect(originalUrl);
    }
}

2. 服務層關鍵邏輯

@Service
public class ShortUrlServiceImpl implements ShortUrlService {
    
    @Autowired
    private ShortUrlRepository repository;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String CACHE_PREFIX = "short_url:";
    private static final int MAX_RETRY = 3;

    @Override
    @Transactional
    public String createShortUrl(String originalUrl, String customCode) {
        // 校驗URL合法性
        validateUrl(originalUrl);
        
        String shortCode;
        if (StringUtils.isNotBlank(customCode)) {
            // 自定義短碼處理
            if (repository.existsByShortCode(customCode)) {
                throw new BusinessException("短碼已被占用");
            }
            shortCode = customCode;
        } else {
            // 自動生成短碼(帶重試機制)
            int retryCount = 0;
            do {
                shortCode = ShortCodeGenerator.generate();
                retryCount++;
            } while (repository.existsByShortCode(shortCode) 
                    && retryCount < MAX_RETRY);
        }
        
        // 持久化存儲
        ShortUrl entity = new ShortUrl();
        entity.setOriginalUrl(originalUrl);
        entity.setShortCode(shortCode);
        entity.setCreateTime(LocalDateTime.now());
        repository.save(entity);
        
        // 寫入緩存
        redisTemplate.opsForValue().set(
            CACHE_PREFIX + shortCode, 
            originalUrl, 
            7, TimeUnit.DAYS);
        
        return shortCode;
    }
}

性能優化

  1. 緩存策略

    • 熱點數據永不過期
    • LRU緩存淘汰策略
    // Spring Cache配置示例
    @Configuration
    @EnableCaching
    public class CacheConfig {
       @Bean
       public CacheManager cacheManager() {
           return new RedisCacheManager(
               RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory()),
               RedisCacheConfiguration.defaultCacheConfig()
                   .entryTtl(Duration.ofHours(1))
                   .disableCachingNullValues()
           );
       }
    }
    
  2. 批量處理

    // 使用Spring Batch進行日志批量插入
    @Bean
    public JdbcBatchItemWriter<AccessLog> logWriter() {
       return new JdbcBatchItemWriterBuilder<AccessLog>()
           .sql("INSERT INTO access_log VALUES (...)")
           .dataSource(dataSource)
           .build();
    }
    

安全考慮

  1. 防護措施
    • URL黑名單過濾(釣魚網站)
    • 頻率限制(Guava RateLimiter)
    ”`java private final RateLimiter limiter = RateLimiter.create(100.0); // 100QPS

@GetMapping(“/s/{code}”) public ResponseEntity<?> redirect(…) { if (!limiter.tryAcquire()) { throw new TooManyRequestsException(); } // … }


2. **敏感操作審計**:
   ```java
   @Aspect
   @Component
   public class AuditAspect {
       @AfterReturning("execution(* com..ShortUrlService.create*(..))")
       public void auditLog(JoinPoint jp) {
           // 記錄操作日志
       }
   }

擴展功能

  1. 可視化面板

    // 使用ECharts展示訪問趨勢
    myChart.setOption({
       xAxis: { data: ['Mon', 'Tue', 'Wed'] },
       series: [{ data: [120, 200, 150] }]
    });
    
  2. API限流方案對比

    方案 實現復雜度 精確度
    令牌桶
    固定窗口
    滑動日志 極高

最佳實踐建議: 1. 生產環境建議使用分布式Redis集群 2. 短碼長度建議6-8字符(62^6≈568億組合) 3. 重要業務鏈接建議使用HTTPS 4. 定期歸檔冷數據到對象存儲 “`

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女