【后端】【Java】可直接落地的 Nginx + Java(Spring Boot)+ Redis 的短链系统实现

一个 示例,包含:

  • 系统架构

  • Nginx 配置

  • Java 代码(短链生成 + 统计 + 302 跳转)

  • Redis 数据结构

  • 访问统计方案

这是一个完整、可部署的模板。


✔️ 1. 系统架构设计

复制代码
用户访问短链 → Nginx → Java短链服务 → Redis查真实链接
                              ↓
                        记录统计数据(异步)
                              ↓
                          302 重定向

✔️ 2. Redis 数据结构设计

1)短链映射

复制代码
Key: short:abcd123
Value: https://example.com/activity?channel=weibo

2)访问统计(可选)

复制代码
短链点击次数:count:abcd123 → incr
访问记录:log:abcd123 → list push {...json...}

✔️ 3. Nginx 配置(负责把短链路由给 Java)

短链域名:https://s.example.com/xxxxxx

nginx.conf

复制代码
server {
    listen 80;
    server_name s.example.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }
}

访问 s.example.com/abcd12 时会转到 Java 后端:

复制代码
GET http://127.0.0.1:8080/abcd12

✔️ 4. Java (Spring Boot) 实现示例

4.1 短链生成 API

Controller

复制代码
@RestController
@RequestMapping("/api")
public class ShortLinkController {

    @Autowired
    private ShortLinkService shortLinkService;

    @PostMapping("/shorten")
    public String createShortLink(@RequestParam String longUrl) {
        return shortLinkService.createShortUrl(longUrl);
    }
}

4.2 Service:短链生成 + 存入 Redis

复制代码
@Service
public class ShortLinkService {

    @Autowired
    private StringRedisTemplate redis;

    private static final String SHORT_KEY_PREFIX = "short:";

    public String createShortUrl(String longUrl) {
        // 生成短链 ID:6 位
        String shortId = RandomStringUtils.randomAlphanumeric(6);

        // 保存到 Redis
        redis.opsForValue().set(SHORT_KEY_PREFIX + shortId, longUrl);

        // 返回短链
        return "https://s.example.com/" + shortId;
    }
}

✔️ 5. Java Controller:接收短链并 302 跳转

关键部分:

  • 查 Redis

  • 记录统计

  • 返回 302

    @RestController
    public class RedirectController {

    复制代码
      @Autowired
      private StringRedisTemplate redis;
    
      @Autowired
      private AsyncLogService asyncLogService;
    
      private static final String SHORT_KEY_PREFIX = "short:";
    
      @GetMapping("/{shortId}")
      public ResponseEntity<Void> redirect(@PathVariable String shortId,
                                           HttpServletRequest request) {
          String key = SHORT_KEY_PREFIX + shortId;
          String longUrl = redis.opsForValue().get(key);
    
          if (longUrl == null) {
              return ResponseEntity.notFound().build();
          }
    
          // 异步记录访问
          asyncLogService.log(shortId, request);
    
          // 302 跳转
          HttpHeaders headers = new HttpHeaders();
          headers.setLocation(URI.create(longUrl));
          return new ResponseEntity<>(headers, HttpStatus.FOUND);
      }

    }


✔️ 6. 异步记录统计(可选)

通过 @Async 保存访问日志,不阻塞跳转。

异步记录点击数量 + 访问日志

复制代码
@Service
public class AsyncLogService {

    @Autowired
    private StringRedisTemplate redis;

    @Async
    public void log(String shortId, HttpServletRequest request) {
        String ua = request.getHeader("User-Agent");
        String ip = request.getRemoteAddr();
        long timestamp = System.currentTimeMillis() / 1000;

        // 点击次数
        redis.opsForValue().increment("count:" + shortId);

        // 访问日志
        JSONObject log = new JSONObject();
        log.put("ip", ip);
        log.put("ua", ua);
        log.put("time", timestamp);

        redis.opsForList().leftPush("log:" + shortId, log.toString());
    }
}

✔️ 7. 查询统计的 API 示例

查询访问次数

复制代码
@GetMapping("/api/count/{shortId}")
public Long getCount(@PathVariable String shortId) {
    return Long.valueOf(redis.opsForValue().get("count:" + shortId));
}

查询访问日志

复制代码
@GetMapping("/api/logs/{shortId}")
public List<String> getLogs(@PathVariable String shortId) {
    return redis.opsForList().range("log:" + shortId, 0, 100);
}

✔️ 8. 运行效果

  1. 创建短链:

    POST /api/shorten
    longUrl=https://example.com/page?channel=test

    返回:
    https://s.example.com/aB92kF

  2. 用户访问短链:

    GET https://s.example.com/aB92kF

  3. Java 读取 Redis → 记录统计 → 302 跳转

  4. 在后台看到统计数据:

    count:aB92kF = 1023
    log:aB92kF = [ {ip:..., ua:..., time:...}, ... ]


相关推荐
蝎子莱莱爱打怪5 小时前
别再裸用 Claude Code 了!32 个亲测Skills + 8 个 MCP,开发效率直接拉满!
java·后端·claude
野犬寒鸦5 小时前
JVM垃圾回收机制面试常问问题及详解
java·服务器·开发语言·jvm·后端·算法·面试
曲幽5 小时前
FastAPI实战:WebSocket vs Socket.IO,这回真给我整明白了!
python·websocket·nginx·socket·fastapi·web·async·socketio
_杨瀚博5 小时前
JAVA找出哪个类import了不存在的类
java·后端
OKkankan5 小时前
深入理解linux进程
java·linux·c++
java1234_小锋6 小时前
Java高频面试题:Spring-AOP通知和执行顺序?
java·开发语言·spring
番茄去哪了6 小时前
Java基础面试题day02
java·开发语言·面向对象编程
我是咸鱼不闲呀6 小时前
力扣Hot100系列22(Java)——[图论]总结(岛屿数量,腐烂的橘子,课程表,实现Trie(前缀树))
java·leetcode·图论
1104.北光c°6 小时前
深入浅出 Elasticsearch:从搜索框到精准排序的架构实战
java·开发语言·elasticsearch·缓存·架构·全文检索·es
MSTcheng.6 小时前
【优选算法必修篇——位运算】『面试题 01.01. 判定字符是否唯一&面试题 17.19. 消失的两个数字』
java·算法·面试