ShortUrl.java
This commit is contained in:
commit
3add1a1098
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### Eclipse ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
### Mac OS ###
|
||||||
|
.DS_Store
|
22
pom.xml
Normal file
22
pom.xml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?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">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>cn.zzzykj</groupId>
|
||||||
|
<artifactId>zy-short-url</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<modules>
|
||||||
|
<module>zy-shorturl-core</module>
|
||||||
|
<module>zy-shorturl-spring-boot-starter</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
48
zy-shorturl-core/pom.xml
Normal file
48
zy-shorturl-core/pom.xml
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<?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-short-url-core</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>
|
||||||
|
<!-- guava -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>31.1-jre</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- lombok -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.24</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- junit -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.13.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -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 ShortUrl {
|
||||||
|
|
||||||
|
private ShortUrlConfig config;
|
||||||
|
|
||||||
|
private final HashFunction hashFunction;
|
||||||
|
|
||||||
|
private static final Base62 base62 = Base62.createInstance();
|
||||||
|
|
||||||
|
public ShortUrl() {
|
||||||
|
config = new ShortUrlConfig();
|
||||||
|
hashFunction = getHashFunction(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShortUrl(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 = 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package cn.shorturl.core;
|
||||||
|
|
||||||
|
import cn.shorturl.core.enums.HashType;
|
||||||
|
import cn.shorturl.core.enums.StoreType;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lenovo
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class ShortUrlConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hash方式
|
||||||
|
*/
|
||||||
|
private HashType hashType = HashType.MURMUR3_32_FIXED;
|
||||||
|
|
||||||
|
private String hashKey = ShortUrlConfig.class.getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存类型
|
||||||
|
*/
|
||||||
|
private StoreType storeType = StoreType.MEMORY;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package cn.shorturl.core.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lenovo
|
||||||
|
*/
|
||||||
|
|
||||||
|
public enum HashType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MD5
|
||||||
|
*/
|
||||||
|
MD5,
|
||||||
|
|
||||||
|
GOOD_FAST_HASH,
|
||||||
|
|
||||||
|
SHA1,
|
||||||
|
|
||||||
|
SHA256,
|
||||||
|
|
||||||
|
SHA384,
|
||||||
|
|
||||||
|
SHA512,
|
||||||
|
|
||||||
|
HMAC_MD5,
|
||||||
|
|
||||||
|
HMAC_SHA1,
|
||||||
|
|
||||||
|
HMAC_SHA256,
|
||||||
|
|
||||||
|
HMAC_SHA512,
|
||||||
|
|
||||||
|
CRC32_C,
|
||||||
|
|
||||||
|
ADLER32,
|
||||||
|
|
||||||
|
FARM_HASH_FINGERPRINT64,
|
||||||
|
|
||||||
|
FINGERPRINT2011,
|
||||||
|
|
||||||
|
MURMUR3_32,
|
||||||
|
|
||||||
|
MURMUR3_32_FIXED,
|
||||||
|
|
||||||
|
MURMUR3_128,
|
||||||
|
|
||||||
|
SIP_HASH24;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package cn.shorturl.core.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* data store type
|
||||||
|
* @author Lenovo
|
||||||
|
*/
|
||||||
|
public enum StoreType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mysql, sqlserver, oracle 等支持jdbc的数据库
|
||||||
|
*/
|
||||||
|
JDBC,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* redis
|
||||||
|
*/
|
||||||
|
REDIS,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mongodb
|
||||||
|
*/
|
||||||
|
MONGODB,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hazelcast
|
||||||
|
*/
|
||||||
|
HAZELCAST,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内存
|
||||||
|
*/
|
||||||
|
MEMORY,
|
||||||
|
|
||||||
|
}
|
223
zy-shorturl-core/src/main/java/cn/shorturl/core/util/Base62.java
Normal file
223
zy-shorturl-core/src/main/java/cn/shorturl/core/util/Base62.java
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
package cn.shorturl.core.util;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base62编码解码实现,常用于短URL
|
||||||
|
* From https://github.com/seruco/base62
|
||||||
|
* A Base62 encoder/decoder.
|
||||||
|
*
|
||||||
|
* @author Sebastian Ruhleder, sebastian@seruco.io
|
||||||
|
*/
|
||||||
|
public class Base62 {
|
||||||
|
|
||||||
|
private static final int STANDARD_BASE = 256;
|
||||||
|
|
||||||
|
private static final int TARGET_BASE = 62;
|
||||||
|
|
||||||
|
private final byte[] alphabet;
|
||||||
|
|
||||||
|
private byte[] lookup;
|
||||||
|
|
||||||
|
private Base62(final byte[] alphabet) {
|
||||||
|
this.alphabet = alphabet;
|
||||||
|
createLookupTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Base62} instance. Defaults to the GMP-style character set.
|
||||||
|
*
|
||||||
|
* @return a {@link Base62} instance.
|
||||||
|
*/
|
||||||
|
public static Base62 createInstance() {
|
||||||
|
return createInstanceWithGmpCharacterSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Base62} instance using the GMP-style character set.
|
||||||
|
*
|
||||||
|
* @return a {@link Base62} instance.
|
||||||
|
*/
|
||||||
|
public static Base62 createInstanceWithGmpCharacterSet() {
|
||||||
|
return new Base62(CharacterSets.GMP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Base62} instance using the inverted character set.
|
||||||
|
*
|
||||||
|
* @return a {@link Base62} instance.
|
||||||
|
*/
|
||||||
|
public static Base62 createInstanceWithInvertedCharacterSet() {
|
||||||
|
return new Base62(CharacterSets.INVERTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a sequence of bytes in Base62 encoding.
|
||||||
|
*
|
||||||
|
* @param message a byte sequence.
|
||||||
|
* @return a sequence of Base62-encoded bytes.
|
||||||
|
*/
|
||||||
|
public byte[] encode(final byte[] message) {
|
||||||
|
final byte[] indices = convert(message, STANDARD_BASE, TARGET_BASE);
|
||||||
|
|
||||||
|
return translate(indices, alphabet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a sequence of Base62-encoded bytes.
|
||||||
|
*
|
||||||
|
* @param encoded a sequence of Base62-encoded bytes.
|
||||||
|
* @return a byte sequence.
|
||||||
|
* @throws IllegalArgumentException when {@code encoded} is not encoded over the Base62 alphabet.
|
||||||
|
*/
|
||||||
|
public byte[] decode(final byte[] encoded) {
|
||||||
|
if (!isBase62Encoding(encoded)) {
|
||||||
|
throw new IllegalArgumentException("Input is not encoded correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
final byte[] prepared = translate(encoded, lookup);
|
||||||
|
|
||||||
|
return convert(prepared, TARGET_BASE, STANDARD_BASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a sequence of bytes is encoded over a Base62 alphabet.
|
||||||
|
*
|
||||||
|
* @param bytes a sequence of bytes.
|
||||||
|
* @return {@code true} when the bytes are encoded over a Base62 alphabet, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isBase62Encoding(final byte[] bytes) {
|
||||||
|
if (bytes == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final byte e : bytes) {
|
||||||
|
if ('0' > e || '9' < e) {
|
||||||
|
if ('a' > e || 'z' < e) {
|
||||||
|
if ('A' > e || 'Z' < e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses the elements of a byte array as indices to a dictionary and returns the corresponding values
|
||||||
|
* in form of a byte array.
|
||||||
|
*/
|
||||||
|
private byte[] translate(final byte[] indices, final byte[] dictionary) {
|
||||||
|
final byte[] translation = new byte[indices.length];
|
||||||
|
|
||||||
|
for (int i = 0; i < indices.length; i++) {
|
||||||
|
translation[i] = dictionary[indices[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a byte array from a source base to a target base using the alphabet.
|
||||||
|
*/
|
||||||
|
private byte[] convert(final byte[] message, final int sourceBase, final int targetBase) {
|
||||||
|
/**
|
||||||
|
* This algorithm is inspired by: http://codegolf.stackexchange.com/a/21672
|
||||||
|
*/
|
||||||
|
|
||||||
|
final int estimatedLength = estimateOutputLength(message.length, sourceBase, targetBase);
|
||||||
|
|
||||||
|
final ByteArrayOutputStream out = new ByteArrayOutputStream(estimatedLength);
|
||||||
|
|
||||||
|
byte[] source = message;
|
||||||
|
|
||||||
|
while (source.length > 0) {
|
||||||
|
final ByteArrayOutputStream quotient = new ByteArrayOutputStream(source.length);
|
||||||
|
|
||||||
|
int remainder = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < source.length; i++) {
|
||||||
|
final int accumulator = (source[i] & 0xFF) + remainder * sourceBase;
|
||||||
|
final int digit = (accumulator - (accumulator % targetBase)) / targetBase;
|
||||||
|
|
||||||
|
remainder = accumulator % targetBase;
|
||||||
|
|
||||||
|
if (quotient.size() > 0 || digit > 0) {
|
||||||
|
quotient.write(digit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.write(remainder);
|
||||||
|
|
||||||
|
source = quotient.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad output with zeroes corresponding to the number of leading zeroes in the message
|
||||||
|
for (int i = 0; i < message.length - 1 && message[i] == 0; i++) {
|
||||||
|
out.write(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reverse(out.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimates the length of the output in bytes.
|
||||||
|
*/
|
||||||
|
private int estimateOutputLength(int inputLength, int sourceBase, int targetBase) {
|
||||||
|
return (int) Math.ceil((Math.log(sourceBase) / Math.log(targetBase)) * inputLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverses a byte array.
|
||||||
|
*/
|
||||||
|
private byte[] reverse(final byte[] arr) {
|
||||||
|
final int length = arr.length;
|
||||||
|
|
||||||
|
final byte[] reversed = new byte[length];
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
reversed[length - i - 1] = arr[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return reversed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the lookup table from character to index of character in character set.
|
||||||
|
*/
|
||||||
|
private void createLookupTable() {
|
||||||
|
lookup = new byte[256];
|
||||||
|
|
||||||
|
for (int i = 0; i < alphabet.length; i++) {
|
||||||
|
lookup[alphabet[i]] = (byte) (i & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CharacterSets {
|
||||||
|
|
||||||
|
private static final byte[] GMP = {
|
||||||
|
(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
|
||||||
|
(byte) '8', (byte) '9', (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F',
|
||||||
|
(byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N',
|
||||||
|
(byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V',
|
||||||
|
(byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd',
|
||||||
|
(byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l',
|
||||||
|
(byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't',
|
||||||
|
(byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z'
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final byte[] INVERTED = {
|
||||||
|
(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7',
|
||||||
|
(byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f',
|
||||||
|
(byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n',
|
||||||
|
(byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', (byte) 'v',
|
||||||
|
(byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D',
|
||||||
|
(byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L',
|
||||||
|
(byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R', (byte) 'S', (byte) 'T',
|
||||||
|
(byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z'
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package cn.shorturl.core;
|
||||||
|
|
||||||
|
import cn.shorturl.core.enums.HashType;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ShortUrlTest {
|
||||||
|
|
||||||
|
ShortUrlConfig config;
|
||||||
|
|
||||||
|
ShortUrl shortUrl;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
config = new ShortUrlConfig().setHashType(HashType.MURMUR3_32_FIXED);
|
||||||
|
shortUrl = new ShortUrl(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);
|
||||||
|
System.out.println(gen);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
zy-shorturl-spring-boot-starter/pom.xml
Normal file
20
zy-shorturl-spring-boot-starter/pom.xml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?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-short-url-spring-boot-starter</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>
|
||||||
|
|
||||||
|
</project>
|
Loading…
Reference in New Issue
Block a user