需求:给用户发送带链接的短信,有些链接较长,因此需要实现短链接。
下面直接上代码了。
通过MurmurHash对长链接进行hash,并对hash结果encode,最后存入redis,超时时间依情况而定。
@Service
public class UrlShortService {
@Autowired
private CacheManager cacheManager;
private static final String ALPHABETS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
private static final int BASE = ALPHABETS.length();
public String shortenUrl(String url, int expireSeconds) {
long murmur32 = Hashing.murmur3_32().hashUnencodedChars(url).padToLong();
String encoded, value;
do {
encoded = encode(murmur32++);
value = (String) cacheManager.get(encoded);
} while (value != null && !value.equals(url));
cacheManager.setString(encoded, url, false, expireSeconds);
return encoded;
}
private String encode(long oct) {
BigInteger octLong = BigInteger.valueOf(oct);
StringBuilder builder = new StringBuilder(6);
while (!octLong.equals(BigInteger.ZERO)) {
BigInteger[] divideAndReminder = octLong.divideAndRemainder(BigInteger.valueOf(BASE));
builder.append(ALPHABETS.charAt(divideAndReminder[1].intValue()));
octLong = divideAndReminder[0];
}
return builder.reverse().toString();
}
}
通过短链接,从redis中取出长链接,做302重定向。
@Controller
public class ShortUrlController {
@Autowired
private CacheManager cacheManager;
@RequestMapping("/{shortPath}")
public void visit(@PathVariable("shortPath") String shortPath, HttpServletResponse response) {
try {
String originalUrl = cacheManager.getString(shortPath, false);
if(StringUtils.isEmpty(originalUrl)) {
response.setStatus(HttpStatus.SC_NOT_FOUND);
return;
}
response.setHeader("Location", originalUrl);
response.setStatus(HttpStatus.SC_MOVED_TEMPORARILY);
} catch (Exception e) {
response.setStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR);
}
}
}