SpringBoot+Redis使用jedis实现了对Redis基本类型操作超全工具类

这编文章主要介绍了springboot整合redis,使用jedis实现了对Redis基本类型操作,一些redis的常用命令总结到了一个公共的工具类中,其中使用了fastjson作为了序列化工具。
注:使用了 jdk 1.8 新特性 ,jdk版本需要>=1.8

一.添加maven依赖

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.12.RELEASE</version></parent><!--统一版本号配置 --><properties><fastjson.version>1.2.47</fastjson.version><redis.clients.version>2.9.0</redis.clients.version></properties><dependencies><!-- springBoot 相关 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency><!-- redis client --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>${redis.clients.version}</version></dependency><!-- json --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency></dependencies>

二.配置文件
创建一个application.properties 配置文件

#端口配置
server.port=8081#redis 基础配置
# Redis数据库索引(默认为0)
spring.redis.database=1
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接密码(默认为空)
spring.redis.password=123456
# Redis服务器连接端口
spring.redis.port=6379
# 连接超时时间(毫秒)
spring.redis.timeout=0#redis 连接池配置
#池中最大链接数
spring.redis.pool-config.max-total=256
# 连接池中的最大空闲连接
spring.redis.pool-config.max-idle=128
# 连接池中的最小空闲连接
spring.redis.pool-config.min-idle=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool-config.max-wait-millis=1000
# 调用者获取链接时,是否检测当前链接有效性
spring.redis.pool-config.test-on-borrow=false
# 向链接池中归还链接时,是否检测链接有效性
spring.redis.pool-config.test-on-return=false
# 调用者获取链接时,是否检测空闲超时, 如果超时,则会被移除-
spring.redis.pool-config.test-while-idle=true
# 空闲链接检测线程一次运行检测多少条链接
spring.redis.pool-config.num-tests-per-eviction-run=8
#空闲链接检测线程检测周期。如果为负值,表示不运行检测线程。(单位:毫秒,默认为-1)
spring.redis.pool-config.time-between-eviction-runs-millis=60000
#配置一个连接在池中最小生存的时间,单位是毫秒
spring.redis.pool-config.min-evictable-idle-time-millis=300000#spring-session
spring.session.store-type=none
#日志配置
logging.level.root=WARN
logging.level.net.sf=WARN
logging.level.com.boot.redis=TRACE

三、代码实现
1)创建启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
/*** 启动类* springboot启动时会自动注入数据源和配置jpa 在不连接数据库情况下需要移除*/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

由于不需要使用mysql等数据库所以移除默认数据源配置

2)创建一个RedisConfigProperties的配置类方便直接使用配置的参数

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/*** redis 配置属性类*/
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConfigProperties {/*** Redis服务器地址*/private String host;/*** Redis服务器连接密码(默认为空)*/private String password;/*** Redis数据库索引(默认为0)*/private int database;/*** Redis服务器连接端口*/private int port;/*** 连接超时时间(毫秒)*/private int timeout;//省略 get/set方法
}

3)创建JedisConfig

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/*** 配置类*/
@Configuration
public class JedisConfig extends CachingConfigurerSupport {private Logger LOGGER = LoggerFactory.getLogger(JedisConfig.class);@Autowiredprivate RedisConfigProperties redisConfigProperties;@Bean(name = "jedisPoolConfig")@ConfigurationProperties(prefix = "spring.redis.pool-config")public JedisPoolConfig getRedisConfig() {JedisPoolConfig config = new JedisPoolConfig();return config;}@Bean(name = "jedisPool")public JedisPool jedisPool(@Qualifier(value = "jedisPoolConfig") final JedisPoolConfig jedisPoolConfig) {LOGGER.info("Jedis Pool build start ");String host = redisConfigProperties.getHost();Integer timeout = redisConfigProperties.getTimeout();int port = redisConfigProperties.getPort();String password = redisConfigProperties.getPassword();int database = redisConfigProperties.getDatabase();JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, timeout, password, database);LOGGER.info("Jedis Pool build success  host={} , port={}", host, port);return jedisPool;}
}

创建序列化工具类

import com.alibaba.fastjson.JSON;
import java.nio.charset.Charset;
/*** json  Serializer util*/
public class JsonSerializer {public static final String UTF_8 = "UTF-8";/*** @param obj* @param <T>* @return*/@SuppressWarnings("unchecked")public static <T> byte[] serialize(T obj) {return JSON.toJSONString(obj).getBytes(Charset.forName(UTF_8));}/*** @param data* @param clazz* @param <T>* @return*/public static <T> T deserialize(byte[] data, Class<T> clazz) {return JSON.parseObject(data, clazz);}
}

创建时间计算工具类

import java.util.concurrent.TimeUnit;
/*** 时间计算工具类*/
public class TimeUnitUtil {/*** 时间秒数计算** @param timeUnit 单位枚举* @param duration 时间量* @return 秒数*/public static int getSeconds(TimeUnit timeUnit, int duration) {return (int) timeUnit.toSeconds(duration);}/*** 时间毫秒数计算** @param timeUnit 单位枚举* @param duration 时间量* @return 毫秒数*/public static long getMillis(TimeUnit timeUnit, int duration) {return timeUnit.toMillis(duration);}
}

创建时间戳工具类SystemClock

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
/*** 高并发场景下System.currentTimeMillis()的性能问题的优化* 时间戳打印建议使用*/
public class SystemClock {private static final String THREAD_NAME = "system.clock";private static final SystemClock MILLIS_CLOCK = new SystemClock(1);private final long precision;private final AtomicLong now;private SystemClock(long precision) {this.precision = precision;now = new AtomicLong(System.currentTimeMillis());scheduleClockUpdating();}public static SystemClock millisClock() {return MILLIS_CLOCK;}private void scheduleClockUpdating() {ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> {Thread thread = new Thread(runnable, THREAD_NAME);thread.setDaemon(true);return thread;});scheduler.scheduleAtFixedRate(() -> now.set(System.currentTimeMillis()), precision, precision, TimeUnit.MILLISECONDS);}public long now() {return now.get();}
}

这里未使用 java 自带的 System.currentTimeMillis() 作为时间戳,
具体原因请至上一篇博客https://blog.csdn.net/qq_38011415/article/details/82813299

创建redis 客户端接口

import redis.clients.jedis.Jedis;
import java.io.IOException;
public interface RedisClientInvoker<T> {T invoke(Jedis jedis) throws IOException;
}

创建redis 客户端工具类

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisException;
import java.io.IOException;
@Component
public class RedisClient {private static final Logger LOGGER = LoggerFactory.getLogger(RedisClient.class);public <T> T invoke(JedisPool pool, RedisClientInvoker<T> clients) {T obj = null;Jedis jedis = null;boolean broken = false;try {jedis = pool.getResource();obj = clients.invoke(jedis);} catch (JedisException | IOException ex) {LOGGER.error(ex.getMessage(), ex);} finally {if (jedis != null) {if (jedis.isConnected())jedis.close();}}return obj;}
}

创建Redis缓存实现公共工具类

import com.alibaba.fastjson.JSONArray;
import com.boot.redis.util.JsonSerializer;
import com.boot.redis.util.SystemClock;
import com.boot.redis.util.TimeUnitUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import redis.clients.jedis.BinaryJedis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.TimeUnit;@Component
public class RedisCache {private static final Logger LOGGER = LoggerFactory.getLogger(RedisCache.class);private static final int ZERO = 0;private static final int FIVE = 5;private static final String OK = "OK";private static final Long LONG_ZERO = 0l;/*** 默认失效时间5 分钟*/public static final int DEFAULT_CACHE_SECONDS = TimeUnitUtil.getSeconds(TimeUnit.SECONDS, FIVE);/*** 默认失效时间毫秒 5 分钟*/public static final long DEFAULT_CACHE_MILLIS = TimeUnitUtil.getMillis(TimeUnit.MINUTES, FIVE);@Autowiredprivate JedisPool jedisPool;@Autowiredprivate RedisClient redisClient;/**------------------key 普通 相关操作--------------------------------*//*** 是否存在校验** @param key* @return 是否存在*/public boolean exists(String key) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.exists(key.getBytes()));}/*** 用于设置 key 的过期时间,* key 过期后将不再可用。单位以秒计** @param key* @return 是否设置成功*/public Boolean expire(String key, int seconds) {return this.expire(key, seconds, TimeUnit.SECONDS);}/*** 用于设置 key 的过期时间,key 过期后将不再可用。* 设置成功返回 1* 当 key 不存在或者不能为 key 设置过期时间时返回 0* <p>* 时间枚举介绍* TimeUnit.DAYS          //天* TimeUnit.HOURS         //小时* TimeUnit.MINUTES       //分钟* TimeUnit.SECONDS       //秒* TimeUnit.MILLISECONDS  //毫秒* TimeUnit.NANOSECONDS   //毫微秒* TimeUnit.MICROSECONDS  //微秒** @param key* @param duration 时间量与单位一起使用* @param timeUnit 单位枚举类* @return*/public Boolean expire(String key, int duration, TimeUnit timeUnit) {validateKeyParam(key);//时间转换成毫秒long millis = TimeUnitUtil.getMillis(timeUnit, duration);Long lResult = redisClient.invoke(jedisPool, (jedis) -> jedis.pexpire(key.getBytes(), millis));if (LONG_ZERO.equals(lResult)) {return false;}return true;}/*** 根据key 获取过期时间秒数* 不存在时返回负数** @param key* @return 剩余过期时间秒数* 当 key 不存在时,返回 -2 。* 当 key 存在但没有设置剩余生存时间时,返回 -1 。* 否则,以秒为单位,返回 key 的剩余生存时间*/public Long getExpiresTtl(String key) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.ttl(key.getBytes()));}/*** 根据key 获取过期时间毫秒数* 不存在时返回负数** @param key* @return 剩余过期时间毫秒数* 当 key 不存在时,返回 -2* 当 key 存在但没有设置剩余生存时间时,返回 -1* 否则,以毫秒为单位,返回 key 的剩余生存时间*/public Long getExpiresPttl(String key) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.pttl(key.getBytes()));}/*** 移除 key 的过期时间,key 将持久保持。* 当过期时间移除成功时,返回 1* 如果 key 不存在或 key 没有设置过期时间,返回 0** @param key*/public Long persist(String key) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.persist(key.getBytes()));}/*** 根据key 获取存储类型** @param key* @return 返回 key 的数据类型,数据类型有:* none (key不存在)* string (字符串)* list (列表)* set (集合)* zset (有序集)* hash (哈希表)*/public String getType(String key) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.type(key.getBytes()));}/*** 根据key移除** @param key*/public void remove(String key) {validateKeyParam(key);if (exists(key)) {redisClient.invoke(jedisPool, (jedis) -> jedis.del(key.getBytes()));}}/**------------------字符串相关操作--------------------------------*//*** 添加数据到redis* 设置默认过期时间  5 分钟** @param key* @param value*/public Boolean put(String key, Object value) {return put(key, value, FIVE, TimeUnit.MINUTES);}/*** 添加数据到redis* 自定义过期时间* 注:从 Redis 2.6.12 版本开始, SET 在设置操作成功完成时,返回 OK** @param key* @param value* @param duration 时间量* @param timeUnit 时间单位枚举*/public Boolean put(String key, Object value, int duration, TimeUnit timeUnit) {validateParam(key, value);String result = redisClient.invoke(jedisPool, (jedis) -> {String srtResult = jedis.set(key.getBytes(), JsonSerializer.serialize(value));if (duration <= ZERO) {//默认5 分钟jedis.pexpire(key.getBytes(), DEFAULT_CACHE_MILLIS);} else {//时间转换成毫秒long millis = TimeUnitUtil.getMillis(timeUnit, duration);jedis.pexpire(key.getBytes(), millis);}return srtResult;});if (OK.equals(result)) {return true;}return false;}/*** 添加数据到redis* 并设置永不过期* 注:一般使用较少,数据过大时尽量不要使用* 从 Redis 2.6.12 版本开始, SET 在设置操作成功完成时,返回 OK** @param key* @param value*/public Boolean putNeverExpires(String key, Object value) {validateParam(key, value);String result = redisClient.invoke(jedisPool, (jedis) -> {String srtResult = jedis.set(key.getBytes(), JsonSerializer.serialize(value));return srtResult;});if (OK.equals(result)) {return true;}return false;}/*** 根据key 获取值** @param key* @param clazz 类class* @return 类对象*/public <T> T get(String key, Class<T> clazz) {validateKeyParam(key);byte[] result = redisClient.invoke(jedisPool, (jedis) -> jedis.get(key.getBytes()));if (result == null) {return null;}return JsonSerializer.deserialize(result, clazz);}/*** 根据key 获取值* 返回 key 的值,如果 key 不存在时,返回 nil。* 如果 key 不是字符串类型,那么返回一个错误。** @param key* @return String*/public String get(String key) {return this.get(key, String.class);}/*** 根据key 获取值** @param key* @param clazz 集合泛型对象* @return 集合对象*/public <T> List<T> getList(String key, Class<T> clazz) {String str = this.get(key, String.class);return JSONArray.parseArray(str, clazz);}/*** 将key 的值设为 value ,当且仅当 key 不存在* more值是时间戳 默认有效期是 5 分钟** @param key* @return 设置成功返回 true 失败返回false*/public boolean setNx(String key) {return this.setNx(key, SystemClock.millisClock().now(), FIVE, TimeUnit.MINUTES);}/*** 将key 的值设为 value ,当且仅当 key 不存在* 默认有效期是 5 分钟** @param key* @param value 自定义值* @return 设置成功返回 true 失败返回false*/public boolean setNx(String key, Object value) {return this.setNx(key, value, FIVE, TimeUnit.MINUTES);}/*** 将key 的值设为 value ,当且仅当 key 不存在* more值是时间戳** @param key* @param seconds 自定义过期时间秒数* @return 设置成功返回 true 失败返回false*/public boolean setNx(String key, int seconds) {return this.setNx(key, SystemClock.millisClock().now(), seconds, TimeUnit.SECONDS);}/*** 将key 的值设为 value ,当且仅当 key 不存在* 默认时间单位是秒** @param key* @param value   自定义 value* @param seconds 自定义过期时间秒数* @return 设置成功返回 true 失败返回false*/public boolean setNx(String key, Object value, int seconds) {return this.setNx(key, value, seconds, TimeUnit.SECONDS);}/*** 将key 的值设为 value ,当且仅当 key 不存在* 注:常用与分布式锁** @param key* @param value* @param duration 时间量* @param timeUnit 时间单位枚举* @return 设置成功返回 true 失败返回false*/public boolean setNx(String key, Object value, int duration, TimeUnit timeUnit) {validateParam(key, value);return redisClient.invoke(jedisPool, (jedis) -> {long result = jedis.setnx(key.getBytes(), JsonSerializer.serialize(value));if (result >= 1) {if (duration <= ZERO) {//默认5 分钟jedis.pexpire(key.getBytes(), DEFAULT_CACHE_MILLIS);return true;} else {//时间转换成毫秒long millis = TimeUnitUtil.getMillis(timeUnit, duration);jedis.pexpire(key.getBytes(), millis);return true;}} else {return false;}});}/*** 设置指定 key 的值,并返回 key 的旧值* 返回给定 key 的旧值。 当 key 没有旧值时,即 key 不存在时,返回 null* 注:默认有效期为 5分钟** @param key* @return String*/public String getSet(String key, String value) {return this.getSet(key, value, FIVE, TimeUnit.MINUTES);}/*** 设置指定 key 的值,并返回 key 的旧值* 返回给定 key 的旧值。 当 key 没有旧值时,即 key 不存在时,返回 null** @param key* @return string key 的旧值*/public String getSet(String key, String value, int duration, TimeUnit timeUnit) {validateParam(key, value);return redisClient.invoke(jedisPool, (jedis) -> {String result = jedis.getSet(key, value);if (duration <= ZERO) {//设置默认过期时间 5 分钟jedis.pexpire(key.getBytes(), DEFAULT_CACHE_MILLIS);return result;} else {//时间转换成毫秒long millis = TimeUnitUtil.getMillis(timeUnit, duration);jedis.pexpire(key.getBytes(), millis);return result;}});}/*** 用于获取指定 key 所储存的字符串值的长度。* 当 key 储存的不是字符串值时,返回一个错误* 当 key 不存在时,返回 0** @param key*/public Long getStrLen(String key) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.strlen(key.getBytes()));}/*** key 中储存的数字值增一 (默认增量+1)* 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。* 注:* 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。* 本操作的值限制在 64 位(bit)有符号数字表示之内** @param key* @return 执行命令之后 key 的值。*/public Long incr(String key) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.incr(key.getBytes()));}/*** key 中储存的数字值增一 (自定义增量值 )* 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。* 注:* 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。* 本操作的值限制在 64 位(bit)有符号数字表示之内** @param key* @param value 自定义增量值* @return 执行命令之后 key 的值。*/public Long incr(String key, long value) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.incrBy(key.getBytes(), value));}/*** 为 key 中所储存的值加上指定的浮点数增量值* 如果 key 不存在,那么 incrbyfloat 会先将 key 的值设为 0 ,再执行加法操作。** @param key* @param value 增量值* @return 执行命令之后 key 的值。*/public Double incr(String key, Double value) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.incrByFloat(key.getBytes(), value));}/*** 将 key 中储存的数字值减一* <p>* 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECR 操作。* 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。* 本操作的值限制在 64 位(bit)有符号数字表示之内。** @param key* @return 执行命令之后 key 的值。*/public Long decr(String key) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.decr(key.getBytes()));}/*** 将 key 中储存的数字值减一* <p>* 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECR 操作。* 如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。* 本操作的值限制在 64 位(bit)有符号数字表示之内。** @param key* @param value 自定义减量值* @return 执行命令之后 key 的值。*/public Long decr(String key, long value) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.decrBy(key.getBytes(), value));}/*** 用于为指定的 key 追加值。* <p>* 如果 key 已经存在并且是一个字符串, APPEND 命令将 value* 追加到 key 原来的值的末尾。* 如果 key 不存在, APPEND 就简单地将给定 key 设为 value ,* 就像执行 SET key value 一样。** @param key* @param value* @return 追加指定值之后, key 中字符串的长度。*/public Long append(String key, Object value) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> jedis.append(key.getBytes(), JsonSerializer.serialize(value)));}/**------------------zSet相关操作--------------------------------*//*** 添加元素到有序集合,有序集合是按照元素的score进行排列* 注意: 在 Redis 2.4 版本以前, ZADD 每次只能添加一个元素。* 当 key 存在但不是有序集类型时,返回一个错误。** @param key* @param obj* @param score 分值*/public void zAddByScore(String key, Object obj, double score) {validateParam(key, obj);redisClient.invoke(jedisPool, jedis -> {jedis.zadd(key.getBytes(), score, JsonSerializer.serialize(obj));return null;});}/*** 根据key 计算集合中元素的数量** @param key* @return 当 key 存在且是有序集类型时,返回有序集的基数。 当 key 不存在时,返回 0*/public long zCard(String key) {validateKeyParam(key);long count = redisClient.invoke(jedisPool, jedis -> {long result = jedis.zcard(key.getBytes());return result;});return count;}/*** 根据key 计算在有序集合中指定区间分数的成员数** @param key* @param minScore 最小排序分值* @param maxScore 最大排序分值* @return 分数值在 min 和 max 之间的成员的数量。*/public long zCount(String key, double minScore, double maxScore) {validateKeyParam(key);long count = redisClient.invoke(jedisPool, jedis -> {long result = jedis.zcount(key.getBytes(), minScore, maxScore);return result;});return count;}/*** 返回有序集中,指定区间内的成员 -> 从小到大* 其中成员的位置按分数值递增(从小到大)来排序* <p>* 具有相同分数值的成员按字典序来排列* 注意:下标参数0 为起始* 负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推** @param key* @param clazz* @param start 开始位置* @param end   结束位置* @return 相应对象集合*/public <T> List<T> zRange(String key, Class<T> clazz, int start, int end) {validateKeyParam(key);List<T> result = redisClient.invoke(jedisPool, jedis -> {Set<byte[]> set = jedis.zrange(key.getBytes(), start, end);List<T> list = new ArrayList<>(set.size());if (CollectionUtils.isEmpty(set)) {return new ArrayList<T>(ZERO);}for (byte[] bytes : set) {T t = JsonSerializer.deserialize(bytes, clazz);list.add(t);}return list;});return result;}/*** 返回有序集中,指定区间内的成员 -> 从大到小* 其中成员的位置按分数值递增(从大到小)来排序** @param key* @param clazz* @param start 开始位置* @param end   结束位置* @return 指定区间内,带有分数值的有序集成员的列表。*/public <T> List<T> zRevRange(String key, Class<T> clazz, int start, int end) {validateKeyParam(key);List<T> result = redisClient.invoke(jedisPool, jedis -> {Set<byte[]> set = jedis.zrevrange(key.getBytes(), start, end);List<T> list = new ArrayList<>(set.size());if (CollectionUtils.isEmpty(set)) {return new ArrayList<T>(ZERO);}for (byte[] bytes : set) {T t = JsonSerializer.deserialize(bytes, clazz);list.add(t);}return list;});return result;}/*** 通过分数返回有序集合指定区间内的成员 -> 从小到大* 有序集成员按分数值递增(从小到大)次序排列** @param key* @param clazz* @param minScore 最小分数* @param maxScore 最大分数* @return 指定区间内,带有分数值(可选)的有序集成员的列表。*/public <T> List<T> zRangeByScore(String key, Class<T> clazz, double minScore, double maxScore) {validateKeyParam(key);List<T> result = redisClient.invoke(jedisPool, jedis -> {Set<byte[]> set = jedis.zrangeByScore(key.getBytes(), minScore, maxScore);List<T> list = new ArrayList<>(set.size());if (CollectionUtils.isEmpty(set)) {return new ArrayList<T>(ZERO);}for (byte[] bytes : set) {T t = JsonSerializer.deserialize(bytes, clazz);list.add(t);}return list;});return result;}/*** 通过分数返回有序集合指定区间内的成员 -> 从大到小* 有序集成员按分数值递增(从大到小)次序排列** @param key* @param clazz* @param minScore 最小分数* @param maxScore 最大分数* @return 指定区间内,带有分数值(可选)的有序集成员的列表。*/public <T> List<T> zRevRangeByScore(String key, Class<T> clazz, double minScore, double maxScore) {validateKeyParam(key);List<T> result = redisClient.invoke(jedisPool, jedis -> {Set<byte[]> set = jedis.zrevrangeByScore(key.getBytes(), maxScore, minScore);List<T> list = new ArrayList<>(set.size());if (CollectionUtils.isEmpty(set)) {return new ArrayList<T>(ZERO);}for (byte[] bytes : set) {T t = JsonSerializer.deserialize(bytes, clazz);list.add(t);}return list;});return result;}/*** 返回有序集中指定成员的排名* 按分数值递增(从小到大)顺序排列* 排名以 0 为底,也就是说, 分数值最小的成员排名为 0** @param key* @param obj 成员对象* @return 如果成员是有序集 key 的成员,返回 member 的排名。* 如果成员不是有序集 key 的成员,返回空*/public long zRank(String key, Object obj) {validateParam(key, obj);long sortIndex = redisClient.invoke(jedisPool, jedis -> {long result = jedis.zrank(key.getBytes(), JsonSerializer.serialize(obj));return result;});return sortIndex;}/*** 返回有序集中指定成员的排名* 分数值递减(从大到小)排序* 排名以 0 为底,也就是说, 分数值最大的成员排名为 0** @param key* @param obj 成员对象* @return 如果成员是有序集 key 的成员,返回 member 的排名。* 如果成员不是有序集 key 的成员,返回空*/public long zRevRank(String key, Object obj) {validateParam(key, obj);long sortIndex = redisClient.invoke(jedisPool, jedis -> {long result = jedis.zrevrank(key.getBytes(), JsonSerializer.serialize(obj));return result;});return sortIndex;}/*** 移除有序集合中的个成员* 名称为key 的有序集合中的元素 obj** @param key* @param obj 元素* @return 被成功移除的成员的数量,不包括被忽略的成员。*/public long zRem(String key, Object obj) {validateParam(key, obj);long lRow = redisClient.invoke(jedisPool, jedis -> {long result = jedis.zrem(key.getBytes(), JsonSerializer.serialize(obj));return result;});return lRow;}/*** 移除有序集合中给定的排名区间的所有成员* 从排序小的开始删除** @param start 开始位置 下标 0 开始* @param end   结束位置* @return 被移除成员的数量。*/public long zRemRangeByRank(String key, int start, int end) {validateKeyParam(key);long lRow = redisClient.invoke(jedisPool, jedis -> {long result = jedis.zremrangeByRank(key.getBytes(), start, end);return result;});return lRow;}/*** 返回有序集中,成员的分数值* 如果成员元素不是有序集 key 的成员,或 key 不存在,返回 null** @param key* @param obj 成员对象* @return 如果成员是有序集 key 的成员,返回 member 的排名。* 如果成员不是有序集 key 的成员,返回空*/public Double zScore(String key, Object obj) {validateParam(key, obj);Double score = redisClient.invoke(jedisPool, jedis -> {Double sResult = jedis.zscore(key.getBytes(), JsonSerializer.serialize(obj));return sResult;});return score;}/*** -------------------list相关操作---------------------*//*** 将一个或多个值插入到列表头部* 如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。* 当 key 存在但不是列表类型时,返回一个错误* 注意:在Redis 2.4版本以前的 lpush 命令,都只接受单个 value 值。** @param key* @return 列表的长度。*/public Long lpush(String key, Object... value) {validateParam(key, value);Long len = redisClient.invoke(jedisPool, jedis -> {return jedis.lpush(key.getBytes(), JsonSerializer.serialize(value));});return len;}/*** 用于返回列表的长度* 如果列表 key 不存在,则 key 被解释为一个空列表,* 返回 0 。 如果 key 不是列表类型,返回一个错误** @param key* @return list 集大小*/public long lLen(String key) {validateKeyParam(key);long count = redisClient.invoke(jedisPool, jedis -> {long countAll = jedis.llen(key.getBytes());return countAll;});return count;}/*** 通过索引获取列表中的元素* 如果指定索引值不在列表的区间范围内,返回 null* 使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。** @param key* @param index 集合索引* @return 元素信息*/public <T> T lindex(String key, int index, Class<T> clazz) {validateParam(key, clazz);T obj = redisClient.invoke(jedisPool, jedis -> {byte[] result = jedis.lindex(key.getBytes(), index);if (result == null) {return null;}return JsonSerializer.deserialize(result, clazz);});return obj;}/*** 移除并返回列表的第一个元素** @param key* @return 列表的第一个元素。 当列表 key 不存在时,返回 null。*/public <T> T lpop(String key, Class<T> clazz) {validateParam(key, clazz);T obj = redisClient.invoke(jedisPool, jedis -> {byte[] result = jedis.lpop(key.getBytes());if (result == null) {return null;}return JsonSerializer.deserialize(result, clazz);});return obj;}/*** 移除并返回列表的最后一个元素** @param key* @return 列表的最后一个元素。 当列表不存在时,返回 null*/public <T> T rpop(String key, Class<T> clazz) {validateParam(key, clazz);T obj = redisClient.invoke(jedisPool, jedis -> {byte[] result = jedis.rpop(key.getBytes());if (result == null) {return null;}return JsonSerializer.deserialize(result, clazz);});return obj;}/*** -------------------Redis 发布订阅---------------------*/public Long publish(String key, Object value) {validateParam(key, value);Long len = redisClient.invoke(jedisPool, jedis -> {return jedis.publish(key.getBytes(), JsonSerializer.serialize(value));});return len;}/*** -------------------Hash相关操作---------------------*//*** 用于为哈希表中的字段赋值* 如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作* 如果字段已经存在于哈希表中,旧值将被覆盖** @param key* @param field* @param value 值*/public Boolean setHash(String key, String field, Object value) {validateKeyParam(key);long result =redisClient.invoke(jedisPool, (jedis) -> jedis.hset(key.getBytes(), field.getBytes(),JsonSerializer.serialize(value)));if (LONG_ZERO.equals(result)) {return false;}return true;}/*** 用于为哈希表中不存在的的字段赋值* 如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作* 如果字段已经存在于哈希表中,操作无效* 如果 key 不存在,一个新哈希表被创建并执行 HSETNX 命令* 设置成功,返回 1 。 如果给定字段已经存在且没有操作被执行,返回 0 。* 注意版本 >= 2.0.0** @param key* @param field* @param value 值* @return 是否成功*/public Boolean setNxHash(String key, String field, Object value) {validateKeyParam(key);long result =redisClient.invoke(jedisPool, (jedis) -> jedis.hsetnx(key.getBytes(), field.getBytes(),JsonSerializer.serialize(value)));if (LONG_ZERO.equals(result)) {return false;}return true;}/*** 获取存储在哈希表中指定字段的值** @param key* @param field* @return 返回给定字段的值。如果给定的字段或 key 不存在时,返回 null*/public <T> T getHash(String key, String field, Class<T> clazz) {validateKeyParam(key);byte[] value = redisClient.invoke(jedisPool, (jedis) -> jedis.hget(key.getBytes(), field.getBytes()));if (value != null) {return JsonSerializer.deserialize(value, clazz);}return null;}/*** 用于删除哈希表 key 中的个指定字段** @param key* @param field*/public void delHash(String key, String field) {validateParam(key, field);redisClient.invoke(jedisPool, (jedis) -> jedis.hdel(key.getBytes(), field.getBytes()));}/*** 用于查看哈希表的指定字段是否存在** @param key* @param field*/public Boolean hashKeyExists(String key, String field) {validateParam(key, field);return redisClient.invoke(jedisPool, (jedis) -> jedis.hexists(key.getBytes(), field.getBytes()));}/*** 获取在哈希表中指定 key 的所有字段和值* 在返回值里,紧跟每个字段名(field name)之后是字段的值(value),* 所以返回值的长度是哈希表大小的两倍。** @param key* @return 以列表形式返回哈希表的字段及字段值。 若 key 不存在,返回空列表。*/public <T> Map<String, T> getAllHash(String key, Class<T> clazz) {validateKeyParam(key);return redisClient.invoke(jedisPool, (jedis) -> {Map<byte[], byte[]> map = jedis.hgetAll(key.getBytes());Map<String, T> resultMap = new HashMap<>();if (map != null) {for (Map.Entry<byte[], byte[]> item : map.entrySet()) {byte[] newKey = item.getKey();T newValue = JsonSerializer.deserialize(item.getValue(), clazz);resultMap.put(Arrays.toString(newKey), newValue);}return resultMap;}return null;});}/*** -------------------以下危险操作 谨慎使用 ---------------------*//*** 清空所有redis 数据* 谨慎使用*/public void clearAll() {LOGGER.error("缓存的clear方法被调用,所有缓存数据都被清除!");redisClient.invoke(jedisPool, BinaryJedis::flushAll);}/*** 查找所有符合给定模式( pattern)的 key 。* 谨慎使用(存在性能问题)* 会引发Redis锁,并且增加Redis的CPU占用** @param pattern* @return 符合给定模式的 key 列表 (Array)。*/public List<String> findKeys(String pattern) {Assert.hasText(pattern, "查找规则不能为空");Charset charset = Charset.forName("UTF-8");return redisClient.invoke(jedisPool, jedis -> {Set<String> sets = jedis.keys(("*" + pattern + "*"));if (sets != null) {List<String> list = new ArrayList<>(sets.size());list.addAll(sets);return list;}return null;});}/*** 校验参数*/private void validateParam(String key, Object value) {this.validateKeyParam(key);Assert.notNull(value, "value不能为空");Assert.isInstanceOf(Object.class, value, "value没有实现Object接口,无法序列化");}/*** 校验参数*/private void validateKeyParam(String key) {Assert.hasText(key, "key不能为空");Assert.notNull(jedisPool, "jedis连接初始化失败");}public synchronized Jedis getRedis() {return jedisPool.getResource();}public void setJedisPool(JedisPool jedisPool) {this.jedisPool = jedisPool;}}

测试
创建测试类

@SpringBootTest
@RunWith(SpringRunner.class)
public class RedisSimplePutTest {private Logger LOGGER = LoggerFactory.getLogger(RedisSimplePutTest.class);@Autowiredprivate RedisCache redisCache;/*** 存储字符串*/@Testpublic void testPutString() {String key = "test_string_2";String value = "string_value";LOGGER.info("存储字符串开始 key={} value={}", key, value);boolean putFlag = redisCache.put(key, "string_value", 0, TimeUnit.MINUTES);LOGGER.info("存储字符串结束 putFlag={}", putFlag);String rvalue = redisCache.get(key);LOGGER.info("存储字符串-> 查询缓存value={}", rvalue);}/*** 存储自定义对象*/@Testpublic void testPutObject() {String key = "test_object_article_2";TArticle tArticle =new TArticle("1111", "测试文章1", "作者1", 1.0, 1);LOGGER.info("存储对象开始 key={} value={}", key, tArticle);redisCache.put(key, tArticle);LOGGER.info("存储对象结束");TArticle value = redisCache.get(key, TArticle.class);LOGGER.info("存储对象-> 查询缓存value={}", value);}
}

输出结果

存储字符串开始 key=test_string_2 value=string_value
存储字符串结束 putFlag=true
存储字符串-> 查询缓存value=string_value

存储对象开始 key=test_object_article_2 value=测试文章1
存储对象结束
存储对象-> 查询缓存value=测试文章1

转载于:https://www.cnblogs.com/mengq0815/p/10596066.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/365619.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

更改span标签样式_CSS 内嵌样式

前面一节我们讲了行内样式&#xff0c;但是行内样式的缺点就是样式不能重用。例如当有好多个 标签&#xff0c;我们希望所有的 标签的样式都一致&#xff0c;那么需要在每个标签中都写一遍&#xff0c;这么会很麻烦&#xff0c;也会增加很多代码。那么为了解决这个问题&#…

js 函数节流

//es6语法export function debounce(func, delay) {let timer//返回一个函数&#xff0c;并拿到参数return function (...args) {if (timer) {clearTimeout(timer)}timer setTimeout(() > {func.apply(this, args)}, delay)} } //简单实现var debounce function(idle, act…

mysql 6安装当前密码_MySQL8.0 安装踩坑指南

就在昨天上午&#xff0c;刚为云服务器安装好Apache2.4.33和PHP7.2.4环境&#xff0c;准备再来一个最新的MySQL5.7.22。寻找5.7版本的rpm包时下到mysql80xxx.rpm&#xff0c;看人家的教程是mysql57&#xff0c;难道80是MySQL出出…出了8版&#xff0c;一搜新闻2个小时前MySQL发…

如何用Java编写最快的表达式评估器之一

当然&#xff0c;标题有点吸引人&#xff0c;但确实如此&#xff08;您当然不相信自己没有伪造自己的基准&#xff0c;但这是另一回事了&#xff09;。 因此&#xff0c;上周我正在寻找一个小型且可用的库来评估数学表达式。 我几乎直接偶然发现了这个stackoverflow帖子 。 推…

Elasticsearch环境搭建和介绍(Windows)

一、Elasticsearch介绍和安装 1.1 介绍 Elastic Elastic官网&#xff1a;https://www.elastic.co/cn/ Elastic有一条完整的产品线&#xff1a;Elasticsearch、Kibana、Logstash等&#xff0c;前面说的三个就是大家常说的ELK技术栈。 Elasticsearch Elasticsearch官网&#xff1…

python 银行业务系统程序编程写_python多线程实现代码(模拟银行服务操作流程)

1.模拟银行服务完成程序代码目前&#xff0c;在以银行营业大厅为代表的窗口行业中大量使用排队(叫号)系统&#xff0c;该系统完全模拟了人群排队全过程&#xff0c;通过取票进队、排队等待、叫号服务等功能&#xff0c;代替了人们站队的辛苦。排队叫号软件的具体操作流程为&…

vue 新版本 webpack 代理 跨域设置

旧版本中&#xff1a;dev-server.js 这段去掉 var apiRoutes express.Router() //getList apiRoutes.get(/getDiscList, function (req, res) {var url https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcgaxios.get(url, {headers: {referer: https://c.y.qq.com…

人月神话(2)

我不知道为什么作者要拿外科医生举例子&#xff0c;在我眼里足球队更合适&#xff0c;或者说更贴近生活&#xff0c;让人们更容易理解。人的专业水平&#xff0c;在刚开始其实没什么可比性&#xff0c;试问&#xff1a;一个有小学学历的人和一个有初中学历的人在大公司招聘时有…

mysql查询出过去一个月_Mysql查询今天、昨天、7天、近30天、本月、上一月 数据...

今天select * from 表名 where to_days(时间字段名) to_days(now());昨天SELECT * FROM 表名 WHERE TO_DAYS( NOW( ) ) - TO_DAYS( 时间字段名) < 17天SELECT * FROM 表名 where DATE_SUB(CURDATE(), INTERVAL 7 DAY) < date(时间字段名)近30天SELECT * FROM 表名 where…

Jar Hell变得轻松–用jHades揭秘classpath

Java开发人员将不得不面对的最困难的问题是类路径错误&#xff1a; ClassNotFoundException &#xff0c; NoClassDefFoundError &#xff0c;Jar Hell&#xff0c; Xerces Hell和company。 在本文中&#xff0c;我们将探究这些问题的根本原因&#xff0c;并了解最小的工具&am…

图像处理中常见的时域与频域区别与关系

本文纯为转载只做个人学习记录用&#xff0c;请自动点击链接到作者原文&#xff1a;https://blog.csdn.net/samkieth/article/details/49561539 一、什么是时域 时域是描述数学函数或物理信号对时间的关系。例如一个信号的时域波形可以表达信号随着时间的变化。 二、什么是频域…

程序控制发送文件到邮箱_Kindle电子邮箱推送

Kindle 推送支持的格式目前 Kindle 推送仅支持以下几种格式。需要注意的是&#xff0c;AZW 和 AZW3 是两种不同的格式&#xff0c;虽然这两种格式 Kindle 设备都支持阅读&#xff0c;但是亚马逊的个人文档服务支持推送 AZW 但是不支持 AZW3。Kindle 格式 (.mobi 或 .azw) * 推荐…

[USACO06JAN] 牛的舞会 The Cow Prom

题目描述 The N (2 < N < 10,000) cows are so excited: its prom night! They are dressed in their finest gowns, complete with corsages and new shoes. They know that tonight they will each try to perform the Round Dance. Only cows can perform the Round D…

前端js 实现文件下载

https://www.zhangxinxu.com/wordpress/2017/07/js-text-string-download-as-html-json-file/ 侵删 1.H5 download属性 function downFile(content, filename) {// 创建隐藏的可下载链接var eleLink document.createElement(a);eleLink.download filename;eleLink.style.disp…

mysql的英文字母_MySQL中查询的有关英文字母大小写问题的分析

mysql数据库在做查询时候&#xff0c;有时候是英文字母大小写敏感的&#xff0c;有时候又不是的&#xff0c;主要是由mysql的字符校验规则的设置决定的&#xff0c;通常默认是不支持的大小写字母敏感的。1. 什么是字符集和校验规则&#xff1f;字符集是一套符号和编码。校对规则…

JDK8 lambda的会话指南–术语表

上次出现…我写了一篇与JDK8为我们提供的新方法有关的文章。 最令我兴奋的功能是lambda。 我必须承认&#xff0c;在即将成为浪子的第一年&#xff08;在此期间&#xff0c;我使用C&#xff03;开发了该产品&#xff09;&#xff0c;我喜欢LINQ和它可以做的漂亮&#xff0c;优雅…

写接口给别人调用 推送数据到我们_我们写了一个超好用的抖音矩阵数据管理工具...

我最近跑了十来个抖音号&#xff0c;遇到一些问题&#xff0c;然后通过我们NB的程序员解决了。如果你也在做抖音矩阵&#xff0c;那这些问题你肯定也会遇到&#xff0c;所以我把解决问题的方法工具化了&#xff0c;给大家用。我遇到的最大的问题&#xff0c;就是账号数据的同步…

php crypt mysql password_使用PHP 5.5的password_hash和password_verify函数

使用PHP 5.5的password_hash和password_verify函数假设我想为用户存储密码&#xff0c;这是使用PHP 5.5的password_hash()功能(或者这个版本的PHP 5.3.7&#xff1a;https&#xff1a;//github.com/ircmaxell/password_compat)的正确方法吗&#xff1f;$options array("c…

Mysql order by 导致 using filesorting

https://www.cnblogs.com/drcoding/p/4942277.html转载于:https://www.cnblogs.com/eason-d/p/9700526.html

angular 拼接html 事件无效

主要是要引用$compile方法 更多专业前端知识&#xff0c;请上 【猿2048】www.mk2048.com