springboot中使用redis(lettuce)

五 SpringBoot2.x中redis使用(lettuce)

Jedis–》进一步做了封装。 --》RedisTemplate

JDBCTemplate

RestTemplate

java代码操作Redis,需要使用Jedis,也就是redis支持java的第三方类库
注意:Jedis2.7以上的版本才支持集群操作

maven配置

新建SpringBoot2.0.3的WEB工程,在MAVEN的pom.xml文件中加入如下依赖

<dependencies>
       
       <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>

        
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-pool2artifactId>
        dependency>
		
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
  dependencies>

hibernate–>JPA–>SpringData

配置文件配置

application.yml

spring:
  redis:
    port: 6379
    password: root
    host: 192.168.245.128
    lettuce:
      pool:
        max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
        max-idle: 8 # 连接池中的最大空闲连接
        min-idle: 0 # 连接池中的最小空闲连接
        max-wait: 1000 # 连接池最大阻塞等待时间(使用负值表示没有限制)
      shutdown-timeout: 100   # 关闭超时时间

redis配置类

JdbcTemplate–>JDBC 进一步封装。

RedisTemplate–>redis进行了进一步封装 (lettuce)

简介

编写缓存配置类RedisConfig用于调优缓存默认配置,RedisTemplate的类型兼容性更高

大家可以看到在redisTemplate()这个方法中用JacksonJsonRedisSerializer更换掉了Redis默认的序列化方式:JdkSerializationRedisSerializer

spring-data-redis中序列化类有以下几个:

GenericToStringSerializer:可以将任何对象泛化为字符创并序列化
Jackson2JsonRedisSerializer:序列化Object对象为json字符创(与JacksonJsonRedisSerializer相同)
JdkSerializationRedisSerializer:序列化java对象
StringRedisSerializer:简单的字符串序列化

JdkSerializationRedisSerializer序列化被序列化对象必须实现Serializable接口,被序列化除属性内容还有其他内容,长度长且不易阅读,默认就是采用这种序列化方式

存储内容如下:

“\xac\xed\x00\x05sr\x00!com.oreilly.springdata.redis.User\xb1\x1c \n\xcd\xed%\xd8\x02\x00\x02I\x00\x03ageL\x00\buserNamet\x00\x12Ljava/lang/String;xp\x00\x00\x00\x14t\x00\x05user1”

JacksonJsonRedisSerializer序列化,被序列化对象不需要实现Serializable接口,被序列化的结果清晰,容易阅读,而且存储字节少,速度快

存储内容如下:

“{“userName”:“guoweixin”,“age”:20}”

StringRedisSerializer序列化

一般如果key、value都是string字符串的话,就是用这个就可以了

RedisConfig类

package com.qfjy.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;

/**
 * @ClassName RedisConfig
 * @Description TODO
 * @Author guoweixin
 * @Version 1.0
 */
@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    /**
     * 自定义缓存key的生成策略。默认的生成策略是看不懂的(乱码内容) 通过Spring 的依赖注入特性进行自定义的配置注入并且此类是一个配置类可以更多程度的自定义配置
     *
     * @return
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * 缓存配置管理器
     */
    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory factory) {
        //以锁写入的方式创建RedisCacheWriter对象
        RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(factory);
        //创建默认缓存配置对象
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        RedisCacheManager cacheManager = new RedisCacheManager(writer, config);
        return cacheManager;
    }

    @Bean
    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
        RedisTemplate<String,Object> template = new RedisTemplate <>();
        template.setConnectionFactory(factory);

        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);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // 在使用注解@Bean返回RedisTemplate的时候,同时配置hashKey与hashValue的序列化方式。
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);

        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

代码示例

RedisServiceImpl

测试String类型
@Service
@Log
public class RedisServiceImpl {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;


    /**
     * 普通缓存放入
     * @param key 键
     * @return true成功 false失败
     */
    public String getString(String key) {
        if(redisTemplate.hasKey(key)) {
            log.info("Redis中查询");
           return (String) redisTemplate.opsForValue().get(key);
        }else{
            String val="guoweixin";
            redisTemplate.opsForValue().set(key, val);
            log.info("数据库中查询的");
            return  val;
        }

    }

    /**
     * 普通缓存放入
     * @param key 键
     * @param value 值
     * @param expireTime 超时时间(秒)
     * @return true成功 false失败
     */
    public Boolean set(String key, Object value, int expireTime) {
        try {
            redisTemplate.opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}    
测试Hash类型
@Service
@Log
public class RedisServiceImpl {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Resource(name="redisTemplate")
    private HashOperations<String,String,User> hash;
     /**
     * 判断key是否存在,如果存在 在Redis中查询
     * 如果不存在,在MYSQL中查询,并将结果得到,添加到Redis Hash中
     * @param id
     * @return
     */
      public User selectUserById1(String id){
        if(hash.hasKey("user",id)){
            log.info("Redis中查询对象");
            return  hash.get("user",id);
        }else{
            User u=new User();
            u.setId(id);
            u.setName("guoweixin");
            u.setAge(22);
            log.info("mysql中查询对象");
            hash.put("user",id,u);
            return u;
        }
    }
}   
    

hash类型代码示例

package com.qfjy.redis.demo.service.impl;

import com.qfjy.redis.demo.service.HashCacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service("hashCacheService")
public class HashCacheServiceImpl implements HashCacheService {
    private final static Logger log = LoggerFactory.getLogger(HashCacheServiceImpl.class);

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 获取MAP中的某个值
     * @param key  键
     * @param item 项
     * @return 值
     */
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey对应的所有键值
     * @param key 键
     * @return 对应的多个键值
     */
    public Map <Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 以map集合的形式添加键值对
     * @param key 键
     * @param map 对应多个键值
     * @return true 成功 false 失败
     */
    public boolean hmset(String key, Map <String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 并设置时间
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true成功 false失败
     */
    public boolean hmset(String key, Map <String, Object> map, long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     * @param key   键
     * @param item  项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 向一张hash表中放入数据,如果不存在将创建
     * @param key   键
     * @param item  项
     * @param value 值
     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
     * @return true 成功 false失败
     */
    public boolean hset(String key, String item, Object value, long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判断hash表中是否有该项的值
     * @param key  键 不能为null
     * @param item 项 不能为null
     * @return true 存在 false不存在
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * hash递增 如果不存在,就会创建一个 并把新增后的值返回
     * @param key  键
     * @param item 项
     * @param by   要增加几(大于0)
     * @return
     */
    public long hincr(String key, String item, long by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash递减
     * @param key  键
     * @param item 项
     * @param by   要减少记(小于0)
     * @return
     */
    public long hdecr(String key, String item, long by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }

    /**
     * 获取指定变量中的hashMap值。
     * @param key
     * @return 返回LIST对象
     */
    @Override
    public List<Object> values(String key) {
        return redisTemplate.opsForHash().values(key);
    }

    /**
     *  获取变量中的键。
     * @param key
     * @return 返回SET集合
     */
    @Override
    public Set<Object> keys(String key) {
        return  redisTemplate.opsForHash().keys(key);
    }

    /**
     * 获取变量的长度。
     * @param key 键
     * @return  返回长度
     */
    @Override
    public long size(String key) {
        return redisTemplate.opsForHash().size(key);
    }

    /**
     * 以集合的方式获取变量中的值。
     * @param key
     * @param list
     * @return 返回LIST集合值
     */
    @Override
    public List multiGet(String key, List list) {
        return redisTemplate.opsForHash().multiGet(key,list);
    }

    /**
     *  如果变量值存在,在变量中可以添加不存在的的键值对
     *  如果变量不存在,则新增一个变量,同时将键值对添加到该变量。
     * @param key
     * @param hashKey
     * @param value
     */
    @Override
    public void putIfAbsent(String key, String hashKey, Object value) {
        redisTemplate.opsForHash().putIfAbsent(key,hashKey,value);
    }

    /**
     * 匹配获取键值对,ScanOptions.NONE为获取全部键对,ScanOptions.scanOptions().match("map1").build()
     * 匹配获取键位map1的键值对,不能模糊匹配。
     * @param key
     * @param options
     * @return
     */
    @Override
    public Cursor<Map.Entry<Object, Object>> scan(String key, ScanOptions options) {
        return  redisTemplate.opsForHash().scan(key,options);
    }

    /**
     * 删除变量中的键值对,可以传入多个参数,删除多个键值对。
     * @param key 键
     * @param hashKeys MAP中的KEY
     */
    @Override
    public void delete(String key, String... hashKeys) {
        redisTemplate.opsForHash().delete(key,hashKeys);
    }

    public boolean expire(String key, long seconds) {
        return redisTemplate.expire(key,seconds,TimeUnit.SECONDS);
    }

    /**
     * 删除
     * @param keys
     */
    @Override
    public void del(String... keys) {
        if (keys != null && keys.length > 0) {
            if (keys.length == 1) {
                redisTemplate.delete(keys[0]);
            } else {
                redisTemplate.delete(CollectionUtils.arrayToList(keys));
            }
        }
    }

    @Override
    public long getExpire(String key) {
        return 0;
    }
}

你可能感兴趣的:(redis,java,spring)