springboot中縮短一個(gè)url鏈接的實(shí)現(xiàn)
縮短 URL 是現(xiàn)代應(yīng)用程序中常見(jiàn)的需求,通常用于減少長(zhǎng) URL 的長(zhǎng)度,使其更易于分享。URL 縮短服務(wù)的核心思路是將長(zhǎng) URL 映射到一個(gè)唯一的短代碼。較為復(fù)雜的場(chǎng)景可能涉及多種功能,例如:
- 縮短的 URL 自動(dòng)過(guò)期(即在一定時(shí)間后失效)。
- 統(tǒng)計(jì) URL 的訪問(wèn)量。
- 檢查并避免短 URL 重復(fù)。
- 添加安全機(jī)制,如防止惡意鏈接。
場(chǎng)景案例
我們可以設(shè)計(jì)一個(gè)場(chǎng)景:
- 用戶通過(guò) API 提交長(zhǎng) URL。
- 系統(tǒng)生成短 URL,短 URL 有有效期(例如 7 天),并存儲(chǔ)在數(shù)據(jù)庫(kù)中。
- 用戶可以通過(guò) API 查詢短 URL 的訪問(wèn)次數(shù)。
- 每當(dāng)有人訪問(wèn)短 URL,系統(tǒng)會(huì)記錄訪問(wèn)量,并自動(dòng)重定向到原始的長(zhǎng) URL。
- 在短 URL 過(guò)期后,無(wú)法再進(jìn)行重定向。
技術(shù)棧
- Spring Boot: 用于快速構(gòu)建 RESTful API 服務(wù)。
- H2 數(shù)據(jù)庫(kù): 用于存儲(chǔ) URL 和相關(guān)元數(shù)據(jù)。
- Java UUID: 生成唯一短碼。
- Java 定時(shí)任務(wù): 自動(dòng)清理過(guò)期 URL。
Step 1: 項(xiàng)目結(jié)構(gòu)
src/ ├── main/ │ ├── java/ │ │ └── com/ │ │ └── example/ │ │ ├── UrlShortenerApplication.java │ │ ├── controller/ │ │ │ └── UrlController.java │ │ ├── model/ │ │ │ └── Url.java │ │ ├── repository/ │ │ │ └── UrlRepository.java │ │ └── service/ │ │ └── UrlService.java │ └── resources/ │ └── application.properties
Step 2: 創(chuàng)建實(shí)體類 Url
Url.java 是用于存儲(chǔ)長(zhǎng) URL、短 URL 以及相關(guān)元數(shù)據(jù)的實(shí)體類。
package com.example.model;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
public class Url {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String originalUrl;
private String shortCode;
private LocalDateTime createdAt;
private LocalDateTime expiresAt;
private int visitCount;
public Url() {}
public Url(String originalUrl, String shortCode, LocalDateTime createdAt, LocalDateTime expiresAt) {
this.originalUrl = originalUrl;
this.shortCode = shortCode;
this.createdAt = createdAt;
this.expiresAt = expiresAt;
this.visitCount = 0;
}
// getters and setters
}Step 3: 創(chuàng)建 Repository 接口
使用 Spring Data JPA,我們可以快速創(chuàng)建一個(gè)操作數(shù)據(jù)庫(kù)的接口。
package com.example.repository;
import com.example.model.Url;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UrlRepository extends JpaRepository<Url, Long> {
Optional<Url> findByShortCode(String shortCode);
void deleteByExpiresAtBefore(LocalDateTime dateTime);
}Step 4: 編寫(xiě)服務(wù)類 UrlService
UrlService.java 包含業(yè)務(wù)邏輯,例如生成短 URL、處理 URL 重定向、統(tǒng)計(jì)訪問(wèn)量等。
package com.example.service;
import com.example.model.Url;
import com.example.repository.UrlRepository;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.UUID;
@Service
public class UrlService {
private final UrlRepository urlRepository;
public UrlService(UrlRepository urlRepository) {
this.urlRepository = urlRepository;
}
public String shortenUrl(String originalUrl, int expirationDays) {
String shortCode = UUID.randomUUID().toString().substring(0, 8); // 生成短碼
LocalDateTime createdAt = LocalDateTime.now();
LocalDateTime expiresAt = createdAt.plusDays(expirationDays);
Url url = new Url(originalUrl, shortCode, createdAt, expiresAt);
urlRepository.save(url);
return shortCode;
}
public Optional<Url> getOriginalUrl(String shortCode) {
Optional<Url> urlOptional = urlRepository.findByShortCode(shortCode);
urlOptional.ifPresent(url -> {
if (url.getExpiresAt().isAfter(LocalDateTime.now())) {
url.setVisitCount(url.getVisitCount() + 1);
urlRepository.save(url);
}
});
return urlOptional.filter(url -> url.getExpiresAt().isAfter(LocalDateTime.now()));
}
public int getVisitCount(String shortCode) {
return urlRepository.findByShortCode(shortCode)
.map(Url::getVisitCount)
.orElse(0);
}
// 定時(shí)任務(wù)清理過(guò)期 URL
public void cleanUpExpiredUrls() {
urlRepository.deleteByExpiresAtBefore(LocalDateTime.now());
}
}Step 5: 編寫(xiě) Controller
UrlController.java 是與前端或其他客戶端交互的層。
package com.example.controller;
import com.example.model.Url;
import com.example.service.UrlService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;
@RestController
@RequestMapping("/api/url")
public class UrlController {
private final UrlService urlService;
public UrlController(UrlService urlService) {
this.urlService = urlService;
}
@PostMapping("/shorten")
public ResponseEntity<String> shortenUrl(@RequestParam String originalUrl, @RequestParam(defaultValue = "7") int expirationDays) {
String shortCode = urlService.shortenUrl(originalUrl, expirationDays);
return ResponseEntity.ok("Shortened URL: http://localhost:8080/api/url/" + shortCode);
}
@GetMapping("/{shortCode}")
public ResponseEntity<?> redirectUrl(@PathVariable String shortCode) {
Optional<Url> urlOptional = urlService.getOriginalUrl(shortCode);
return urlOptional
.map(url -> ResponseEntity.status(302).header("Location", url.getOriginalUrl()).build())
.orElse(ResponseEntity.notFound().build());
}
@GetMapping("/{shortCode}/stats")
public ResponseEntity<Integer> getUrlStats(@PathVariable String shortCode) {
int visitCount = urlService.getVisitCount(shortCode);
return ResponseEntity.ok(visitCount);
}
}Step 6: 定時(shí)清理任務(wù)
Spring Boot 可以通過(guò) @Scheduled 注解定期執(zhí)行任務(wù)。我們可以創(chuàng)建一個(gè)任務(wù)來(lái)清理過(guò)期的 URL。
package com.example.service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class CleanupTask {
private final UrlService urlService;
public CleanupTask(UrlService urlService) {
this.urlService = urlService;
}
@Scheduled(cron = "0 0 0 * * ?") // 每天午夜執(zhí)行一次
public void cleanExpiredUrls() {
urlService.cleanUpExpiredUrls();
}
}Step 7: 配置文件
在 application.properties 中配置 H2 數(shù)據(jù)庫(kù)以及其他 Spring Boot 配置。
spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.h2.console.enabled=true spring.jpa.hibernate.ddl-auto=update
Step 8: 啟動(dòng)類 UrlShortenerApplication.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class UrlShortenerApplication {
public static void main(String[] args) {
SpringApplication.run(UrlShortenerApplication.class, args);
}
}運(yùn)行服務(wù)
- 使用 POST 請(qǐng)求 /api/url/shorten 提交長(zhǎng) URL 并獲取短 URL。
- 使用 GET 請(qǐng)求 /api/url/{shortCode} 重定向到原始 URL。
- 使用 GET 請(qǐng)求 /api/url/{shortCode}/stats 獲取短 URL 的訪問(wèn)量。
- 每天定時(shí)任務(wù)會(huì)清理過(guò)期的 URL。
總結(jié)
通過(guò) Spring Boot 框架,我們可以快速構(gòu)建一個(gè)帶有定時(shí)任務(wù)、訪問(wèn)統(tǒng)計(jì)以及過(guò)期處理的 URL 縮短服務(wù)。在真實(shí)場(chǎng)景中,可能還會(huì)涉及更多的功能,如用戶身份驗(yàn)證、URL 黑名單過(guò)濾等。
到此這篇關(guān)于springboot中縮短一個(gè)url鏈接的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)springboot縮短url鏈接內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot+springJdbc+postgresql 實(shí)現(xiàn)多數(shù)據(jù)源的配置
本文主要介紹了springboot+springJdbc+postgresql 實(shí)現(xiàn)多數(shù)據(jù)源的配置,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Spring?Boot?中的?@HystrixCommand?注解原理及使用方法
通過(guò)使用 @HystrixCommand 注解,我們可以輕松地實(shí)現(xiàn)對(duì)方法的隔離和監(jiān)控,從而提高系統(tǒng)的可靠性和穩(wěn)定性,本文介紹了Spring Boot 中的@HystrixCommand注解是什么,其原理以及如何使用,感興趣的朋友跟隨小編一起看看吧2023-07-07
Java數(shù)據(jù)結(jié)構(gòu)之常見(jiàn)排序算法(下)
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之常見(jiàn)排序算法(下),與之相對(duì)有(上),想了解的朋友可以去本網(wǎng)站掃搜,在這兩篇文章里涵蓋關(guān)于八大排序算法的所有內(nèi)容,需要的朋友可以參考下2023-01-01
SpringDataRedis入門(mén)和序列化方式解決內(nèi)存占用問(wèn)題小結(jié)
spring-data-redis是spring-data模塊的一部分,專門(mén)用來(lái)支持在spring管理項(xiàng)目對(duì)redis的操作,這篇文章主要介紹了SpringDataRedis入門(mén)和序列化方式解決內(nèi)存占用問(wèn)題,需要的朋友可以參考下2022-12-12
SpringBoot響應(yīng)處理之以Json數(shù)據(jù)返回的實(shí)現(xiàn)方法
這篇文章主要介紹了SpringBoot整合Web開(kāi)發(fā)其中Json數(shù)據(jù)返回的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-09-09
MyBatis使用resultMap如何解決列名和屬性名不一致
這篇文章主要介紹了MyBatis使用resultMap如何解決列名和屬性名不一致的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
Mybatis-Plus適配聯(lián)合主鍵實(shí)現(xiàn)方式
本文介紹了如何使用Mybatis-Plus(MP)和Mybatis-Plus-Plus(MPP)工具來(lái)處理聯(lián)合主鍵的問(wèn)題,并詳細(xì)描述了整合過(guò)程、遇到的問(wèn)題及解決方式2025-11-11
SpringBoot使用Quartz無(wú)法注入Bean的問(wèn)題及解決
這篇文章主要介紹了SpringBoot使用Quartz無(wú)法注入Bean的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
改善Java代碼之慎用java動(dòng)態(tài)編譯
這篇文章主要介紹了改善Java代碼之慎用java動(dòng)態(tài)編譯,需要的朋友可以參考下2021-04-04

