ShortUrlStore
This commit is contained in:
parent
3add1a1098
commit
93aeb8266a
1
pom.xml
1
pom.xml
|
@ -11,6 +11,7 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>zy-shorturl-core</module>
|
<module>zy-shorturl-core</module>
|
||||||
<module>zy-shorturl-spring-boot-starter</module>
|
<module>zy-shorturl-spring-boot-starter</module>
|
||||||
|
<module>zy-shorturl-store</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|
|
@ -1,77 +1,51 @@
|
||||||
package cn.shorturl.core;
|
package cn.shorturl.core;
|
||||||
|
|
||||||
import cn.shorturl.core.enums.HashType;
|
import lombok.AllArgsConstructor;
|
||||||
import cn.shorturl.core.util.Base62;
|
|
||||||
import com.google.common.hash.HashCode;
|
|
||||||
import com.google.common.hash.HashFunction;
|
|
||||||
import com.google.common.hash.Hashing;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Lenovo
|
* @author Lenovo
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
public class ShortUrl {
|
public class ShortUrl {
|
||||||
|
|
||||||
private ShortUrlConfig config;
|
/**
|
||||||
|
* 短连接
|
||||||
|
*/
|
||||||
|
private String hash;
|
||||||
|
|
||||||
private final HashFunction hashFunction;
|
/**
|
||||||
|
* 原链接
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
private static final Base62 base62 = Base62.createInstance();
|
/**
|
||||||
|
* 原链接长度(在Hash冲突时, 给原链接加上随机数并重新生成短链接, 通过Hash获取原链接是还原原链接)
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
private Integer urlLength;
|
||||||
|
|
||||||
public ShortUrl() {
|
/**
|
||||||
config = new ShortUrlConfig();
|
* 创建时间
|
||||||
hashFunction = getHashFunction(config);
|
*/
|
||||||
}
|
private Date gmtCreate;
|
||||||
|
|
||||||
public ShortUrl(ShortUrlConfig config) {
|
/**
|
||||||
this.config = config;
|
* 有效时间(秒)
|
||||||
hashFunction = getHashFunction(config);
|
*/
|
||||||
}
|
@Deprecated
|
||||||
|
private Long validityTime;
|
||||||
|
|
||||||
public String gen(String url) {
|
/**
|
||||||
HashCode hashCode = hashFunction.hashString(url, StandardCharsets.UTF_8);
|
* 过期时间
|
||||||
byte[] bytes = hashCode.asBytes();
|
*/
|
||||||
return new String(base62.encode(bytes));
|
private Date gmtExpire;
|
||||||
}
|
|
||||||
|
|
||||||
private static HashFunction getHashFunction(ShortUrlConfig config) {
|
|
||||||
return getHashFunction(config.getHashType(), config.getHashKey());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HashFunction getHashFunction(HashType type, String key) {
|
|
||||||
if (type == null) {
|
|
||||||
return Hashing.murmur3_32_fixed();
|
|
||||||
}
|
|
||||||
if (key == null) {
|
|
||||||
key = ShortUrl.class.getName();
|
|
||||||
}
|
|
||||||
byte[] keyBytes = key.getBytes();
|
|
||||||
switch (type) {
|
|
||||||
case MD5: return Hashing.md5();
|
|
||||||
case GOOD_FAST_HASH: return Hashing.goodFastHash(32);
|
|
||||||
case SHA1: return Hashing.sha1();
|
|
||||||
case SHA256: return Hashing.sha256();
|
|
||||||
case SHA384: return Hashing.sha384();
|
|
||||||
case SHA512: return Hashing.sha512();
|
|
||||||
case HMAC_MD5: return Hashing.hmacMd5(keyBytes);
|
|
||||||
case HMAC_SHA1: return Hashing.hmacSha1(keyBytes);
|
|
||||||
case HMAC_SHA256: return Hashing.hmacSha256(keyBytes);
|
|
||||||
case HMAC_SHA512: return Hashing.hmacSha512(keyBytes);
|
|
||||||
case CRC32_C: return Hashing.crc32c();
|
|
||||||
case ADLER32: return Hashing.adler32();
|
|
||||||
case FARM_HASH_FINGERPRINT64: return Hashing.farmHashFingerprint64();
|
|
||||||
case FINGERPRINT2011: return Hashing.fingerprint2011();
|
|
||||||
case MURMUR3_32: return Hashing.murmur3_32();
|
|
||||||
case MURMUR3_128: return Hashing.murmur3_128();
|
|
||||||
case SIP_HASH24: return Hashing.sipHash24();
|
|
||||||
case MURMUR3_32_FIXED:
|
|
||||||
default: return Hashing.murmur3_32_fixed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,4 +24,9 @@ public class ShortUrlConfig {
|
||||||
*/
|
*/
|
||||||
private StoreType storeType = StoreType.MEMORY;
|
private StoreType storeType = StoreType.MEMORY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最大重试次数
|
||||||
|
*/
|
||||||
|
private Integer retryMax = 5;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package cn.shorturl.core;
|
||||||
|
|
||||||
|
import cn.shorturl.core.enums.HashType;
|
||||||
|
import cn.shorturl.core.util.Base62;
|
||||||
|
import com.google.common.hash.HashCode;
|
||||||
|
import com.google.common.hash.HashFunction;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lenovo
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class ShortUrlUtil {
|
||||||
|
|
||||||
|
private ShortUrlConfig config;
|
||||||
|
|
||||||
|
private final HashFunction hashFunction;
|
||||||
|
|
||||||
|
private static final Base62 base62 = Base62.createInstance();
|
||||||
|
|
||||||
|
public ShortUrlUtil() {
|
||||||
|
config = new ShortUrlConfig();
|
||||||
|
hashFunction = getHashFunction(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShortUrlUtil(ShortUrlConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
hashFunction = getHashFunction(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String gen(String url) {
|
||||||
|
HashCode hashCode = hashFunction.hashString(url, StandardCharsets.UTF_8);
|
||||||
|
byte[] bytes = hashCode.asBytes();
|
||||||
|
return new String(base62.encode(bytes));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashFunction getHashFunction(ShortUrlConfig config) {
|
||||||
|
return getHashFunction(config.getHashType(), config.getHashKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HashFunction getHashFunction(HashType type, String key) {
|
||||||
|
if (type == null) {
|
||||||
|
return Hashing.murmur3_32_fixed();
|
||||||
|
}
|
||||||
|
if (key == null) {
|
||||||
|
key = ShortUrlUtil.class.getName();
|
||||||
|
}
|
||||||
|
byte[] keyBytes = key.getBytes();
|
||||||
|
switch (type) {
|
||||||
|
case MD5: return Hashing.md5();
|
||||||
|
case GOOD_FAST_HASH: return Hashing.goodFastHash(32);
|
||||||
|
case SHA1: return Hashing.sha1();
|
||||||
|
case SHA256: return Hashing.sha256();
|
||||||
|
case SHA384: return Hashing.sha384();
|
||||||
|
case SHA512: return Hashing.sha512();
|
||||||
|
case HMAC_MD5: return Hashing.hmacMd5(keyBytes);
|
||||||
|
case HMAC_SHA1: return Hashing.hmacSha1(keyBytes);
|
||||||
|
case HMAC_SHA256: return Hashing.hmacSha256(keyBytes);
|
||||||
|
case HMAC_SHA512: return Hashing.hmacSha512(keyBytes);
|
||||||
|
case CRC32_C: return Hashing.crc32c();
|
||||||
|
case ADLER32: return Hashing.adler32();
|
||||||
|
case FARM_HASH_FINGERPRINT64: return Hashing.farmHashFingerprint64();
|
||||||
|
case FINGERPRINT2011: return Hashing.fingerprint2011();
|
||||||
|
case MURMUR3_32: return Hashing.murmur3_32();
|
||||||
|
case MURMUR3_128: return Hashing.murmur3_128();
|
||||||
|
case SIP_HASH24: return Hashing.sipHash24();
|
||||||
|
case MURMUR3_32_FIXED:
|
||||||
|
default: return Hashing.murmur3_32_fixed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,22 +4,22 @@ import cn.shorturl.core.enums.HashType;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class ShortUrlTest {
|
public class ShortUrlUtilTest {
|
||||||
|
|
||||||
ShortUrlConfig config;
|
ShortUrlConfig config;
|
||||||
|
|
||||||
ShortUrl shortUrl;
|
ShortUrlUtil shortUrlUtil;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void init() {
|
public void init() {
|
||||||
config = new ShortUrlConfig().setHashType(HashType.MURMUR3_32_FIXED);
|
config = new ShortUrlConfig().setHashType(HashType.MURMUR3_32_FIXED);
|
||||||
shortUrl = new ShortUrl(config);
|
shortUrlUtil = new ShortUrlUtil(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGen() {
|
public void testGen() {
|
||||||
String url = "http://www.baidu.com//?asdasdasdaas=das==wqe===gfa=sd=asf=g=eq=w===a=sd=as=fg=w=d=as=d=as=f=w=";
|
String url = "http://www.baidu.com//?asdasdasdaas=das==wqe===gfa=sd=asf=g=eq=w===a=sd=as=fg=w=d=as=d=as=f=w=";
|
||||||
String gen = shortUrl.gen(url);
|
String gen = shortUrlUtil.gen(url);
|
||||||
System.out.println(gen);
|
System.out.println(gen);
|
||||||
}
|
}
|
||||||
|
|
42
zy-shorturl-store/pom.xml
Normal file
42
zy-shorturl-store/pom.xml
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>zy-short-url</artifactId>
|
||||||
|
<groupId>cn.zzzykj</groupId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>zy-shorturl-store</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.zzzykj</groupId>
|
||||||
|
<artifactId>zy-short-url-core</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
<version>2.7.2</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
|
||||||
|
<version>2.7.2</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,73 @@
|
||||||
|
package cn.shorturl.store;
|
||||||
|
|
||||||
|
import cn.shorturl.core.ShortUrl;
|
||||||
|
import cn.shorturl.core.ShortUrlConfig;
|
||||||
|
import cn.shorturl.core.ShortUrlUtil;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lenovo
|
||||||
|
*/
|
||||||
|
public interface ShortUrlStore {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加短连接(外部访问)
|
||||||
|
* @param url 原链接
|
||||||
|
* @return 短连接
|
||||||
|
*/
|
||||||
|
default ShortUrl add(String url) {
|
||||||
|
return add(url, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加短链接(外部访问)
|
||||||
|
* @param url 原链接
|
||||||
|
* @param expireTime 过期时间
|
||||||
|
* @return 短连接
|
||||||
|
*/
|
||||||
|
default ShortUrl add(String url, Date expireTime) {
|
||||||
|
Integer max = getConfig().getRetryMax();
|
||||||
|
if (max == null) {
|
||||||
|
max = 5;
|
||||||
|
}
|
||||||
|
ShortUrl shortUrl = new ShortUrl().setUrl(url).setGmtExpire(expireTime).setGmtCreate(new Date());
|
||||||
|
for (int i = 0; i < max; i++) {
|
||||||
|
String hash = hash(url);
|
||||||
|
try {
|
||||||
|
shortUrl.setHash(hash);
|
||||||
|
add(shortUrl);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new RuntimeException("add short url failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加短链接(内部访问, 请勿外部访问)
|
||||||
|
* @param shortUrl 短链接
|
||||||
|
*/
|
||||||
|
ShortUrl add(ShortUrl shortUrl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取短链接
|
||||||
|
* @param hash 短链接
|
||||||
|
* @return 原链接
|
||||||
|
*/
|
||||||
|
ShortUrl get(String hash);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对URL进行Hash编码
|
||||||
|
* @param url 原链接
|
||||||
|
* @return 短链接
|
||||||
|
*/
|
||||||
|
String hash(String url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置对象
|
||||||
|
* @return 配置对象
|
||||||
|
*/
|
||||||
|
ShortUrlConfig getConfig();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package cn.shorturl.store.config;
|
||||||
|
|
||||||
|
import cn.shorturl.core.ShortUrlConfig;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lenovo
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties
|
||||||
|
@ComponentScan(basePackages = "cn.shorturl.store")
|
||||||
|
public class BeanRegister {
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "shorturl.store")
|
||||||
|
public ShortUrlConfig shortUrlConfig(ShortUrlConfig shortUrlConfig) {
|
||||||
|
return shortUrlConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package cn.shorturl.store.store;
|
||||||
|
|
||||||
|
import cn.shorturl.core.ShortUrl;
|
||||||
|
import cn.shorturl.core.ShortUrlConfig;
|
||||||
|
import cn.shorturl.store.ShortUrlStore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lenovo
|
||||||
|
*/
|
||||||
|
public class JdbcShortUrlStore implements ShortUrlStore {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShortUrl add(ShortUrl shortUrl) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShortUrl get(String hash) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String hash(String url) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShortUrlConfig getConfig() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package cn.shorturl.store.store;
|
||||||
|
|
||||||
|
import cn.shorturl.core.ShortUrl;
|
||||||
|
import cn.shorturl.core.ShortUrlConfig;
|
||||||
|
import cn.shorturl.store.ShortUrlStore;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lenovo
|
||||||
|
*/
|
||||||
|
@ConditionalOnProperty(prefix = "shorturl.store", name = "storeType", havingValue = "redis")
|
||||||
|
public class RedisShortUrlStore implements ShortUrlStore {
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
System.out.println("RedisShortUrlStore init");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShortUrl add(ShortUrl shortUrl) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShortUrl get(String hash) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String hash(String url) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShortUrlConfig getConfig() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user