From 539b4e5b0c7fc37ae270ff7142cf6db25424c43e Mon Sep 17 00:00:00 2001 From: Naccl Date: Fri, 26 Mar 2021 14:54:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=AE=8C=E6=88=90Redis=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E5=92=8C=E5=B8=83=E9=9A=86=E8=BF=87=E6=BB=A4=E5=99=A8=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../naccl/dwz/controller/IndexController.java | 16 ++++- .../java/top/naccl/dwz/entity/UrlMap.java | 4 +- .../top/naccl/dwz/service/UrlService.java | 2 +- .../dwz/service/impl/UrlServiceImpl.java | 58 +++++++++++++------ 4 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/main/java/top/naccl/dwz/controller/IndexController.java b/src/main/java/top/naccl/dwz/controller/IndexController.java index f8f1bf5..a1625c6 100644 --- a/src/main/java/top/naccl/dwz/controller/IndexController.java +++ b/src/main/java/top/naccl/dwz/controller/IndexController.java @@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @@ -37,11 +38,20 @@ public class IndexController { @ResponseBody public R generateShortURL(@RequestParam String longURL) { if (UrlUtils.checkURL(longURL)) { - String shortURL = urlService.saveUrlMap(HashUtils.hashToBase62(longURL), longURL); + String shortURL = urlService.saveUrlMap(HashUtils.hashToBase62(longURL), longURL, longURL); return R.ok("请求成功", host + shortURL); - } else { - return R.create(400, "URL有误"); } + return R.create(400, "URL有误"); + } + @GetMapping("/{shortURL}") + public String redirect(@PathVariable String shortURL) { + String longURL = urlService.getLongUrlByShortUrl(shortURL); + if (longURL != null) { + //查询到对应的原始链接,302重定向 + return "redirect:" + longURL; + } + //没有对应的原始链接,直接返回首页 + return "redirect:/"; } } diff --git a/src/main/java/top/naccl/dwz/entity/UrlMap.java b/src/main/java/top/naccl/dwz/entity/UrlMap.java index ba1c266..e138357 100644 --- a/src/main/java/top/naccl/dwz/entity/UrlMap.java +++ b/src/main/java/top/naccl/dwz/entity/UrlMap.java @@ -22,9 +22,9 @@ public class UrlMap { private String lurl;//长链接 private Date createTime;//创建时间 - public UrlMap(String surl, String lurl, Date createTime) { + public UrlMap(String surl, String lurl) { this.surl = surl; this.lurl = lurl; - this.createTime = createTime; + this.createTime = new Date(); } } diff --git a/src/main/java/top/naccl/dwz/service/UrlService.java b/src/main/java/top/naccl/dwz/service/UrlService.java index 526f3bc..0e3312d 100644 --- a/src/main/java/top/naccl/dwz/service/UrlService.java +++ b/src/main/java/top/naccl/dwz/service/UrlService.java @@ -3,5 +3,5 @@ package top.naccl.dwz.service; public interface UrlService { String getLongUrlByShortUrl(String shortURL); - String saveUrlMap(String shortURL, String longURL); + String saveUrlMap(String shortURL, String longURL, String originalURL); } diff --git a/src/main/java/top/naccl/dwz/service/impl/UrlServiceImpl.java b/src/main/java/top/naccl/dwz/service/impl/UrlServiceImpl.java index b56b547..5d38e59 100644 --- a/src/main/java/top/naccl/dwz/service/impl/UrlServiceImpl.java +++ b/src/main/java/top/naccl/dwz/service/impl/UrlServiceImpl.java @@ -1,14 +1,17 @@ package top.naccl.dwz.service.impl; +import cn.hutool.bloomfilter.BitMapBloomFilter; +import cn.hutool.bloomfilter.BloomFilterUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DuplicateKeyException; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import top.naccl.dwz.entity.UrlMap; import top.naccl.dwz.mapper.UrlMapper; import top.naccl.dwz.service.UrlService; import top.naccl.dwz.util.HashUtils; -import java.util.Date; +import java.util.concurrent.TimeUnit; /** * @Description: 长短链接映射业务层实现 @@ -19,33 +22,58 @@ import java.util.Date; public class UrlServiceImpl implements UrlService { @Autowired UrlMapper urlMapper; - private static final String DUPLICATE = " *"; + @Autowired + StringRedisTemplate redisTemplate; + //自定义长链接防重复字符串 + private static final String DUPLICATE = "*"; + //最近使用的短链接过期时间(分钟) + private static final long TIMEOUT = 10; + //创建布隆过滤器 + private static final BitMapBloomFilter FILTER = BloomFilterUtil.createBitMap(10); @Override public String getLongUrlByShortUrl(String shortURL) { - return urlMapper.getLongUrlByShortUrl(shortURL).replace(DUPLICATE, ""); + //查找Redis中是否有缓存 + String longURL = redisTemplate.opsForValue().get(shortURL); + if (longURL != null) { + //有缓存 + return longURL; + } + //Redis没有缓存,从数据库查找 + return urlMapper.getLongUrlByShortUrl(shortURL); } @Override - public String saveUrlMap(String shortURL, String longURL) { + public String saveUrlMap(String shortURL, String longURL, String originalURL) { + //保留长度为1的短链接 + if (shortURL.length() == 1) { + longURL += DUPLICATE; + shortURL = saveUrlMap(HashUtils.hashToBase62(longURL), longURL, originalURL); + } //在布隆过滤器中查找是否存在 - if (judgeExist()) { - //存在,在长链接后加上指定字符串,重新hash + else if (FILTER.contains(shortURL)) { + //存在,从Redis中查找是否有缓存 + String redisLongURL = redisTemplate.opsForValue().get(shortURL); + if (redisLongURL != null && originalURL.equals(redisLongURL)) { + //Redis有缓存,重置过期时间 + redisTemplate.expire(shortURL, TIMEOUT, TimeUnit.MINUTES); + return shortURL; + } + //没有缓存,在长链接后加上指定字符串,重新hash longURL += DUPLICATE; - shortURL = HashUtils.hashToBase62(longURL); - shortURL = saveUrlMap(shortURL, longURL); - return shortURL; + shortURL = saveUrlMap(HashUtils.hashToBase62(longURL), longURL, originalURL); } else { //不存在,直接存入数据库 try { - urlMapper.saveUrlMap(new UrlMap(shortURL, longURL, new Date())); + urlMapper.saveUrlMap(new UrlMap(shortURL, originalURL)); + FILTER.add(shortURL); + //添加缓存 + redisTemplate.opsForValue().set(shortURL, originalURL, TIMEOUT, TimeUnit.MINUTES); } catch (Exception e) { if (e instanceof DuplicateKeyException) { //数据库已经存在此短链接,则可能是布隆过滤器误判,在长链接后加上指定字符串,重新hash longURL += DUPLICATE; - shortURL = HashUtils.hashToBase62(longURL); - shortURL = saveUrlMap(shortURL, longURL); - return shortURL; + shortURL = saveUrlMap(HashUtils.hashToBase62(longURL), longURL, originalURL); } else { throw e; } @@ -53,8 +81,4 @@ public class UrlServiceImpl implements UrlService { } return shortURL; } - - public boolean judgeExist() { - return false; - } }