4

前不久分享过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封装之后的再次封装,大家应该都能理解。并且以上方法我都有测试过,亲测可用,因为测试代码也比较的简单,因此就不贴出来了。最后,欢迎大家补充、批评、指正。

国子监阿创
131 声望8 粉丝

任何一个傻瓜都能写出计算机能理解的程序,而优秀的程序员却能写出别人能读得懂的程序。—— Martin Fowler