前不久分享过 Redis 的基本数据结构及基本命令详解。在熟悉了 redis 的基本操作之后(如果还有对 redis 的基本操作不熟悉的,可以点击前面的连接先熟悉下),今天给大家分享下实际开发中对 redis 操作的 Java 实现版本。
Maven 依赖
使用 maven 来构建项目在当下应该已经是主流了,所以我们也不例外使用了 Maven。因为使用了 spring 对 redis 封装的 jar,所以也需要引入 spring 基本 jar,Maven 依赖如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>redis</artifactId>
</dependency>
实现代码
实现代码篇幅有点长,而且 segmentfault 代码 div 的高度有限制,建议大家把代码拷贝到开发工具中再阅读。
package spring.redis;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class SpringRedisHandler implements InitializingBean {
//redis 编码
private static final String redisCode = "utf-8";
private static final String EmptyString = "";
@Autowired
private RedisTemplate<String, String> jtRedis;
/**
* 设置 key-value【不含超时时间】*
* @param key
* @param value
*/
public void set(String key, Object value) {this.set(key, String.valueOf(value), 0L);
}
/**
* 设置 key-value【含超时时间】*
* @param key
* @param value
* @param liveTime
*/
public void set(String key, Object value, long liveTime) {this.set(key.getBytes(), String.valueOf(value).getBytes(), liveTime);
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void set(final byte[] key, final byte[] value, final long liveTime) {jtRedis.execute(new RedisCallback() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {connection.set(key, value);
if (liveTime > 0) {connection.expire(key, liveTime);
}
return 1L;
}
});
}
/**
* get key 的值
*
* @param key
* @return
*/
public String get(final String key) {return jtRedis.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {
try {return new String(connection.get(key.getBytes()), redisCode);
} catch (UnsupportedEncodingException e) {e.printStackTrace();
return "";
}
}
});
}
/**
* 是否存在 key
*
* @param key
* @return
*/
public boolean exists(final String key) {return jtRedis.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {return connection.exists(key.getBytes());
}
});
}
/**
* 某数据中所有 key 的总数
*
* @return
*/
public long dbSize() {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {return connection.dbSize();
}
});
}
/**
* 检测 redis 服务器是否能平通
*/
public String ping() {return jtRedis.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {return connection.ping();
}
});
}
/**
* value 增加某个值
*
* @param key
* @param value
* @return
*/
public Long incr(String key, long value) {return incr(key.getBytes(), value);
}
private Long incr(byte[] key, long value) {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {return connection.incrBy(key, value);
}
});
}
/**
* 自增
*
* @param key
* @return
*/
public Long incr(String key) {return incr(key.getBytes(), 1);
}
/**
* 自减
*
* @param key
* @return
*/
public Long decr(String key) {return decr(key.getBytes(), 1);
}
/**
* value 减少某个值
*
* @param key
* @param value
* @return
*/
public Long decr(String key, long value) {return decr(key.getBytes(), value);
}
private Long decr(byte[] key, long value) {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {return connection.decrBy(key, value);
}
});
}
/**
* 删除 key
*
* @param key
* @return
*/
public Long del(String key) {return del(key.getBytes());
}
private Long del(byte[] key) {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {return connection.del(key);
}
});
}
/**
* flushdb:删除 db 下的所有数据
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public void flushDb() {jtRedis.execute(new RedisCallback() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {connection.flushDb();
return 1L;
}
});
}
/**
* 设置 hash
*
* @param key
* @param field
* @param value
* @return
*/
public Boolean hSet(String key, String field, String value) {return jtRedis.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {return redisConnection.hSet(key.getBytes(), field.getBytes(), value.getBytes());
}
});
}
/**
* 获取 hash 的属性值
*
* @param key
* @param field
* @return
*/
public String hGet(String key, String field) {return jtRedis.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection redisConnection) throws DataAccessException {return new String(redisConnection.hGet(key.getBytes(), field.getBytes()));
}
});
}
/**
* 批量设置 hash
*
* @param key
* @param values
*/
public void hMSet(String key, Map<String, Object> values) {jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {redisConnection.hMSet(key.getBytes(), stringObjectMapToBytes(values));
return null;
}
});
}
/**
* 批量获取 hash 的多个属性
*
* @param key
* @param fields
* @return
*/
public List<String> hMGet(String key, String... fields) {return jtRedis.execute(new RedisCallback<List<String>>() {
@Override
public List<String> doInRedis(RedisConnection redisConnection) throws DataAccessException {List<String> listFileds = new ArrayList<>();
for (int i = 0; i < fields.length; i++) {listFileds.add(fields[i]);
}
List<byte[]> byteFileds = stringListToByte(listFileds);
return bytesListToString(redisConnection.hMGet(key.getBytes(), byteFileds.toArray(new byte[byteFileds.size()][byteFileds.size()])));
}
});
}
/**
* 获取 hash 的所有属性
*
* @param key
* @return
*/
public Map<String, String> hGetAll(String key) {return jtRedis.execute(new RedisCallback<Map<String, String>>() {
@Override
public Map<String, String> doInRedis(RedisConnection redisConnection) throws DataAccessException {return bytesMapToString(redisConnection.hGetAll(key.getBytes()));
}
});
}
/**
* 针对 hash 中某个属性增加指定的值
*
* @param key
* @param field
* @param value
* @return
*/
public Double hIncrBy(String key, String field, double value) {return jtRedis.execute(new RedisCallback<Double>() {
@Override
public Double doInRedis(RedisConnection redisConnection) throws DataAccessException {return redisConnection.hIncrBy(key.getBytes(), field.getBytes(), value);
}
});
}
/**
* hash 是存在某属性
*
* @param key
* @param field
* @return
*/
public Boolean hExists(String key, String field) {return jtRedis.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {return redisConnection.hExists(key.getBytes(), field.getBytes());
}
});
}
/**
* 删除 hash 的某属性
*
* @param key
* @param field
* @return
*/
public Long hDel(String key, String field) {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {return redisConnection.hDel(key.getBytes(), field.getBytes());
}
});
}
/**
* 向 zset 中的某个 key 添加一个属性几分数(可以根据分数排序)*
* @param key
* @param score
* @param field
* @return
*/
public Boolean zAdd(String key, double score, String field) {return jtRedis.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {return redisConnection.zAdd(key.getBytes(), score, field.getBytes());
}
});
}
/**
* 给 zset 中的某个 key 中的某个属性增加指定分数
*
* @param key
* @param score
* @param field
* @return
*/
public Double zIncrBy(String key, double score, String field) {return jtRedis.execute(new RedisCallback<Double>() {
@Override
public Double doInRedis(RedisConnection redisConnection) throws DataAccessException {return redisConnection.zIncrBy(key.getBytes(), score, field.getBytes());
}
});
}
/**
* 从 list 左侧插入一个元素
*
* @param key
* @param values
* @return
*/
public Long lPush(String key, String value) {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {return connection.lPush(key.getBytes(), value.getBytes());
}
});
}
/**
* 从 list 左侧插入多个元素
*
* @param key
* @param values
* @return
*/
public Long lPush(String key, List<String> values) {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {List<byte[]> bytes = stringListToByte(values);
return connection.lPush(key.getBytes(), bytes.toArray(new byte[bytes.size()][bytes.size()]));
}
});
}
/**
* 从 list 的左侧取出一个元素
*
* @param key
* @return
*/
public String lPop(String key) {return jtRedis.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {if (connection.lLen(key.getBytes()) > 0) {return new String(connection.lPop(key.getBytes()));
} else {return EmptyString;}
}
});
}
/**
* 向 list 的右侧插入一个元素
*
* @param key
* @param value
* @return
*/
public Long rPush(String key, String value) {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {return connection.rPush(key.getBytes(), value.getBytes());
}
});
}
/**
* list 的 rpush,从右侧插入多个元素
*
* @param key
* @param values
* @return
*/
public Long rPush(String key, List<String> values) {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {List<byte[]> bytes = stringListToByte(values);
return connection.rPush(key.getBytes(), bytes.toArray(new byte[bytes.size()][bytes.size()]));
}
});
}
/**
* 从 list 的右侧取出一个元素
*
* @param key
* @return
*/
public String rPop(String key) {return jtRedis.execute(new RedisCallback<String>() {
@Override
public String doInRedis(RedisConnection connection) throws DataAccessException {if (connection.lLen(key.getBytes()) > 0) {return new String(connection.rPop(key.getBytes()));
} else {return EmptyString;}
}
});
}
/**
* 给 set 中添加元素
*
* @param key
* @param values
* @return
*/
public Long sadd(String key, List<String> values) {return jtRedis.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {List<byte[]> bytes = stringListToByte(values);
return connection.sAdd(key.getBytes(), bytes.toArray(new byte[bytes.size()][bytes.size()]));
}
});
}
/**
* 获取 set 中的所有元素
*
* @param key
* @return
*/
public List<String> smembers(String key) {return jtRedis.execute(new RedisCallback<List<String>>() {
@Override
public List<String> doInRedis(RedisConnection connection) throws DataAccessException {return bytesListToString(connection.sMembers(key.getBytes()));
}
});
}
/**
* set 中是否包含某元素
*
* @param key
* @param value
* @return
*/
public Boolean sIsMember(String key, String value) {return jtRedis.execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws DataAccessException {return connection.sIsMember(key.getBytes(), value.getBytes());
}
});
}
private byte[][] change(List<byte[]> values) {byte[][] result = {};
return result;
}
private List<byte[]> stringListToByte(List<String> values) {
return values
.stream()
.map(p -> p.getBytes())
.collect(Collectors.toList()
);
}
private List<String> bytesListToString(Collection<byte[]> values) {
return values
.stream()
.map(p -> new String(p))
.collect(Collectors.toList()
);
}
private Map<String, String> bytesMapToString(Map<byte[], byte[]> values) {Map<String, String> result = new HashMap<>();
values.forEach((k, v) -> result.put(new String(k), new String(v)));
return result;
}
private Map<byte[], byte[]> stringObjectMapToBytes(Map<String, Object> values) {Map<byte[], byte[]> result = new HashMap<>();
values.forEach((k, v) -> result.put(k.getBytes(), String.valueOf(v).getBytes()));
return result;
}
/**
* 正则表达式获取值
*
* @param pattern
* @return
*/
public Set<String> keys(String pattern) {return jtRedis.keys(pattern);
}
@Override
public void afterPropertiesSet() throws Exception {RedisSerializer<String> stringSerializer = new StringRedisSerializer();
jtRedis.setKeySerializer(stringSerializer);
jtRedis.setValueSerializer(stringSerializer);
jtRedis.setHashKeySerializer(stringSerializer);
jtRedis.setHashValueSerializer(stringSerializer);
}
}
配置文件
配置文件主要有两个,一个是 spirng 相关配置的配置文件 applicationContext-redis.xml,还有一个是 redis 相关配置文件 redis-config.properties
applicationContext-redis.xml 配置文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="spring.redis"></context:component-scan>
<!-- 加载 redis 配置文件 -->
<context:property-placeholder location="classpath:redis-config.properties"/>
<!-- 实例化 redis 配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}"/>
<property name="maxWaitMillis" value="${redis.maxWait}"/>
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
</bean>
<!--redis 连接工厂 -->
<bean id="dsRedis" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}"/>
<property name="port" value="${redis.port}"/>
<property name="password" value="${redis.pass}"/>
<property name="database" value="${redis.database}"/>
<property name="poolConfig" ref="poolConfig"/>
</bean>
<bean id="jtRedis" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="dsRedis"/>
</bean>
</beans>
redis-config.properties 配置文件内容如下:
# 装有 redis 数据库的虚拟机中的一台机器的 ip
redis.host=127.0.0.1
redis.port=6379
redis.pass=
#默认存储在 databse[0] 数据库, redis 的 database 相当于一个数据, 默认也是 0
redis.database=0
#maxIdle: 最大空闲数
redis.maxIdle=300
#maxWait: 最大等待时长,3 秒
redis.maxWait=3000
#testOnBorrow:在提取一个 jedis 实例时,是否提前进行验证操作;如果为 true,则得到的 jedis 实例均是可用的;redis.testOnBorrow=true
结语
虽然代码篇幅有点长,但是都是基于 spring 封装之后的再次封装,大家应该都能理解。并且以上方法我都有测试过,亲测可用,因为测试代码也比较的简单,因此就不贴出来了。最后,欢迎大家补充、批评、指正。