1. 程式人生 > >初學redis---在redis裡面進行分頁查詢

初學redis---在redis裡面進行分頁查詢

redis分頁

在一個專案中,有訪問比較頻繁的情況出現,這個時候,如果利用資料庫進行處理,效率就會比較慢,這個時候,使用了redis這種NoSql資料庫,由於專案的原因,我做了一個demo,用於展示。

我使用的是springboot+mybatis的框架,搭建的過程看我的另一篇部落格,在這裡附上pom.xml的檔案,利用maven進行管理jar包,這裡只是部分,要是想看全的,看我的另一篇部落格

        <!--在建立springboot專案的時候選擇的redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--設定reids配置需要的依賴包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!--使用的是jedis這個類-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

這個是檔案的目錄結構 

redis的一些需要的jar包引入進去之後,我們要封裝一個redisutils這個類,用於一些redis的一些基本操作,包括了一些註釋。

package cn.aimacademy.spy.spyserver.server.redisservice;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;


@Service
public class RedisUtilsService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Resource(name = "stringRedisTemplate")
    ValueOperations<String, String> valOpsStr;

    @Autowired
    RedisTemplate<Object, Object> redisTemplate;

    @Resource(name = "redisTemplate")
    ValueOperations<Object, Object> valOpsObj;

    /**
     * 根據指定key獲取String
     *
     * @param key
     * @return
     */
    public String getStr(String key) {
        String s = valOpsStr.get(key);

        if (s == null) {
            return "暫無對應的值";
        } else {
            return s;
        }
    }

    /**
     * 設定Str快取
     *
     * @param key
     * @param val
     */
    public void setStr(String key, String val) {
        valOpsStr.set(key, val);

    }

    /**
     * 刪除指定key
     *
     * @param key
     */

    public void del(String key) {
        stringRedisTemplate.delete(key);
    }

    /**
     * 根據指定o獲取Object
     *
     * @param o
     * @return
     */
    public Object getObj(Object o) {
        Object o1 = valOpsObj.get(o);
        if (o1 == null) {
            return o1;
        } else {
            return o1;
        }
    }

    /**
     * 設定obj快取
     *
     * @param key
     * @param value
     */
    public void setObj(Object key, Object value) {

        valOpsObj.set(key, value);
    }

    /**
     * 刪除Obj快取
     *
     * @param o
     */
    public void delObj(Object o) {
        redisTemplate.delete(o);
    }


    /**
     * 新增物件到redis 裡面的list中
     * redis中的 list 是雙向的 所以新增的時候需要注意
     * rightPush 先進先出 leftPush 先進後出 這裡 需要注意
     *
     * @param key list 對應的key
     * @param obj 需要存的物件
     */
    public void addList(String key, Object obj) {
        redisTemplate.opsForList().rightPush(key, obj);
    }


    /**
     * opsForList().range(key, start, end);  取範圍值  redis裡面的list下標從0開始
     * 流程 拿到key 對應的list 取 0 到 5  和 mysql的limt  類似 注意下標即可
     * 從redis list 裡面的獲取資料分頁
     *
     * @param key   redis list 對應的key
     * @param start 開始下標
     * @param end   介紹下標
     * @return 返回list給前端
     */
    public List getListPage(String key, int start, int end) {
        return (List) redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 新增一個有序集合,存在為false,不存在是true
     * @param k,集合名字,
     * @param v k值
     * @param score 分數
     * @return
     */
    public boolean addZSet(Object k ,String v,double score){
        return redisTemplate.opsForZSet().add(k,v,score);
    }

    public Set getZSetByName(Object key, int start, int end) {
        return  redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
    }

    public long getZSetSize(Object k){
        return redisTemplate.opsForZSet().size(k);
    }

}

 寫好之後,還需要建立一個redisconfig檔案,用於配置redis的一些初始化。

package cn.aimacademy.spy.spyserver.config;


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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
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.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;



@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    //快取管理器 spring boot 2.0後 配置快取管理器 和2.0以前 不一樣 根據自己的版本 配置
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisTemplate) {
        return RedisCacheManager.create(redisTemplate);
    }
    // 以下兩種redisTemplate自由根據場景選擇
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        //使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值(預設使用JDK的序列化方式)
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        template.setValueSerializer(serializer);
        //使用StringRedisSerializer來序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        //這裡設定redis事務一致
        template.setEnableTransactionSupport(true);
        return template;
    }
    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(factory);
        stringRedisTemplate.setEnableTransactionSupport(true);
        return stringRedisTemplate;
    }
}

到這基本也就寫完了,這個時候就有人問我,你也沒說分頁啊,在redis裡面,有一個zSet的資料結構,裡面可以進行排序操作,redis裡面總共有五種資料結構,StringListHashSetzSet,前面的大家基本都知道了,字串集合雜湊無序集合有序集合,其實也可以利用List進行分頁操作,但是寫法和效率都比較慢,所以還是直接使用zSet這個裡面的東西了,在剛才那個RedisUtilsServer的類裡面最後兩個方法封裝了zSet的一些方法,其實zSet還有很多的方法,這個時候就是看自己慢慢學了,在這裡就不介紹了。 

下面是在redis裡面進行賦值的操作,其中,第一個屬性,是在redis裡面標記是那個list的名字,第二個是具體的資料,第三個是排序用的。

        List<Map<String, Object>> list = textServer.queryInfo();
        for (Map<String, Object> map : list) {
            //這裡迴圈user 把每個物件存到 redis中list中
//            redisUtilsService.addList("list",map);
            String creation_date = map.get("creation_date") == null ? "2000-01-01 00:00:00" : map.get("creation_date").toString();
            String creationDate = DateUtils.date2TimeStamp(creation_date, "yyyy-MM-dd HH:mm:ss");
            redisUtilsService.addZSet(CommonUtils.ENT_INFO_LIST, map.toString(), Double.parseDouble(creationDate));
        }

同樣取值的時候,這麼取值就可以了。

  Set list = redisUtilsService.getZSetByName(CommonUtils.ENT_INFO_LIST,0,5);

下面這個就是CommonUtils 

public class CommonUtils {

    public final static String ENT_INFO_LIST = "ENT_INFO_LIST";


}

我已經把大部分的程式碼粘貼出來了,要是有不懂的,或者是有疑問的,可以聯絡我,qq:1029273212