feat:完成Redis缓存和布隆过滤器检查
This commit is contained in:
@@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
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.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.ResponseBody;
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
@@ -37,11 +38,20 @@ public class IndexController {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
public R generateShortURL(@RequestParam String longURL) {
|
public R generateShortURL(@RequestParam String longURL) {
|
||||||
if (UrlUtils.checkURL(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);
|
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:/";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ public class UrlMap {
|
|||||||
private String lurl;//长链接
|
private String lurl;//长链接
|
||||||
private Date createTime;//创建时间
|
private Date createTime;//创建时间
|
||||||
|
|
||||||
public UrlMap(String surl, String lurl, Date createTime) {
|
public UrlMap(String surl, String lurl) {
|
||||||
this.surl = surl;
|
this.surl = surl;
|
||||||
this.lurl = lurl;
|
this.lurl = lurl;
|
||||||
this.createTime = createTime;
|
this.createTime = new Date();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ package top.naccl.dwz.service;
|
|||||||
public interface UrlService {
|
public interface UrlService {
|
||||||
String getLongUrlByShortUrl(String shortURL);
|
String getLongUrlByShortUrl(String shortURL);
|
||||||
|
|
||||||
String saveUrlMap(String shortURL, String longURL);
|
String saveUrlMap(String shortURL, String longURL, String originalURL);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
package top.naccl.dwz.service.impl;
|
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.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.DuplicateKeyException;
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import top.naccl.dwz.entity.UrlMap;
|
import top.naccl.dwz.entity.UrlMap;
|
||||||
import top.naccl.dwz.mapper.UrlMapper;
|
import top.naccl.dwz.mapper.UrlMapper;
|
||||||
import top.naccl.dwz.service.UrlService;
|
import top.naccl.dwz.service.UrlService;
|
||||||
import top.naccl.dwz.util.HashUtils;
|
import top.naccl.dwz.util.HashUtils;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 长短链接映射业务层实现
|
* @Description: 长短链接映射业务层实现
|
||||||
@@ -19,33 +22,58 @@ import java.util.Date;
|
|||||||
public class UrlServiceImpl implements UrlService {
|
public class UrlServiceImpl implements UrlService {
|
||||||
@Autowired
|
@Autowired
|
||||||
UrlMapper urlMapper;
|
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
|
@Override
|
||||||
public String getLongUrlByShortUrl(String shortURL) {
|
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
|
@Override
|
||||||
public String saveUrlMap(String shortURL, String longURL) {
|
public String saveUrlMap(String shortURL, String longURL, String originalURL) {
|
||||||
//在布隆过滤器中查找是否存在
|
//保留长度为1的短链接
|
||||||
if (judgeExist()) {
|
if (shortURL.length() == 1) {
|
||||||
//存在,在长链接后加上指定字符串,重新hash
|
|
||||||
longURL += DUPLICATE;
|
longURL += DUPLICATE;
|
||||||
shortURL = HashUtils.hashToBase62(longURL);
|
shortURL = saveUrlMap(HashUtils.hashToBase62(longURL), longURL, originalURL);
|
||||||
shortURL = saveUrlMap(shortURL, longURL);
|
}
|
||||||
return shortURL;
|
//在布隆过滤器中查找是否存在
|
||||||
|
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 = saveUrlMap(HashUtils.hashToBase62(longURL), longURL, originalURL);
|
||||||
} else {
|
} else {
|
||||||
//不存在,直接存入数据库
|
//不存在,直接存入数据库
|
||||||
try {
|
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) {
|
} catch (Exception e) {
|
||||||
if (e instanceof DuplicateKeyException) {
|
if (e instanceof DuplicateKeyException) {
|
||||||
//数据库已经存在此短链接,则可能是布隆过滤器误判,在长链接后加上指定字符串,重新hash
|
//数据库已经存在此短链接,则可能是布隆过滤器误判,在长链接后加上指定字符串,重新hash
|
||||||
longURL += DUPLICATE;
|
longURL += DUPLICATE;
|
||||||
shortURL = HashUtils.hashToBase62(longURL);
|
shortURL = saveUrlMap(HashUtils.hashToBase62(longURL), longURL, originalURL);
|
||||||
shortURL = saveUrlMap(shortURL, longURL);
|
|
||||||
return shortURL;
|
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@@ -53,8 +81,4 @@ public class UrlServiceImpl implements UrlService {
|
|||||||
}
|
}
|
||||||
return shortURL;
|
return shortURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean judgeExist() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user