RedisShortUrlStore 完成

This commit is contained in:
TheEnd 2022-07-31 19:35:26 +08:00
parent 7ce692a2b2
commit 00e9949550
9 changed files with 176 additions and 8 deletions

View File

@ -27,4 +27,12 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@ -3,7 +3,9 @@ package cn.shorturl.boot.starter;
import cn.shorturl.core.ShortUrlConfig;
import cn.shorturl.core.ShortUrlUtil;
import cn.shorturl.store.ShortUrlStore;
import cn.shorturl.store.store.JdbcShortUrlStore;
import cn.shorturl.store.store.RedisShortUrlStore;
import cn.shorturl.store.template.ShortUrlRedisTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -13,6 +15,8 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import javax.annotation.PostConstruct;
@ -44,9 +48,18 @@ public class ShortUrlAutoConfiguration {
@ConditionalOnMissingBean(ShortUrlStore.class)
@ConditionalOnBean(ShortUrlUtil.class)
@ConditionalOnProperty(prefix = "shorturl.store", name = "store-type", havingValue = "redis")
public ShortUrlStore redisShortUrlStore(ShortUrlUtil util) {
public ShortUrlStore redisShortUrlStore(ShortUrlUtil util, RedisConnectionFactory connectionFactory) {
log.info("use short-url store: {}", RedisShortUrlStore.class.getName());
return new RedisShortUrlStore(util);
return new RedisShortUrlStore(util, new ShortUrlRedisTemplate(connectionFactory));
}
@Bean
@ConditionalOnMissingBean(ShortUrlStore.class)
@ConditionalOnBean(ShortUrlUtil.class)
@ConditionalOnProperty(prefix = "shorturl.store", name = "store-type", havingValue = "jdbc")
public ShortUrlStore jdbcShortUrlStore(ShortUrlUtil util) {
log.info("use short-url store: {}", RedisShortUrlStore.class.getName());
return new JdbcShortUrlStore(util);
}
}

View File

@ -23,6 +23,18 @@
<artifactId>zy-short-url-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,7 +1,6 @@
package cn.shorturl.store;
import cn.shorturl.core.ShortUrl;
import cn.shorturl.core.ShortUrlConfig;
import cn.shorturl.core.ShortUrlUtil;
import java.util.Date;
@ -30,12 +29,16 @@ public abstract class ShortUrlStore {
*/
public ShortUrl add(String url, Date expireTime) {
Integer max = util.getConfig().getRetryMax();
if (max == null) {
max = 5;
if (max == null || max < 1) {
max = 10;
}
ShortUrl shortUrl = new ShortUrl().setUrl(url).setGmtExpire(expireTime).setGmtCreate(new Date());
for (int i = 0; i < max; i++) {
String hash = hash(url);
if (contains(hash)) {
url += (int) (Math.random() * 10);
continue;
}
try {
shortUrl.setHash(hash);
add(shortUrl);
@ -50,6 +53,7 @@ public abstract class ShortUrlStore {
/**
* 添加短链接(内部访问, 请勿外部访问)
* @param shortUrl 短链接
* @return 短链接
*/
protected abstract ShortUrl add(ShortUrl shortUrl);
@ -60,6 +64,13 @@ public abstract class ShortUrlStore {
*/
public abstract ShortUrl get(String hash);
/**
* Hash是否已经存在
* @param hash Hash
* @return 是否已经存在
*/
public abstract boolean contains(String hash);
/**
* 对URL进行Hash编码
* @param url 原链接

View File

@ -0,0 +1,17 @@
package cn.shorturl.store.exception;
/**
* @author ZhuoQinghui
* @version 1.0.0
* Create By 2022/7/31 18:49
*/
public class HashAlreadyException extends RuntimeException {
public HashAlreadyException() {
}
public HashAlreadyException(String message) {
super(message);
}
}

View File

@ -1,6 +1,7 @@
package cn.shorturl.store.store;
import cn.shorturl.core.ShortUrl;
import cn.shorturl.core.ShortUrlUtil;
import cn.shorturl.store.ShortUrlStore;
/**
@ -8,6 +9,9 @@ import cn.shorturl.store.ShortUrlStore;
*/
public class JdbcShortUrlStore extends ShortUrlStore {
public JdbcShortUrlStore(ShortUrlUtil util) {
super.util = util;
}
@Override
protected ShortUrl add(ShortUrl shortUrl) {
@ -19,4 +23,9 @@ public class JdbcShortUrlStore extends ShortUrlStore {
return null;
}
@Override
public boolean contains(String hash) {
return false;
}
}

View File

@ -3,27 +3,55 @@ package cn.shorturl.store.store;
import cn.shorturl.core.ShortUrl;
import cn.shorturl.core.ShortUrlUtil;
import cn.shorturl.store.ShortUrlStore;
import cn.shorturl.store.exception.HashAlreadyException;
import cn.shorturl.store.template.ShortUrlRedisTemplate;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* @author Lenovo
*/
public class RedisShortUrlStore extends ShortUrlStore {
ShortUrlRedisTemplate redisTemplate;
public static final String SHORT_KEY = "short:url:";
public RedisShortUrlStore(ShortUrlUtil util) {
public RedisShortUrlStore(ShortUrlUtil util, ShortUrlRedisTemplate redisTemplate) {
super.util = util;
this.redisTemplate = redisTemplate;
}
@Override
protected ShortUrl add(ShortUrl shortUrl) {
System.out.println(shortUrl);
return null;
String key = SHORT_KEY + shortUrl.getHash();
Date expire = shortUrl.getGmtExpire();
Boolean save;
if (expire != null) {
long time = expire.getTime() - System.currentTimeMillis();
if (time < 0) {
return null;
}
save = redisTemplate.opsForValue().setIfAbsent(key, shortUrl, time, TimeUnit.MILLISECONDS);
} else {
save = redisTemplate.opsForValue().setIfAbsent(key, shortUrl);
}
if (!Boolean.TRUE.equals(save)) {
throw new HashAlreadyException("hash already exists");
}
return shortUrl;
}
@Override
public ShortUrl get(String hash) {
return null;
return redisTemplate.opsForValue().get(SHORT_KEY + hash);
}
@Override
public boolean contains(String hash) {
return redisTemplate.opsForValue().get(SHORT_KEY + hash) != null;
}
}

View File

@ -0,0 +1,32 @@
package cn.shorturl.store.template;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
/**
* @author ZhuoQinghui
* @version 1.0.0
* Create By 2022/7/31 18:07
*/
public class DefaultRedisTemplate<K, V> extends RedisTemplate<K, V> {
public DefaultRedisTemplate(Class<K> kClass, Class<V> vClass) {
if (kClass.equals(String.class)) {
this.setKeySerializer(RedisSerializer.string());
this.setHashKeySerializer(RedisSerializer.string());
} else {
this.setKeySerializer(new Jackson2JsonRedisSerializer<>(kClass));
this.setHashKeySerializer(new Jackson2JsonRedisSerializer<>(kClass));
}
this.setValueSerializer(new Jackson2JsonRedisSerializer<>(vClass));
this.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(vClass));
}
public DefaultRedisTemplate(Class<K> kClass, Class<V> vClass, RedisConnectionFactory connectionFactory) {
this(kClass, vClass);
this.setConnectionFactory(connectionFactory);
this.afterPropertiesSet();
}
}

View File

@ -0,0 +1,38 @@
package cn.shorturl.store.template;
import cn.shorturl.core.ShortUrl;
import org.springframework.data.redis.connection.RedisConnectionFactory;
/**
* @author ZhuoQinghui
* @version 1.0.0
* Create By 2022/7/31 18:03
*/
public class ShortUrlRedisTemplate extends DefaultRedisTemplate<String, ShortUrl> {
public ShortUrlRedisTemplate() {
super(String.class, ShortUrl.class);
}
public ShortUrlRedisTemplate(RedisConnectionFactory connectionFactory) {
this();
this.setConnectionFactory(connectionFactory);
this.afterPropertiesSet();
}
// public ShortUrlRedisTemplate() {
// this.setKeySerializer(RedisSerializer.string());
// this.setHashKeySerializer(RedisSerializer.string());
// this.setValueSerializer(new Jackson2JsonRedisSerializer<>(ShortUrl.class));
// this.setHashValueSerializer(RedisSerializer.string());
// }
//
// public ShortUrlRedisTemplate(RedisConnectionFactory connectionFactory) {
// this();
// this.setConnectionFactory(connectionFactory);
// this.afterPropertiesSet();
// }
}