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> |         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||||
|     </properties> |     </properties> | ||||||
| 
 | 
 | ||||||
|  |     <dependencies> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.data</groupId> | ||||||
|  |             <artifactId>spring-data-redis</artifactId> | ||||||
|  |             <optional>true</optional> | ||||||
|  |         </dependency> | ||||||
|  |     </dependencies> | ||||||
|  | 
 | ||||||
| </project> | </project> | ||||||
|  | @ -3,7 +3,9 @@ package cn.shorturl.boot.starter; | ||||||
| import cn.shorturl.core.ShortUrlConfig; | import cn.shorturl.core.ShortUrlConfig; | ||||||
| import cn.shorturl.core.ShortUrlUtil; | import cn.shorturl.core.ShortUrlUtil; | ||||||
| import cn.shorturl.store.ShortUrlStore; | import cn.shorturl.store.ShortUrlStore; | ||||||
|  | import cn.shorturl.store.store.JdbcShortUrlStore; | ||||||
| import cn.shorturl.store.store.RedisShortUrlStore; | import cn.shorturl.store.store.RedisShortUrlStore; | ||||||
|  | import cn.shorturl.store.template.ShortUrlRedisTemplate; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; | ||||||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | 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.Bean; | ||||||
| import org.springframework.context.annotation.ComponentScan; | import org.springframework.context.annotation.ComponentScan; | ||||||
| import org.springframework.context.annotation.Configuration; | import org.springframework.context.annotation.Configuration; | ||||||
|  | import org.springframework.data.redis.connection.RedisConnectionFactory; | ||||||
|  | import org.springframework.data.redis.core.StringRedisTemplate; | ||||||
| 
 | 
 | ||||||
| import javax.annotation.PostConstruct; | import javax.annotation.PostConstruct; | ||||||
| 
 | 
 | ||||||
|  | @ -44,9 +48,18 @@ public class ShortUrlAutoConfiguration { | ||||||
|     @ConditionalOnMissingBean(ShortUrlStore.class) |     @ConditionalOnMissingBean(ShortUrlStore.class) | ||||||
|     @ConditionalOnBean(ShortUrlUtil.class) |     @ConditionalOnBean(ShortUrlUtil.class) | ||||||
|     @ConditionalOnProperty(prefix = "shorturl.store", name = "store-type", havingValue = "redis") |     @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()); |         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> |             <artifactId>zy-short-url-core</artifactId> | ||||||
|             <version>1.0-SNAPSHOT</version> |             <version>1.0-SNAPSHOT</version> | ||||||
|         </dependency> |         </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> |     </dependencies> | ||||||
| 
 | 
 | ||||||
| </project> | </project> | ||||||
|  | @ -1,7 +1,6 @@ | ||||||
| package cn.shorturl.store; | package cn.shorturl.store; | ||||||
| 
 | 
 | ||||||
| import cn.shorturl.core.ShortUrl; | import cn.shorturl.core.ShortUrl; | ||||||
| import cn.shorturl.core.ShortUrlConfig; |  | ||||||
| import cn.shorturl.core.ShortUrlUtil; | import cn.shorturl.core.ShortUrlUtil; | ||||||
| 
 | 
 | ||||||
| import java.util.Date; | import java.util.Date; | ||||||
|  | @ -30,12 +29,16 @@ public abstract class ShortUrlStore { | ||||||
|      */ |      */ | ||||||
|     public ShortUrl add(String url, Date expireTime) { |     public ShortUrl add(String url, Date expireTime) { | ||||||
|         Integer max = util.getConfig().getRetryMax(); |         Integer max = util.getConfig().getRetryMax(); | ||||||
|         if (max == null) { |         if (max == null || max < 1) { | ||||||
|             max = 5; |             max = 10; | ||||||
|         } |         } | ||||||
|         ShortUrl shortUrl = new ShortUrl().setUrl(url).setGmtExpire(expireTime).setGmtCreate(new Date()); |         ShortUrl shortUrl = new ShortUrl().setUrl(url).setGmtExpire(expireTime).setGmtCreate(new Date()); | ||||||
|         for (int i = 0; i < max; i++) { |         for (int i = 0; i < max; i++) { | ||||||
|             String hash = hash(url); |             String hash = hash(url); | ||||||
|  |             if (contains(hash)) { | ||||||
|  |                 url += (int) (Math.random() * 10); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|             try { |             try { | ||||||
|                 shortUrl.setHash(hash); |                 shortUrl.setHash(hash); | ||||||
|                 add(shortUrl); |                 add(shortUrl); | ||||||
|  | @ -50,6 +53,7 @@ public abstract class ShortUrlStore { | ||||||
|     /** |     /** | ||||||
|      * 添加短链接(内部访问, 请勿外部访问) |      * 添加短链接(内部访问, 请勿外部访问) | ||||||
|      * @param shortUrl 短链接 |      * @param shortUrl 短链接 | ||||||
|  |      * @return 短链接 | ||||||
|      */ |      */ | ||||||
|     protected abstract ShortUrl add(ShortUrl shortUrl); |     protected abstract ShortUrl add(ShortUrl shortUrl); | ||||||
| 
 | 
 | ||||||
|  | @ -60,6 +64,13 @@ public abstract class ShortUrlStore { | ||||||
|      */ |      */ | ||||||
|     public abstract ShortUrl get(String hash); |     public abstract ShortUrl get(String hash); | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Hash是否已经存在 | ||||||
|  |      * @param hash Hash | ||||||
|  |      * @return 是否已经存在 | ||||||
|  |      */ | ||||||
|  |     public abstract boolean contains(String hash); | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * 对URL进行Hash编码 |      * 对URL进行Hash编码 | ||||||
|      * @param url 原链接 |      * @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; | package cn.shorturl.store.store; | ||||||
| 
 | 
 | ||||||
| import cn.shorturl.core.ShortUrl; | import cn.shorturl.core.ShortUrl; | ||||||
|  | import cn.shorturl.core.ShortUrlUtil; | ||||||
| import cn.shorturl.store.ShortUrlStore; | import cn.shorturl.store.ShortUrlStore; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  | @ -8,6 +9,9 @@ import cn.shorturl.store.ShortUrlStore; | ||||||
|  */ |  */ | ||||||
| public class JdbcShortUrlStore extends ShortUrlStore { | public class JdbcShortUrlStore extends ShortUrlStore { | ||||||
| 
 | 
 | ||||||
|  |     public JdbcShortUrlStore(ShortUrlUtil util) { | ||||||
|  |         super.util = util; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     protected ShortUrl add(ShortUrl shortUrl) { |     protected ShortUrl add(ShortUrl shortUrl) { | ||||||
|  | @ -19,4 +23,9 @@ public class JdbcShortUrlStore extends ShortUrlStore { | ||||||
|         return null; |         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.ShortUrl; | ||||||
| import cn.shorturl.core.ShortUrlUtil; | import cn.shorturl.core.ShortUrlUtil; | ||||||
| import cn.shorturl.store.ShortUrlStore; | 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 |  * @author Lenovo | ||||||
|  */ |  */ | ||||||
| public class RedisShortUrlStore extends ShortUrlStore { | 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; |         super.util = util; | ||||||
|  |         this.redisTemplate = redisTemplate; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     protected ShortUrl add(ShortUrl shortUrl) { |     protected ShortUrl add(ShortUrl shortUrl) { | ||||||
|         System.out.println(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 |     @Override | ||||||
|     public ShortUrl get(String hash) { |     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