SpringBoot之自定义启动器

));

/使用RedisCacheConfiguration创建RedisCacheManager/

RedisCacheManager manager = RedisCacheManager.builder(factory)

.cacheDefaults(cacheConfiguration)

.build();

return manager;

}

@Bean

CacheManager yzmManager(RedisConnectionFactory factory) {

RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()

.computePrefixWith(cacheName -> cacheName + “:-yzm-:”)

/设置缓存过期时间/

.entryTtl(Duration.ofSeconds(60))

/禁用缓存空值,不缓存null校验/

.disableCachingNullValues()

/设置CacheManager的值序列化方式为json序列化,可使用加入@Class属性/

.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(

new GenericJackson2JsonRedisSerializer()

));

/使用RedisCacheConfiguration创建RedisCacheManager/

RedisCacheManager manager = RedisCacheManager.builder(factory)

.cacheDefaults(cacheConfiguration)

.build();

return manager;

}

@Bean

@Primary

// redis操作对象

public RedisTemplate redisTemplate(RedisConnectionFactory factory) {

RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();

redisTemplate.setConnectionFactory(factory);

RedisSerializer stringSerializer = new StringRedisSerializer();

/* key序列化 */

redisTemplate.setKeySerializer(stringSerializer);

/* value序列化 */

redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

/* Hash key序列化 */

redisTemplate.setHashKeySerializer(stringSerializer);

/* Hash value序列化 */

redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());

redisTemplate.afterPropertiesSet();

return redisTemplate;

}

@Bean

@Primary

@Override

// 主键生成器

public KeyGenerator keyGenerator() {

return (Object target, Method method, Object… params) -> {

final int NO_PARAM_KEY = 0;

final int NULL_PARAM_KEY = 53;

StringBuilder key = new StringBuilder();

/* Class.Method: */

key.append(target.getClass().getSimpleName())

.append(“.”)

.append(method.getName())

.append(“:”);

if (params.length == 0) {

return key.append(NO_PARAM_KEY).toString();

}

int count = 0;

for (Object param : params) {

/* 参数之间用,进行分隔 */

if (0 != count) {

key.append(‘,’);

}

if (param == null) {

key.append(NULL_PARAM_KEY);

} else if (ClassUtils.isPrimitiveArray(param.getClass())) {

int length = Array.getLength(param);

for (int i = 0; i < length; i++) {

key.append(Array.get(param, i));

key.append(‘,’);

}

} else if (ClassUtils.isPrimitiveOrWrapper(param.getClass()) || param instanceof String) {

key.append(param);

} else {

/JavaBean一定要重写hashCode和equals/

key.append(param.hashCode());

}

count++;

}

return key.toString();

};

}

}

Ⅴ、导入util包

RedisUtil :

package com.lv.code.util;

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.SneakyThrows;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeansException;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import org.springframework.data.redis.RedisSystemException;

import org.springframework.data.redis.connection.DataType;

import org.springframework.data.redis.connection.RedisConnection;

import org.springframework.data.redis.connection.RedisStringCommands;

import org.springframework.data.redis.connection.ReturnType;

import org.springframework.data.redis.connection.jedis.JedisConnection;

import org.springframework.data.redis.connection.lettuce.LettuceConnection;

import org.springframework.data.redis.core.Cursor;

import org.springframework.data.redis.core.RedisOperations;

import org.springframework.data.redis.core.ScanOptions;

import org.springframework.data.redis.core.StringRedisTemplate;

import org.springframework.data.redis.core.ZSetOperations.TypedTuple;

import org.springframework.data.redis.core.types.Expiration;

import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;

import java.time.Instant;

import java.util.*;

import java.util.Map.Entry;

import java.util.concurrent.TimeUnit;

/**

  • Redis工具类

  • 声明: 此工具只简单包装了redisTemplate的大部分常用的api,没有包装redisTemplate所有的api

  • 如果对此工具类中的功能不太满意,或对StringRedisTemplate提供的api不太满意,

  • 那么可自行实现相应的{@link StringRedisTemplate}类中的对应execute方法,以达

  • 到自己想要的效果; 至于如何实现,则可参考源码或{@link LockOps}中的方法

  • 注: 此工具类依赖spring-boot-starter-data-redis类库

  • 注: 更多javadoc细节,可详见{@link RedisOperations}

  • 统一说明一: 方法中的key、 value都不能为null

  • 统一说明二: 不能跨数据类型进行操作,否者会操作失败/操作报错

  • 如: 向一个String类型的做Hash操作,会失败/报错…等等

*/

@Slf4j

@Component

@SuppressWarnings(“unused”)

public class RedisUtil implements ApplicationContextAware {

/**

  • 使用StringRedisTemplate(,其是RedisTemplate的定制化升级)

*/

private static StringRedisTemplate redisTemplate;

private static final ObjectMapper mapper = new ObjectMapper();

@Override

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

RedisUtil.redisTemplate = applicationContext.getBean(StringRedisTemplate.class);

}

/**

  • key相关操作

*/

public static class KeyOps {

/**

  • 根据key,删除redis中的对应key-value

  • 注: 若删除失败,则返回false

  • 若redis中,不存在该key,那么返回的也是false

  • 所以,不能因为返回了false,就认为redis中一定还存

  • 在该key对应的key-value

  • @param key 要删除的key

  • @return 删除是否成功

*/

public static Boolean delete(String key) {

log.info(“delete(…) => key -> {}”, key);

// 返回值只可能为true/false,不可能为null

Boolean result = redisTemplate.delete(key);

log.info(“delete(…) => result -> {}”, result);

if (result == null) {

throw new RedisOpsResultIsNullException();

}

return result;

}

/**

  • 根据keys,批量删除key-value

  • 注: 若redis中,不存在对应的key,那么计数不会加1,即:

  • redis中存在的key-value里,有名为a1、a2的key,

  • 删除时,传的集合是a1、a2、a3,那么返回结果为2

  • @param keys 要删除的key集合

  • @return 删除了的key-value个数

*/

public static long delete(Collection keys) {

log.info(“delete(…) => keys -> {}”, keys);

Long count = redisTemplate.delete(keys);

log.info(“delete(…) => count -> {}”, count);

if (count == null) {

throw new RedisOpsResultIsNullException();

}

return count;

}

/**

  • 将key对应的value值进行序列化,并返回序列化后的value值

  • 注: 若不存在对应的key,则返回null

  • 注: dump时,并不会删除redis中的对应key-value

  • 注: dump功能与restore相反

  • @param key 要序列化的value的key

  • @return 序列化后的value值

*/

public static byte[] dump(String key) {

log.info(“dump(…) =>key -> {}”, key);

byte[] result = redisTemplate.dump(key);

log.info(“dump(…) => result -> {}”, result);

return result;

}

/**

  • 将给定的value值,反序列化到redis中,形成新的key-value

  • @param key value对应的key

  • @param value 要反序列的value值

  •               注: 这个值可以由{@link this#dump(String)}获得
    
  • @param timeToLive 反序列化后的key-value的存活时长

  • @param unit timeToLive的单位

  • @throws RedisSystemException 如果redis中已存在同样的key时,抛出此异常

*/

public static void restore(String key, byte[] value, long timeToLive, TimeUnit unit) {

restore(key, value, timeToLive, unit, false);

}

/**

  • 将给定的value值,反序列化到redis中,形成新的key-value

  • @param key value对应的key

  • @param value 要反序列的value值

  •            注: 这个值可以由{@link this#dump(String)}获得
    
  • @param timeout 反序列化后的key-value的存活时长

  • @param unit timeout的单位

  • @param replace 若redis中已经存在了相同的key,是否替代原来的key-value

  • @throws RedisSystemException 如果redis中已存在同样的key,且replace为false时,抛出此异常

*/

public static void restore(String key, byte[] value, long timeout, TimeUnit unit, boolean replace) {

log.info(“restore(…) => key -> {},value -> {},timeout -> {},unit -> {},replace -> {}”,

key, value, timeout, unit, replace);

redisTemplate.restore(key, value, timeout, unit, replace);

}

/**

  • redis中是否存在,指定key的key-value

  • @param key 指定的key

  • @return 是否存在对应的key-value

*/

public static boolean hasKey(String key) {

log.info(“hasKey(…) => key -> {}”, key);

Boolean result = redisTemplate.hasKey(key);

log.info(“hasKey(…) => result -> {}”, result);

if (result == null) {

throw new RedisOpsResultIsNullException();

}

return result;

}

/**

  • 给指定的key对应的key-value设置: 多久过时

  • 注:过时后,redis会自动删除对应的key-value

  • 注:若key不存在,那么也会返回false

  • @param key 指定的key

  • @param timeout 过时时间

  • @param unit timeout的单位

  • @return 操作是否成功

*/

public static boolean expire(String key, long timeout, TimeUnit unit) {

log.info(“expire(…) => key -> {},timeout -> {},unit -> {}”, key, timeout, unit);

Boolean result = redisTemplate.expire(key, timeout, unit);

log.info(“expire(…) => result is -> {}”, result);

if (result == null) {

throw new RedisOpsResultIsNullException();

}

return result;

}

/**

  • 给指定的key对应的key-value设置: 什么时候过时

  • 注:过时后,redis会自动删除对应的key-value

  • 注:若key不存在,那么也会返回false

  • @param key 指定的key

  • @param date 啥时候过时

  • @return 操作是否成功

*/

public static boolean expireAt(String key, Date date) {

log.info(“expireAt(…) => key -> {},date -> {}”, key, date);

Boolean result = redisTemplate.expireAt(key, date);

log.info(“expireAt(…) => result is -> {}”, result);

if (result == null) {

throw new RedisOpsResultIsNullException();

}

return result;

}

/**

  • 找到所有匹配pattern的key,并返回该key的结合.

  • 提示:若redis中键值对较多,此方法耗时相对较长,慎用!慎用!慎用!

  • @param pattern 匹配模板

  •            注: 常用的通配符有:
    
  •            ?    有且只有一个;
    
  •            *     >=0个;
    
  • @return 匹配pattern的key的集合 可能为null

*/

public static Set keys(String pattern) {

log.info(“keys(…) => pattern -> {}”, pattern);

Set keys = redisTemplate.keys(pattern);

log.info(“keys(…) => keys -> {}”, keys);

return keys;

}

/**

  • 将当前数据库中的key对应的key-value,移动到对应位置的数据库中

  • 注:单机版的redis,默认将存储分为16个db,index为0 到 15

  • 注:同一个db下,key唯一; 但是在不同db中,key可以相同

  • 注:若目标db下,已存在相同的key,那么move会失败,返回false

  • @param key 定位要移动的key-value的key

  • @param dbIndex 要移动到哪个db

  • @return 移动是否成功

  • 注: 若目标db下,已存在相同的key,那么move会失败,返回false

*/

public static boolean move(String key, int dbIndex) {

log.info(“move(…) => key -> {},dbIndex -> {}”, key, dbIndex);

Boolean result = redisTemplate.move(key, dbIndex);

log.info(“move(…) =>result -> {}”, result);

if (result == null) {

throw new RedisOpsResultIsNullException();

}

return result;

}

/**

  • 移除key对应的key-value的过期时间,使该key-value一直存在

  • 注: 若key对应的key-value,本身就是一直存在(无过期时间的),那么persist方法会返回false;

  • 若没有key对应的key-value存在,本那么persist方法会返回false;

  • @param key 定位key-value的key

  • @return 操作是否成功

*/

public static boolean persist(String key) {

log.info(“persist(…) => key -> {}”, key);

Boolean result = redisTemplate.persist(key);

log.info(“persist(…) => result -> {}”, result);

if (result == null) {

throw new RedisOpsResultIsNullException();

}

return result;

}

/**

  • 获取key对应的key-value的过期时间

  • 注: 若key-value永不过期,那么返回的为-1

  • 注: 若不存在key对应的key-value,那么返回的为-2

  • 注:若存在零碎时间不足1 SECONDS,则(大体上)四舍五入到SECONDS级别

  • @param key 定位key-value的key

  • @return 过期时间(单位s)

*/

public static long getExpire(String key) {

return getExpire(key, TimeUnit.SECONDS);

}

/**

  • 获取key对应的key-value的过期时间

  • 注: 若key-value永不过期,那么返回的为-1

  • 注: 若不存在key对应的key-value,那么返回的为-2

  • 注:若存在零碎时间不足1 unit,则(大体上)四舍五入到unit别

  • @param key 定位key-value的key

  • @return 过期时间(单位unit)

*/

public static long getExpire(String key, TimeUnit unit) {

log.info(“getExpire(…) =>key -> {},unit is -> {}”, key, unit);

Long result = redisTemplate.getExpire(key, unit);

log.info(“getExpire(…) => result -> {}”, result);

if (result == null) {

throw new RedisOpsResultIsNullException();

}

return result;

}

/**

  • 从redis的所有key中,随机获取一个key

  • 注: 若redis中不存在任何key-value,那么这里返回null

  • @return 随机获取到的一个key

*/

public static String randomKey() {

String result = redisTemplate.randomKey();

log.info(“randomKey(…) => result is -> {}”, result);

return result;

}

/**

  • 重命名对应的oldKey为新的newKey

  • 注: 若oldKey不存在,则会抛出异常.

  • 注: 若redis中已存在与newKey一样的key,

  • 那么原key-value会被丢弃,

  • 只留下新的key,以及原来的value

  • 示例说明: 假设redis中已有 (keyAlpha,valueAlpha) 和 (keyBeta,valueBeat),

  • 在使用rename(keyAlpha,keyBeta)替换后,redis中只会剩下(keyBeta,valueAlpha)

  • @param oldKey 旧的key

  • @param newKey 新的key

  • @throws RedisSystemException 若oldKey不存在时,抛出此异常

*/

public static void rename(String oldKey, String newKey) {

log.info(“rename(…) => oldKey -> {},newKey -> {}”, oldKey, newKey);

redisTemplate.rename(oldKey, newKey);

}

/**

  • 当redis中不存在newKey时,重命名对应的oldKey为新的newKey

  • 否者不进行重命名操作

  • 注: 若oldKey不存在,则会抛出异常.

  • @param oldKey 旧的key

  • @param newKey 新的key

  • @throws RedisSystemException 若oldKey不存在时,抛出此异常

*/

public static boolean renameIfAbsent(String oldKey, String newKey) {

log.info(“renameIfAbsent(…) => oldKey -> {},newKey -> {}”, oldKey, newKey);

Boolean result = redisTemplate.renameIfAbsent(oldKey, newKey);

log.info(“renameIfAbsent(…) => result -> {}”, result);

if (result == null) {

throw new RedisOpsResultIsNullException();

}

return result;

}

/**

  • 获取key对应的value的数据类型

  • 注: 若redis中不存在该key对应的key-value,那么这里返回NONE

  • @param key 用于定位的key

  • @return key对应的value的数据类型

*/

public static DataType type(String key) {

log.info(“type(…) => key -> {}”, key);

DataType result = redisTemplate.type(key);

log.info(“type(…) => result -> {}”, result);

return result;

}

}

/**

  • string相关操作

*/

public static class StringOps {

/**

  • 设置key-value

  • 注: 若已存在相同的key,那么原来的key-value会被丢弃

  • @param key key

  • @param value key对应的value

*/

public static void set(String key, String value) {

log.info(“set(…) => key -> {},value -> {}”, key, value);

redisTemplate.opsForValue().set(key, value);

}

/**

  • 处理redis中key对应的value值,将第offset位的值,设置为1或0

  • 说明: 在redis中,存储的字符串都是以二级制的进行存在的; 如存储的key-value里,值为abc,实际上,

  • 在redis里面存储的是011000010110001001100011,前8为对应a,中间8为对应b,后面8位对应c

  • 示例:这里如果setBit(key,6,true)的话,就是将索引位置6的那个数,设置值为1,值就变成

  • 了011000110110001001100011

  • 追注:offset即index,从0开始

  • 注: 参数value为true,则设置为1;参数value为false,则设置为0

  • 注: 若redis中不存在对应的key,那么会自动创建新的

  • 注: offset可以超过value在二进制下的索引长度

  • @param key 定位value的key

  • @param offset 要改变的bit的索引

  • @param value 改为1或0,true - 改为1,false - 改为0

  • @return set是否成功

*/

public static boolean setBit(String key, long offset, boolean value) {

log.info(“setBit(…) => key -> {},offset -> {},value -> {}”, key, offset, value);

Boolean result = redisTemplate.opsForValue().setBit(key, offset, value);

log.info(“setBit(…) => result -> {}”, result);

if (result == null) {

throw new RedisOpsResultIsNullException();

}

return result;

}

/**

  • 设置key-value

  • 注: 若已存在相同的key,那么原来的key-value会被丢弃

  • @param key key

  • @param value key对应的value

  • @param timeout 过时时长

  • @param unit timeout的单位

*/

public static void setEx(String key, String value, long timeout, TimeUnit unit) {

log.info(“setEx(…) => key -> {},value -> {},timeout -> {},unit -> {}”,

key, value, timeout, unit);

redisTemplate.opsForValue().set(key, value, timeout, unit);

}

/**

  • 若不存在key时,向redis中添加key-value,返回成功/失败

  • 若存在,则不作任何操作,返回false

  • @param key key

  • @param value key对应的value

  • @return set是否成功

*/

public static boolean setIfAbsent(String key, String value) {

log.info(“setIfAbsent(…) => key -> {},value -> {}”, key, value);

Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value);

log.info(“setIfAbsent(…) => result -> {}”, resul

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值