java

springboot中redis使用一條龍

springboot中redis使用

 <!--redis-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.13.3</version>
        </dependency>
        <!-- springboot整合redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>29.0-</version>
        </dependency>

Jedis是Redis官方推薦的Java連線開發工具。要在Java開發中使用好Redis中介軟體

redis配置類

1.redis連線

package cn.zqs.sqpproduct.config;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RedissonConfig {
    public static final String NODE="redis://127.0.0.1:6379";

    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        config.useSingleServer().setAddress(NODE);
        RedissonClient redissonClient = Redisson.create(config);
        return redissonClient;
    }
}

2.redis配置

package cn.zqs.sqpproduct.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration//表示該類為配置類
public class RedisConfig {

    /**
     * 新建restTemplate交給spring容器管理
     * 注意:
     * springboot其實已經自動注入了RedisTemplate,
     * 但是泛型是RedisTemplate<Object,Object>,而且沒有指定序列化的方式
     * 而我們需要key都是string型別的 ,避免頻繁型別轉換,所以一般會自定義
     * 當手動去注入一個RedisTemplate後 springboot將不會自動注入
     * RedisConnectionFactory:springboot自動讀取配置檔案然後注入
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        //設定連結工廠  工廠用於建立連結
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //設定自定義序列化方式
        setSerializeConfig(redisTemplate, redisConnectionFactory);
        return redisTemplate;
    }

    /**
     * 為什麼要序列化?
     * 序列化能加快網路傳輸,而且redis的value都是字串,
     * 如果是javabean或者集合物件,就需要手動去序列化為json字串,這兒直接配置了,
     * 以後傳入任意value的時候,就會自動序列化
     * <p>
     * 比如:我們現在想儲存一個student物件到redis,但是redis只能存字串,那麼我們需要把物件透過json工具類轉換為字串
     * 再去存入,寫了這個就不需要轉了,傳入student物件,內部自動幫助我們轉換為字串
     */
    private void setSerializeConfig(RedisTemplate<String, Object> redisTemplate, RedisConnectionFactory redisConnectionFactory) {
        //對字串採取普通的序列化方式 適用於key 因為我們一般採取簡單字串作為key
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        //普通的string型別的key採用 普通序列化方式
        redisTemplate.setKeySerializer(stringRedisSerializer);
        //普通hash型別的key也使用 普通序列化方式
        redisTemplate.setHashKeySerializer(stringRedisSerializer);
        //解決查詢快取轉換異常的問題  大家不能理解就直接用就可以了 這是springboot自帶的jackson序列化類,但是會有一定問題
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //普通的值採用jackson方式自動序列化
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        //hash型別的值也採用jackson方式序列化
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        //屬性設定完成afterPropertiesSet就會被呼叫,可以對設定不成功的做一些預設處理
        redisTemplate.afterPropertiesSet();
    }

依賴json,所以配置

package cn.zqs.sqpproduct.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import .io.IOException;

@Configuration
public class JacksonConfig {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        //透過該方法對mapper物件進行設定,所有序列化的物件都將按改規則進行系列化
        // Include.Include.ALWAYS 預設
        // Include.NON_DEFAULT 屬性為預設值不序列化
        // Include.NON_EMPTY 屬性為 空("") 或者為 NULL 都不序列化,則返回的json是沒有這個欄位的。這樣對移動端會更省流量
        // Include.NON_NULL 屬性為NULL 不序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        //反序列化的時候 忽略不匹配的屬性
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 允許出現特殊字元和轉義符
        objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
        // 允許出現單引號
        objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        //欄位保留,將null值轉為""
        objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object o, JsonGenerator jsonGenerator,
                                  SerializerProvider serializerProvider)
                    throws IOException {
                jsonGenerator.writeString("");
            }
        });
        return objectMapper;

    }
}

redis工具類

1、redis

package cn.zqs.sqpproduct.util;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class RedisUtils {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * @param key
     * @return 獲得值
     * redis有五種資料型別 opsForValue表示是操作字串型別
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    //本來只可以放入string型別,但是我們配置了自動序列化所以這兒可以傳入object
    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            log.error("redis set value exception:{}", e);
            return false;
        }
    }

    /**
     * 原子操作
     *
     * @param key
     * @param value
     * @param expire 過期時間 秒
     * @return
     */
    public boolean setex(String key, Object value, long expire) {
        try {//TimeUnit.SECONDS指定型別為秒
            redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            log.error("redis set value and expire exception:{}", e);
            return false;
        }
    }

    /**
     * 非原子操作
     *
     * @param key
     * @param expire
     * @return
     */
    public boolean expire(String key, long expire) {
        try {//這兒沒有ops什麼的是因為每種資料型別都能設定過期時間
            redisTemplate.expire(key, expire, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            log.error("redis set key expire exception:{}", e);
            return false;
        }
    }

    /**
     * @param key
     * @return 獲取key的過期時間
     */
    public long ttl(String key) {
        return redisTemplate.getExpire(key);
    }

    /**
     * @param keys 刪除key 可變引數
     */
    public void del(String... keys) {
        if (keys != null && keys.length > 0) {
            redisTemplate.delete(CollectionUtils.arrayToList(keys));
        }
    }

    /**
     * @param key
     * @param step 傳入正數 就是加多少 傳入負數就是減多少
     * @return
     */
    public long incrBy(String key, long step) {
        return redisTemplate.opsForValue().increment(key, step);
    }

    /**
     * @param key
     * @param value
     * @return 如果該key存在就返回false 設定不成功 key不存在就返回ture設定成功
     */
    public boolean setnx(String key, Object value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    /**
     * 原子操作
     *
     * @param key
     * @param value
     * @param expire 在上面方法加上過期時間設定
     * @return
     */
    public boolean setnxAndExpire(String key, Object value, long expire) {
        return redisTemplate.opsForValue().setIfAbsent(key, value, expire, TimeUnit.SECONDS);
    }

    /**
     * @param key
     * @param value
     * @return 如果該key存在就返回之前的value  不存在就返回null
     */
    public Object getAndSet(String key, Object value) {
        return redisTemplate.opsForValue().getAndSet(key, value);
    }

    /**
     * @param key
     * @return 判斷key是否存在
     */
    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }


    /*****hash資料型別方法   opsForHash表示是操作字串型別*****/

    /**
     * @param key   健
     * @param field 屬性
     * @param value 值
     * @return
     */
    public boolean hset(String key, String field, Object value) {
        try {
            redisTemplate.opsForHash().put(key, field, value);
            return true;
        } catch (Exception e) {
            log.error("redis hset eror,key:{},field:{},value:{}", key, field, value);
            return false;
        }
    }

    /**
     * @param key
     * @param field
     * @param value
     * @param seconds(秒) 過期時間
     * @return
     */
    public boolean hset(String key, String field, Object value, long seconds) {
        try {
            redisTemplate.opsForHash().put(key, field, value);
            expire(key, seconds);//呼叫通用方法設定過期時間
            return true;
        } catch (Exception e) {
            log.error("redis hset and expire eror,key:{},field:{},value:{},exception:{}", key, field, value, e);
            return false;
        }
    }

    /**
     * 獲取key中field屬性的值
     *
     * @param key
     * @param field
     * @return
     */
    public Object hget(String key, String field) {
        return redisTemplate.opsForHash().get(key, field);
    }

    /**
     * 獲取key中多個屬性的鍵值對,這兒使用map來接收
     *
     * @param key
     * @param fields
     * @return
     */
    public Map<String, Object> hmget(String key, String... fields) {
        Map<String, Object> map = new HashMap<>();
        for (String field : fields) {
            map.put(field, hget(key, field));
        }
        return map;
    }

    /**
     * @param key 獲得該key下的所有鍵值對
     * @return
     */
    public Map<Object, Object> hmget(String key) {
        Map<Object, Object> entries = redisTemplate.opsForHash().entries(key);//先要再工具類判斷是否為null
        if (CollectionUtils.isEmpty(entries)) return null;
        return entries;
    }

    public <T> T hmget(String key, Class<T> tClass) {
        Map<Object, Object> hmget = hmget(key);
        if (CollectionUtils.isEmpty(hmget)) return null;

        String s = jacksonUtil.writeAsString(hmget);
        return jacksonUtil.readValue(s, tClass);
    }

    /**
     * @param key 鍵
     * @param map 對應多個鍵值
     * @return
     */
    public boolean hmsetMap(String key, Map<String, String> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            log.error("redis hmset eror,key:{},value:{},exception:{}", key, map, e);
            return false;
        }
    }

    @Autowired
    private JacksonUtil jacksonUtil;

    /**
     * @param key 鍵
     * @param t   javabean
     * @return
     */
    public <T> boolean hmset(String key, T t) {
        String s = jacksonUtil.writeAsString(t);
        Map<String, String> stringStringMap = jacksonUtil.readValueMap(s);
        return hmsetMap(key, stringStringMap);
    }

    /**
     * @param key     鍵
     * @param map     對應多個鍵值
     * @param seconds 過期時間(秒)
     * @return
     */
    public boolean hmset(String key, Map<String, Object> map, long seconds) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            expire(key, seconds);
            return true;
        } catch (Exception e) {
            log.error("redis hmset eror,key:{},value:{},expireTime,exception:{}", key, map, seconds, e);
            return false;
        }
    }

    /**
     * 刪除key中的屬性
     *
     * @param key
     * @param fields
     */
    public void hdel(String key, Object... fields) {
        redisTemplate.opsForHash().delete(key, fields);
    }

    /**
     * 判斷key中是否存在某屬性
     *
     * @param key
     * @param field
     * @return
     */
    public boolean hHashKey(String key, String field) {
        return redisTemplate.opsForHash().hasKey(key, field);
    }

    /**
     * 對key中filed的value增加多少 如果是減少就傳入負數
     *
     * @param key
     * @param field
     * @param step  正數增加,負數減少
     * @return
     */
    public double hincr(String key, String field, double step) {
        return redisTemplate.opsForHash().increment(key, field, step);
    }

    /**
     * key中多少個
     *
     * @param key
     * @return
     */
    public long hlen(String key) {
        return redisTemplate.opsForHash().size(key);
    }
    /******其他方法用到在增加********/

    /***set集合***/
    /**
     * 獲取key中所有元素
     *
     * @param key
     * @return
     */
    public Set<Object> sgetAll(String key) {
        try {
            Set<Object> members = redisTemplate.opsForSet().members(key);
            if (CollectionUtils.isEmpty(members)) return null;
            return members;
        } catch (Exception e) {
            log.error("redis sgetAll error,key:{},exception:{}", key, e);
            return null;
        }
    }

    /**
     * 判斷value是否在key中
     *
     * @param key
     * @param value
     * @return
     */
    public boolean sexists(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            log.error("redis sexists error,key:{},value:{},exception:{}", key, value, e);
            return false;
        }
    }

    /**
     * 插入多個元素
     *
     * @param key
     * @param values
     * @return 成功的個數
     */
    public long sset(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            log.error("redis sset error,key:{},value:{},values:{},exception:{}", key, values, e);
            return 0;
        }
    }

    public long ssetCollection(String key, Collection collection) {
        try {
            Object[] objects = collection.toArray();
            return redisTemplate.opsForSet().add(key, objects);
        } catch (Exception e) {
            log.error("redis sset error,key:{},value:{},values:{},exception:{}", key, collection, e);
            return 0;
        }
    }

    /**
     * 新增元素並設定過期時間  (非原子操作)
     *
     * @param key
     * @param time
     * @param values
     * @return
     */
    public long sset(String key, long time, Object... values) {
        try {
            long count = redisTemplate.opsForSet().add(key, values);
            expire(key, time);
            return count;
        } catch (Exception e) {
            log.error("redis sset error,key:{},value:{},values:{},exception:{}", key, values, e);
            return 0;
        }
    }

    /**
     * 獲取set的長度
     *
     * @param key
     * @return
     */
    public long sgetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            log.error("redis sgetSize error,key:{},exception:{}", key, e);
            return 0;
        }
    }

    /**
     * 移除值為value的
     *
     * @param key    鍵
     * @param values 值 可以是多個
     * @return 移除的個數
     */
    public long sRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            log.error("redis sRemove error,key:{},values:{},exception:{}", key, values, e);
            return 0;
        }
    }

    /**
     * 隨機取count個元素  count為正數就取不重複的  負數就有可能重複
     *
     * @param key
     * @param count
     * @return
     */
    public List<Object> sRandom(String key, long count) {
        try {
            return redisTemplate.opsForSet().randomMembers(key, count);
        } catch (Exception e) {
            log.error("redis sRandom error,key:{},count:{},exception:{}", key, count, e);
            return null;
        }
    }


}

2.依賴(轉json)

package cn.zqs.sqpproduct.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class JacksonUtil {
    @Autowired
    private ObjectMapper objectMapper;

    public String writeAsString(Object obj) {
        try {
            String s = objectMapper.writeValueAsString(obj);
            return s;
        } catch (JsonProcessingException e) {
            log.error("object convert json exception,obj:{}", obj);
            throw new RuntimeException(e);
        }
    }


    public <T> T readValue(String str, Class<T> tClass) {
        try {
            return objectMapper.readValue(str, tClass);
        } catch (JsonProcessingException e) {
            log.error("str convert Object exception,str:{},class:{}", str, tClass);
            throw new RuntimeException(e);
        }
    }

    public <T> List<T> readValueList(String str, Class<T> tClass) {
        try {
            TypeFactory typeFactory = TypeFactory.defaultInstance();
            return objectMapper.readValue(str, typeFactory.constructParametricType(List.class, tClass));
        } catch (JsonProcessingException e) {
            log.error("str convert List<Object> exception,str:{},class:{}", str, tClass);
            throw new RuntimeException(e);
        }
    }

    public <K, V> Map<K, V> readValueMap(String str, Class<K> tClass, Class<V> vClass) {
        try {
            TypeFactory typeFactory = TypeFactory.defaultInstance();
            return objectMapper.readValue(str, typeFactory.constructParametricType(HashMap.class, tClass, vClass));
        } catch (JsonProcessingException e) {
            log.error("str convert Map<K,V> exception,str:{},tClass:{},vClass:{}", str, tClass, vClass);
            throw new RuntimeException(e);
        }
    }

    public Map<String, String> readValueMap(String str) {
        try {

            return objectMapper.readValue(str, HashMap.class);
        } catch (JsonProcessingException e) {
            log.error("str convert Map exception,str:{}", str);
            throw new RuntimeException(e);
        }
    }
}

測試

@SpringBootTest
@RunWith(SpringRunner.class)

public class RedisTest {


    @Autowired
    RedisUtils redisUtils;
    @Test
    public void testRedis(){
        redisUtils.set("zqs","bigBoy");
    }
}

在這裡插入圖片描述

本文章已修改原文用詞符合繁體字使用者習慣使其容易閱讀

版權宣告:此處為CSDN博主「想飛的Duke」的原創文章,依據CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。

原文連結:https://blog.csdn.net/weixin_49161209/article/details/109046859