使用步骤
1、引入依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <!-- SpringBoot redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <!-- jackson --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-json</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
2、自增ID生成类
import org.springframework.data.redis.core.*; import org.springframework.data.redis.support.atomic.RedisAtomicLong; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.Serializable; import java.util.Date; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; @Service public class RedisUtilService { @Resource private RedisTemplate redisTemplate; /** * @Title: generate * @Description: Atomically increments by one the current value. * @param key * @return */ public long generate(String key) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); return counter.incrementAndGet(); } /** * @Title: generate * @Description: Atomically increments by one the current value. * @param key * @return */ public long generate(String key,Date expireTime) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); counter.expireAt(expireTime); return counter.incrementAndGet(); } /** * @Title: generate * @Description: Atomically adds the given value to the current value. * @param key * @param increment * @return */ public long generate(String key,int increment) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); return counter.addAndGet(increment); } /** * @Title: generate * @Description: Atomically adds the given value to the current value. * @param key * @param increment * @param expireTime * @return */ public long generate(String key,int increment,Date expireTime) { RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); counter.expireAt(expireTime); return counter.addAndGet(increment); } /** * 刷新缓存时间 * @param key * @param expireTime * @param timeUnit * @return */ public boolean expire(final String key, Long expireTime ,TimeUnit timeUnit) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 写入缓存 * @param key * @param value * @return */ public boolean set(final String key, Object value) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); operations.set(key, value); // System.out.println("11"+operations.get(key)); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 写入缓存设置时效时间 * @param key * @param value * @return */ public boolean set(final String key, Object value, Long expireTime ,TimeUnit timeUnit) { boolean result = false; try { ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); operations.set(key, value); redisTemplate.expire(key, expireTime, timeUnit); // System.out.println("11"+operations.get(key)); result = true; } catch (Exception e) { e.printStackTrace(); } return result; } /** * 批量删除对应的value * @param keys */ public void remove(final String... keys) { for (String key : keys) { remove(key); } } /** * 批量删除key * @param pattern */ public void removePattern(final String pattern) { Set<Serializable> keys = redisTemplate.keys(pattern); if (keys.size() > 0){ redisTemplate.delete(keys); } } /** * 删除对应的value * @param key */ public void remove(final String key) { if (exists(key)) { redisTemplate.delete(key); } } /** * 判断缓存中是否有对应的value * @param key * @return */ public boolean exists(final String key) { return redisTemplate.hasKey(key); } /** * 读取缓存 * @param key * @return */ public Object get(final String key) { Object result = null; ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue(); result = operations.get(key); return result; } /** * 哈希 添加 * @param key * @param hashKey * @param value */ public void hmSet(String key, Object hashKey, Object value){ HashOperations<String, Object, Object> hash = redisTemplate.opsForHash(); hash.put(key,hashKey,value); } /** * 哈希获取数据 * @param key * @param hashKey * @return */ public Object hmGet(String key, Object hashKey){ HashOperations<String, Object, Object> hash = redisTemplate.opsForHash(); return hash.get(key,hashKey); } /** * 列表添加 * @param k * @param v */ public void lPush(String k,Object v){ ListOperations<String, Object> list = redisTemplate.opsForList(); list.rightPush(k,v); } /** * 列表获取 * @param k * @param l * @param l1 * @return */ public List<Object> lRange(String k, long l, long l1){ ListOperations<String, Object> list = redisTemplate.opsForList(); return list.range(k,l,l1); } /** * 集合添加 * @param key * @param value */ public void add(String key,Object value){ SetOperations<String, Object> set = redisTemplate.opsForSet(); set.add(key,value); } /** * 集合获取 * @param key * @return */ public Set<Object> setMembers(String key){ SetOperations<String, Object> set = redisTemplate.opsForSet(); return set.members(key); } /** * 有序集合添加 * @param key * @param value * @param scoure */ public void zAdd(String key,Object value,double scoure){ ZSetOperations<String, Object> zset = redisTemplate.opsForZSet(); zset.add(key,value,scoure); } /** * 有序集合获取 * @param key * @param scoure * @param scoure1 * @return */ public Set<Object> rangeByScore(String key,double scoure,double scoure1){ ZSetOperations<String, Object> zset = redisTemplate.opsForZSet(); return zset.rangeByScore(key, scoure, scoure1); } }
3、RedisTemplate配置
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import java.lang.reflect.Method; @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public KeyGenerator wiselyKeyGenerator() { return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { StringBuilder sb = new StringBuilder(); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); } }; } @Bean public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) { StringRedisTemplate template = new StringRedisTemplate(factory); setSerializer(template); //设置序列化工具,这样ReportBean不需要实现Serializable接口 template.afterPropertiesSet(); return template; } /** * TODO 监听 Redis键过期事件 * @author zhuzhen * @date 14:38 2018/12/21 * @param factory * @return org.springframework.data.redis.listener.RedisMessageListenerContainer */ @Bean RedisMessageListenerContainer container(RedisConnectionFactory factory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(factory); return container; } private void setSerializer(StringRedisTemplate template) { Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setValueSerializer(jackson2JsonRedisSerializer); } }
4、SerialNumber序列号生成工具类
import java.text.SimpleDateFormat; import java.util.Date; public class SerialNumber { static final int DEFAULT_LENGTH = 4; /** * * @param prefix (前缀) * @param redisKey (redis key) * @return */ public static String generate(String prefix,String data, long redisKey) { //** 自增 *//* String seq = getSequence(redisKey); StringBuilder sb = new StringBuilder(); sb.append(prefix).append(data).append(seq); String serial = sb.toString(); return serial; } /** * 填充000 * * @param seq * @return */ public static String getSequence(long seq) { String str = String.valueOf(seq); int len = str.length(); if (len >= DEFAULT_LENGTH) {// 取决于业务规模,应该不会到达4 return str; } int rest = DEFAULT_LENGTH - len; StringBuilder sb = new StringBuilder(); for (int i = 0; i < rest; i++) { sb.append('0'); } sb.append(str); return sb.toString(); } /** * 得到系统当前日期 * "yyyyMMdd" */ public static String getCurentDate() { SimpleDateFormat tempDate = new SimpleDateFormat("yyyyMMdd"); String datetime = tempDate.format(new Date()); return datetime; } }
5、测试类
@RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class RedisAtomicLongTest { @Autowired private RedisUtilService redisUtilService; @Test public void test1(){ String curentDate = SerialNumber.getCurentDate(); String key = "serial.number.ghpc:" + curentDate; long generate = redisUtilService.generate(key,getTodayEndTime()); System.out.println(generate); String ghpcNumber = SerialNumber.generate("", curentDate, generate); System.out.println(ghpcNumber); } private static Date getTodayEndTime() { Calendar todayEnd = Calendar.getInstance(); todayEnd.set(Calendar.HOUR_OF_DAY, 23); todayEnd.set(Calendar.MINUTE, 59); todayEnd.set(Calendar.SECOND, 59); todayEnd.set(Calendar.MILLISECOND, 999); return todayEnd.getTime(); } }
注意:由于key为当天的,故最好设置过期时间,否则该键值对会永久存在。该自增ID缓存的key为“serial.number.ghpc:8位日期”,并且该缓存在当天23:59:59:999时会自动过期,过期后会重置为0。
第一次运行的结果为:
1 202202280001
第二次运行的结果:
2 202202280002
第三次运行的结果:
3 202202280003