RedisShortUrlStore 完成
This commit is contained in:
parent
7ce692a2b2
commit
00e9949550
8
pom.xml
8
pom.xml
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
|
@ -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 原链接
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user