springboot中缩短一个url链接的实现

 更新时间:2024年09月15日 10:30:23   作者:一只爱撸猫的程序猿  
缩短 URL 是现代应用程序中常见的需求,通常用于减少长 URL 的长度,使其更易于分享,URL 缩短服务的核心思路是将长 URL 映射到一个唯一的短代码,本文主要介绍了springboot中缩短一个url链接的实现,感兴趣的可以了解一下

缩短 URL 是现代应用程序中常见的需求,通常用于减少长 URL 的长度,使其更易于分享。URL 缩短服务的核心思路是将长 URL 映射到一个唯一的短代码。较为复杂的场景可能涉及多种功能,例如:

  • 缩短的 URL 自动过期(即在一定时间后失效)。
  • 统计 URL 的访问量。
  • 检查并避免短 URL 重复。
  • 添加安全机制,如防止恶意链接。

场景案例

我们可以设计一个场景:

  • 用户通过 API 提交长 URL。
  • 系统生成短 URL,短 URL 有有效期(例如 7 天),并存储在数据库中。
  • 用户可以通过 API 查询短 URL 的访问次数。
  • 每当有人访问短 URL,系统会记录访问量,并自动重定向到原始的长 URL。
  • 在短 URL 过期后,无法再进行重定向。

技术栈

  • Spring Boot: 用于快速构建 RESTful API 服务。
  • H2 数据库: 用于存储 URL 和相关元数据。
  • Java UUID: 生成唯一短码。
  • Java 定时任务: 自动清理过期 URL。

Step 1: 项目结构

src/
├── main/
│   ├── java/
│   │   └── com/
│   │       └── example/
│   │           ├── UrlShortenerApplication.java
│   │           ├── controller/
│   │           │   └── UrlController.java
│   │           ├── model/
│   │           │   └── Url.java
│   │           ├── repository/
│   │           │   └── UrlRepository.java
│   │           └── service/
│   │               └── UrlService.java
│   └── resources/
│       └── application.properties

Step 2: 创建实体类 Url

Url.java 是用于存储长 URL、短 URL 以及相关元数据的实体类。

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: 创建 Repository 接口

使用 Spring Data JPA,我们可以快速创建一个操作数据库的接口。

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: 编写服务类 UrlService

UrlService.java 包含业务逻辑,例如生成短 URL、处理 URL 重定向、统计访问量等。

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);
    }

    // 定时任务清理过期 URL
    public void cleanUpExpiredUrls() {
        urlRepository.deleteByExpiresAtBefore(LocalDateTime.now());
    }
}

Step 5: 编写 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: 定时清理任务

Spring Boot 可以通过 @Scheduled 注解定期执行任务。我们可以创建一个任务来清理过期的 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 * * ?")  // 每天午夜执行一次
    public void cleanExpiredUrls() {
        urlService.cleanUpExpiredUrls();
    }
}

Step 7: 配置文件

在 application.properties 中配置 H2 数据库以及其他 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: 启动类 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);
    }
}

运行服务

  • 使用 POST 请求 /api/url/shorten 提交长 URL 并获取短 URL。
  • 使用 GET 请求 /api/url/{shortCode} 重定向到原始 URL。
  • 使用 GET 请求 /api/url/{shortCode}/stats 获取短 URL 的访问量。
  • 每天定时任务会清理过期的 URL。

总结

通过 Spring Boot 框架,我们可以快速构建一个带有定时任务、访问统计以及过期处理的 URL 缩短服务。在真实场景中,可能还会涉及更多的功能,如用户身份验证、URL 黑名单过滤等。

到此这篇关于springboot中缩短一个url链接的实现的文章就介绍到这了,更多相关springboot缩短url链接内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring AOP手写动态代理代码实例

    Spring AOP手写动态代理代码实例

    这篇文章主要介绍了Spring AOP手写动态代理代码实例,AOP我们知道,是在不修改源代码的情况下,为代码添加一些新功能的技术,通过动态代理,可以在不修改原始类代码的前提下,对方法进行拦截和增强,需要的朋友可以参考下
    2024-01-01
  • Java设计模式之策略模式_动力节点Java学院整理

    Java设计模式之策略模式_动力节点Java学院整理

    策略模式是对算法的封装,把一系列的算法分别封装到对应的类中,并且这些类实现相同的接口,相互之间可以替换。接下来通过本文给大家分享Java设计模式之策略模式,感兴趣的朋友一起看看吧
    2017-08-08
  • 使用java实现Xmodem协议

    使用java实现Xmodem协议

    这篇文章主要介绍了使用java实现Xmodem协议的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • Logback 使用TurboFilter实现日志级别等内容的动态修改操作

    Logback 使用TurboFilter实现日志级别等内容的动态修改操作

    这篇文章主要介绍了Logback 使用TurboFilter实现日志级别等内容的动态修改操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • spring-boot中使用spring-boot-devtools的实现代码

    spring-boot中使用spring-boot-devtools的实现代码

    这篇文章主要介绍了spring-boot中使用spring-boot-devtools的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • Java实现学生成绩管理系统

    Java实现学生成绩管理系统

    这篇文章主要为大家详细介绍了Java实现学生成绩管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • 详解MyBatis配置typeAliases的方法

    详解MyBatis配置typeAliases的方法

    这篇文章主要介绍了详解MyBatis配置typeAliases的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Java中BeanUtils.copyProperties()详解及应用场景

    Java中BeanUtils.copyProperties()详解及应用场景

    BeanUtils.copyProperties()是Apache Commons BeanUtils提供的方法,用于Java对象间属性的复制,特别适用于DTO、VO和Entity之间的数据传递,这篇文章主要介绍了Java中BeanUtils.copyProperties()详解及应用场景的相关资料,需要的朋友可以参考下
    2024-09-09
  • Java中获取年份月份的几种常见方法

    Java中获取年份月份的几种常见方法

    这篇文章主要给大家介绍了关于Java中获取年份月份的几种常见方法,在开发应用程序时,经常需要获取当前的年、月、日,并以特定格式进行展示或处理,需要的朋友可以参考下
    2023-09-09
  • IDEA开启Run Dashboard的几种方式

    IDEA开启Run Dashboard的几种方式

    Run Dashboard 是 IntelliJ IDEA 中的一个工具窗口,用于管理和监视项目中正在运行的应用程序和配置,它提供了一种集中管理运行和调试过程的方式,本文给大家介绍了IDEA开启Run Dashboard的几种方式,需要的朋友可以参考下
    2024-03-03

最新评论