diff --git a/pom.xml b/pom.xml index 7cf67ac..8719134 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ zy-shorturl-core zy-shorturl-spring-boot-starter + zy-shorturl-store diff --git a/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrl.java b/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrl.java index 6d23866..691e5bf 100644 --- a/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrl.java +++ b/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrl.java @@ -1,77 +1,51 @@ 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.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import lombok.experimental.Accessors; -import java.nio.charset.StandardCharsets; +import java.util.Date; /** * @author Lenovo */ @Data @Accessors(chain = true) +@NoArgsConstructor +@AllArgsConstructor 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 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(); - } - } + /** + * 过期时间 + */ + private Date gmtExpire; } diff --git a/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrlConfig.java b/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrlConfig.java index dd21e9e..7dd38a8 100644 --- a/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrlConfig.java +++ b/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrlConfig.java @@ -24,4 +24,9 @@ public class ShortUrlConfig { */ private StoreType storeType = StoreType.MEMORY; + /** + * 最大重试次数 + */ + private Integer retryMax = 5; + } diff --git a/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrlUtil.java b/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrlUtil.java new file mode 100644 index 0000000..0292cca --- /dev/null +++ b/zy-shorturl-core/src/main/java/cn/shorturl/core/ShortUrlUtil.java @@ -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(); + } + } + +} diff --git a/zy-shorturl-core/src/test/java/cn/shorturl/core/ShortUrlTest.java b/zy-shorturl-core/src/test/java/cn/shorturl/core/ShortUrlUtilTest.java similarity index 74% rename from zy-shorturl-core/src/test/java/cn/shorturl/core/ShortUrlTest.java rename to zy-shorturl-core/src/test/java/cn/shorturl/core/ShortUrlUtilTest.java index 967e1c1..167f4cd 100644 --- a/zy-shorturl-core/src/test/java/cn/shorturl/core/ShortUrlTest.java +++ b/zy-shorturl-core/src/test/java/cn/shorturl/core/ShortUrlUtilTest.java @@ -4,22 +4,22 @@ import cn.shorturl.core.enums.HashType; import org.junit.Before; import org.junit.Test; -public class ShortUrlTest { +public class ShortUrlUtilTest { ShortUrlConfig config; - ShortUrl shortUrl; + ShortUrlUtil shortUrlUtil; @Before public void init() { config = new ShortUrlConfig().setHashType(HashType.MURMUR3_32_FIXED); - shortUrl = new ShortUrl(config); + shortUrlUtil = new ShortUrlUtil(config); } @Test 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 gen = shortUrl.gen(url); + String gen = shortUrlUtil.gen(url); System.out.println(gen); } diff --git a/zy-shorturl-store/pom.xml b/zy-shorturl-store/pom.xml new file mode 100644 index 0000000..8e4ed1a --- /dev/null +++ b/zy-shorturl-store/pom.xml @@ -0,0 +1,42 @@ + + + + zy-short-url + cn.zzzykj + 1.0-SNAPSHOT + + 4.0.0 + + zy-shorturl-store + + + 8 + 8 + UTF-8 + + + + + cn.zzzykj + zy-short-url-core + 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter + 2.7.2 + compile + true + + + org.springframework.boot + spring-boot-starter-data-redis-reactive + 2.7.2 + compile + true + + + + \ No newline at end of file diff --git a/zy-shorturl-store/src/main/java/cn/shorturl/store/ShortUrlStore.java b/zy-shorturl-store/src/main/java/cn/shorturl/store/ShortUrlStore.java new file mode 100644 index 0000000..8079d98 --- /dev/null +++ b/zy-shorturl-store/src/main/java/cn/shorturl/store/ShortUrlStore.java @@ -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(); + +} diff --git a/zy-shorturl-store/src/main/java/cn/shorturl/store/config/BeanRegister.java b/zy-shorturl-store/src/main/java/cn/shorturl/store/config/BeanRegister.java new file mode 100644 index 0000000..d24be4c --- /dev/null +++ b/zy-shorturl-store/src/main/java/cn/shorturl/store/config/BeanRegister.java @@ -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; + } + +} diff --git a/zy-shorturl-store/src/main/java/cn/shorturl/store/store/JdbcShortUrlStore.java b/zy-shorturl-store/src/main/java/cn/shorturl/store/store/JdbcShortUrlStore.java new file mode 100644 index 0000000..37abbc0 --- /dev/null +++ b/zy-shorturl-store/src/main/java/cn/shorturl/store/store/JdbcShortUrlStore.java @@ -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; + } +} diff --git a/zy-shorturl-store/src/main/java/cn/shorturl/store/store/RedisShortUrlStore.java b/zy-shorturl-store/src/main/java/cn/shorturl/store/store/RedisShortUrlStore.java new file mode 100644 index 0000000..683b3b3 --- /dev/null +++ b/zy-shorturl-store/src/main/java/cn/shorturl/store/store/RedisShortUrlStore.java @@ -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; + } +}