SpringBoot2.0+Mybatis整合redis(SpringDataRedis)

前言

对于刚接触Spring boot data-redis 的同学,与jedis的关系很容易搞混,这里对data-redis于jedis做一个简单的说明,并提供整合方式

jedis和spring-boot-data-redis区别与关系

jedis是redis的java客户端,通过它可以对redis进行操作。与之功能相似的还包括:Lettuce等。

  1. spring-data-redis
    它依赖jedis或Lettuce,实际上是对jedis这些客户端的封装,提供一套与客户端无关的api供应用使用,从而你在从一个redis客户端切换为另一个客户端,不需要修改业务代码。

  2. spring boot 整合data redis (默认依赖Lettuce)
    spring-boot-data-redis 内部实现了对Lettuce和jedis两个客户端的封装,默认使用的是Lettuce

spring boot 整合data redis (默认依赖Lettuce)

spring-boot-data-redis 内部实现了对Lettuce和jedis两个客户端的封装,默认使用的是Lettuce

使用RedisTemplate
(RedisTemplate是SpringDataRedis中对JedisApi的高度封装。
SpringDataRedis相对于Jedis来说可以方便地更换Redis的Java客户端,比Jedis多了自动管理连接池的特性,方便与其他Spring框架进行搭配使用如:SpringCache)

引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--com/fasterxml/jackson/core/JsonProcessingException-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

在application.yml中配置redis相关的属性

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/master1?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
  redis:
    #redis服务器地址
    host: 88.88.88.142
    #redis服务器端口
    port: 6379
    #服务密码
    password:
    #连接数
    #超时时间
    timeout: 10000ms
    lettuce:
      pool:
        #最大连接数 默认为8
        max-active: 1024
        #最小空闲连接 默认0
        max-wait: 10000ms
        #最大空闲连接 默认8
        max-idle: 200
        #最大连接阻塞等待时间
        min-idle: 5

logging:
  level:
    com.xkcoding: debug
    com.xkcoding.orm.mybatis.mapper: trace

server:
  port: 8080

mybatis:
  type-aliases-package: com.orm.mybatis.redis.entity
  mapper-locations: classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true

创建RedisConfig类

用来创建RedisTemplate或者StringRedisTemplate对象(RedisTemplate和StringRedisTemplate的区别)

@Configuration
public class RedisConfig {

    /**
     * StringRedisTemplate与RedisTemplate区别点
     * 两者的关系是StringRedisTemplate继承RedisTemplate。
     *
     * 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。
     *
     * 其实他们两者之间的区别主要在于他们使用的序列化类:
     *     RedisTemplate使用的是JdkSerializationRedisSerializer    存入数据会将数据先序列化成字节数组然后在存入Redis数据库。
     *
     *       StringRedisTemplate使用的是StringRedisSerializer
     *
     * 使用时注意事项:
     *    当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可。
     *    但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。
     */

    @Bean      //用GenericJackson2JsonRedisSerializer来序列化
    public RedisTemplate redisTemplate(LettuceConnectionFactory lettuceConnectionFactory){
        //我们为了自己开发方便,一般直接使用<String,Object>
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();

        // 设置键(key)的序列化采用StringRedisSerializer
        StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);

        // 设置值(value)的序列化采用GenericJackson2JsonRedisSerializer
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        redisTemplate.setValueSerializer(jsonRedisSerializer);

        //设置连接工厂
        redisTemplate.setConnectionFactory(lettuceConnectionFactory);

        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }


//    @Bean      //用Jackson2JsonRedisSerializer来序列化
//    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
//        //我们为了自己开发方便,一般直接使用<String,Object>
//        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
//
//        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
//        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
//
//        ObjectMapper mapper = new ObjectMapper();
//        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//        //mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);   过期了
//        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
//                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
//
//        serializer.setObjectMapper(mapper);
//
//        redisTemplate.setValueSerializer(serializer);
//        //使用StringRedisSerializer来序列化和反序列化redis的key值
//        StringRedisSerializer stringRedisSerializer=new StringRedisSerializer();
//        redisTemplate.setKeySerializer(stringRedisSerializer);
//        redisTemplate.setHashKeySerializer(stringRedisSerializer);
//
//        redisTemplate.setConnectionFactory(lettuceConnectionFactory);
//
//        redisTemplate.afterPropertiesSet();
//        return redisTemplate;
//    }

    @Bean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(factory);
        return stringRedisTemplate;
    }

}

Jackson2JsonRedisSerializer和GenericJackson2JsonRedisSerializer的区别 https://blog.csdn.net/bai_bug/article/details/81222519

StringRedisTemplate 与 RedisTemplate

RedisTemplate 对五种数据结构分别定义了操作

redisTemplate.opsForValue();
操作字符串

redisTemplate.opsForHash();
操作hash

redisTemplate.opsForList();
操作list

redisTemplate.opsForSet();
操作set

redisTemplate.opsForZSet();
操作有序set

如果操作字符串的话,建议用 StringRedisTemplate 。

StringRedisTemplate 与 RedisTemplate 的区别

StringRedisTemplate 继承了 RedisTemplate。
RedisTemplate 是一个泛型类,而 StringRedisTemplate 则不是。
StringRedisTemplate 只能对 key=String,value=String 的键值对进行操作,RedisTemplate 可以对任何类型的 key-value 键值对操作。
他们各自序列化的方式不同,但最终都是得到了一个字节数组,殊途同归,StringRedisTemplate 使用的是 StringRedisSerializer 类;RedisTemplate 使用的是 JdkSerializationRedisSerializer 类。反序列化,则是一个得到 String,一个得到 Object
两者的数据是不共通的,StringRedisTemplate 只能管理 StringRedisTemplate 里面的数据,RedisTemplate 只能管理 RedisTemplate中的数据。

注解方式使用 Redis 缓存

在启动类上加注解 @EnableCaching

@EnableCaching
@SpringBootApplication
public class SpringbootMybatisRedisApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootMybatisRedisApplication.class, args);
    }

}

常用的注解有以下几个

@Cacheable

用于查询和添加缓存,第一次查询的时候返回该方法返回值,并向 Redis 服务器保存数据。

以后调用该方法先从 Redis 中查是否有数据,如果有直接返回 Redis 缓存的数据,而不执行方法里的代码。如果没有则正常执行方法体中的代码。

value 或 cacheNames 属性做键,key 属性则可以看作为 value 的子键, 一个 value 可以有多个 key 组成不同值存在 Redis 服务器。

验证了下,value 和 cacheNames 的作用是一样的,都是标识主键。两个属性不能同时定义,只能定义一个,否则会报错。

在需要加缓存的方法上添加注解
key为数字 @Cacheable(value = “user”, key = “123”)

key为英文 @Cacheable(value = “user”, key = “‘test’”)

cacheNames 和 key 都必须填,如果不填 key ,默认的 key 是当前的方法名。

下面介绍一下 @Cacheable 这个注解常用的几个属性:

属性解释
cacheNames/value用来指定缓存组件的名字
key缓存数据时使用的 key,可以用它来指定。默认是使用方法参数的值。(这个 key 你可以使用 spEL 表达式来编写)
keyGeneratorkey 的生成器。 key 和 keyGenerator 二选一使用
cacheManager可以用来指定缓存管理器。从哪个缓存管理器里面获取缓存。
condition可以用来指定符合条件的情况下才缓存
unless否定缓存。当 unless 指定的条件为 true ,方法的返回值就不会被缓存。当然你也可以获取到结果进行判断。(通过 #result 获取方法结果)
sync是否使用异步模式。

Key 也可以动态设置为方法的参数

    @Cacheable(value = "user",key = "#id")
    @GetMapping(value = "/get/user")
    public User getUser(@RequestParam Long id){
        User user = userMapper1.selectUserById(id);
        System.out.println("走了DB查询"+id);
        return user;
    }

如果参数是个对象,也可以设置对象的某个属性为 key。比如其中一个参数是 user 对象,key 可以写成 key=“#user.id”

    @Cacheable(value = "user",key = "#user.id")
    @GetMapping(value = "/get/user")
    public User getUser(@RequestBody User user){
        User user = userMapper1.selectUserByUser(user);
        System.out.println("走了DB查询"+user);
        return user;
    }

@CachePut

在需要更新缓存的方法上加注解: @CachePut(cacheNames = “user”, key = “123”)

使用CachePut注解,该方法每次都会执行,会清除对应的key值得缓存(或者更新)。

分为以下两种情况:

情况一:如果返回值null,下次进行该key值查询时,还会查一次数据库,此时相当于@CacheEvict注解;

情况二:如果返回值不为null,此时会进行该key值缓存的更新,更新缓存值为返回的数据;

分析情况一:

查询方法

    @Cacheable(value = "user",key = "#id")
    @GetMapping(value = "/get/user")
    public User getUser(@RequestParam Long id){
        User user = userMapper1.selectUserById(id);
        System.out.println("走了DB查询"+id);
        return user;
    }

更新方法

    @CachePut(value = "user",key = "#user.id")
    @PostMapping(value = "/update/user",produces = "application/json;charset=UTF-8")
    public User updateUser(@RequestBody User user){
        userMapper1.updateUserById(user);
        return null;
    }

相当于添加了@CacheEvict(value=“user”,key=“#user.id”)
下一次访问/get/user方法时候,会重新走一次DB,数据库查询。不走redis。

分析情况二:

查询方法

    @Cacheable(value = "user",key = "#id")
    @GetMapping(value = "/get/user")
    public User getUser(@RequestParam Long id){
        User user = userMapper1.selectUserById(id);
        System.out.println("走了DB查询"+id);
        return user;
    }

更新方法

    @CachePut(value = "user",key = "#user.id")
    @PostMapping(value = "/update/user",produces = "application/json;charset=UTF-8")
    public User updateUser(@RequestBody User user){
        userMapper1.updateUserById(user);
        User user1 = userMapper1.selectUserById(user.getId());
        return user1;
//此时进行id为1数据更新操作,返回值不为null;
//如果下次进行/get/user id为1的数据查询,发现此时id为1缓存被更新为更新的数据,且没有进行DB查询操作;
    }

先进行数据id为1的查询,发现下次查询id为1的数据不会再查询DB,直接走缓存;

@CacheEvict

在需要删除缓存的方法上加注解:@CacheEvict(value= “user”, key = “123”),执行完这个方法之后会将 Redis 中对应的记录删除。

@CacheEvict还有个allEntries属性,默认为false,我们可以将其设置为,清除指定缓存中的所有缓存,这里是user (value =) 。

allEntries 是 @CacheEvict 特有的一个属性,意为是否删除整个缓存(value 或 cacheNames 指定的),默认为 false。

@CacheEvict还有个beforeInvocation属性,默认为false,表示缓存是否在方法执行之前进行清除。默认为false是在方法执行之后执行。

beforeInvocation 是 @CacheEvict 中特有的一个属性,意为是否在执行对应方法之前删除缓存,默认 false(即执行方法之后再删除缓存)。

@Caching

@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。

@Caching(put ={@CachePut(value = "user",key = "#user.id")},
evict = {@CacheEvict(value = "user",key = "'getUserList'"),@CacheEvict(value = "user",key = "1")})
import com.orm.mybatis.redis.entity.User;
import com.orm.mybatis.redis.mapper.UserMapper1;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

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

@RestController
public class RedisController {

    @Resource
    private UserMapper1 userMapper1;

    //@Cacheable用于查询和添加缓存,第一次查询的时候返回该方法返回值,并向 Redis 服务器保存数据。
    //以后调用该方法先从 Redis 中查是否有数据,如果有直接返回 Redis 缓存的数据,而不执行方法里的代码。
    //如果没有则正常执行方法体中的代码。
    //value 或 cacheNames 属性做键,key 属性则可以看作为 value 的子键,一个 value 可以有多个 key 
   // 组成不同值存在 Redis 服务器。
    //验证了下,value 和 cacheNames 的作用是一样的,都是标识主键。两个属性不能同时定义,只能定义一个,否则会报错。
    @Cacheable(value = "user",key = "#id")
    @GetMapping(value = "/get/user")
    public User getUser(@RequestParam Long id){
        User user = userMapper1.selectUserById(id);
        System.out.println("走了DB查询"+id);
        return user;
    }


    @Cacheable(value = "user",key = "'getUserList'")
    @GetMapping(value = "/get/userList")
    public List<User> getUserList(){
        List<User> userList = userMapper1.selectAllUser();
        System.out.println("走了DB查询userList");
        return userList;
    }


    //使用CachePut注解,该方法每次都会执行,会清除对应的key值得缓存(或者更新),
    //分为以下两种情况:
    //如果返回值null,下次进行该key值查询时,还会查一次数据库,此时相当于@CacheEvict注解;
    //如果返回值不为null,此时会进行该key值缓存的更新,更新缓存值为返回的数据;
    //这里会先删除value的user的所有缓存再返回该value对应的key值缓存的新增更新
    @CachePut(value = "user",key = "#user.id")
    @CacheEvict(value = "user", allEntries = true,beforeInvocation = true)
    @PostMapping(value = "/update/user",produces = "application/json;charset=UTF-8")
    public User updateUser(@RequestBody User user){
        userMapper1.updateUserById(user);
        User user1 = userMapper1.selectUserById(user.getId());
        return user1;
        //此时进行id为1数据更新操作,返回值不为null;
        //如果下次进行/get/user id为1的数据查询,发现此时id为1缓存被更新为更新的数据,
        //且没有进行DB查询操作;
    }

    //在需要删除缓存的方法上加注解:@CacheEvict(cacheNames = "user", key = "#id"),
    //执行完这个方法之后会将user 中对所有记录删除。
//    @CacheEvict(value = "user",key = "#id")
    @CacheEvict(value = "user",allEntries = true)
    @GetMapping(value = "/cancel/user")
    public void updateUser(@RequestParam Long id){

    }
    
    //新增的数据put到缓存,删除对应的list数组的value::key的缓存,以及测试用的删除对应的key为1的缓存。
    @Caching(put ={@CachePut(value = "user",key = "#user.id")},
    evict = {@CacheEvict(value = "user",key = "'getUserList'"),@CacheEvict(value = "user",key = "1")})
    @PostMapping(value = "/insert/user")
    public User insertUser(@RequestBody User user){
    userMapper1.saveUser(user);
    System.out.println(user.getId());
    User user1 = userMapper1.selectUserById(user.getId());
    return user1;
    }

}



如上方法能保证在最新访问查数据的接口时候
@Cacheable(value = “user”,key = “#id”)
@GetMapping(value = “/get/user”)

@Cacheable(value = “user”,key = “‘getUserList’”)
@GetMapping(value = “/get/userList”)
如果遇到增删改的话会删除或替换对应缓存,然后下次查询list时候走数据库查询或走新的缓存,而不走旧的数值的缓存。

新建REDIS.utils工具类

package com.orm.mybatis.redis.utils;

@Component
public class RedisUtils {

    @Resource
    private RedisTemplate redisTemplate;

    //=======================common========================

    /**
     * 指定缓存失效时间
     * @param key 键
     * @param time 时间(秒)
     * @return
     */
    public boolean expire(String key,long time){
        try {
            if(time > 0){
                redisTemplate.expire(key,time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据key获取过期时间
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表永久有效
     */
    public long getExpire(String key){

        return redisTemplate.getExpire(key,TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key){

        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     * @param key 可以传一个或多个
     */
    public void del(String... key){
        if(key != null && key.length > 0){
            if(key.length == 1){
                redisTemplate.delete(key[0]);
            }else{
                redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
            }
        }
    }


    // ============================String=============================
    /**
     * 普通缓存获取
     * @param key 键
     * @return 值
     */
    public Object get(String key){
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存放入
     * @param key 键
     * @param value 值
     * @return true 成功 false 失败
     */
    public boolean set(String key,Object value){
        try {
            redisTemplate.opsForValue().set(key,value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // ============================multiSet和 multiGet=============================
    /**
     * 普通缓存获取
     * @param keys 键
     * @return 值
     */
    public List<?> multiGet(ArrayList<?> keys){
        return keys == null ? null : redisTemplate.opsForValue().multiGet(keys);
    }

    /**
     * 普通缓存获取
     * @param keys 键
     * @return 值
     */
    public Set<?> getPattern(String pattern){
        return redisTemplate.keys(pattern);
    }

    /**
     *
     * @param hashMap
     * @return
     */
    public boolean multiSet(HashMap hashMap){
        try {
            redisTemplate.opsForValue().multiSet(hashMap);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存放入并设置时间
     * @param key 键
     * @param value 值
     * @param time 时间(秒)time小于等于0,将设置无限期
     * @return true 成功 false 失败
     */
    public boolean set(String key,Object value,long time){
        try {
            if(time > 0){
                redisTemplate.opsForValue().set(key,value,time,TimeUnit.SECONDS);
            }else{
                set(key,value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     * @param key 键
     * @param delta 要增加几(大于0)
     */
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     * @param key 键
     * @param delta 要减少几(小于0)
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }
// ================================Map=================================
    /**
     * HashGet
     * @param key 键 不能为null
     * @param item 项 不能为null
     */
    public Object hget(String key, String item) {
        return  redisTemplate.opsForHash().get(key, item);
    }
    /**
     * HashGet
     * @param key 键 不能为null
     * @param items 项 不能为null
     */
    public Object hMultiGet(String key, ArrayList<?> items) {
        return redisTemplate.opsForHash().multiGet(key, items);
    }
    /**
     * 获取hashKey对应的所有键值
     * @param key 键
     * @return 对应的多个键值
     */
    public Map<Object, Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }
    /**
     * HashSet
     * @param key 键
     * @param map 对应多个键值
     */
    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, String 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)
     */
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * hash递减
     *
     * @param key 键
     * @param item 项
     * @param by 要减少记(小于0)
     */
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }
    // ============================set=============================
    /**
     * 根据key获取Set中的所有值
     * @param key 键
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key 键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 将数据放入set缓存
     *
     * @param key 键
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     *
     * @param key 键
     * @param time 时间(秒)
     * @param values 值 可以是多个
     * @return 成功个数
     */
    public long sSetAndTime(String key, long time, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     * @param key 键
     * @return
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     *
     * @param key 键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
// ===============================list=================================
    /**
     * 获取list缓存的内容
     *
     * @param key 键
     * @param start 开始
     * @param end 结束 0 到 -1代表所有值
     */
    public List<Object> lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取list缓存的长度
     *
     * @param key 键
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引 获取list中的值
     *
     * @param key 键
     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0
    时,-1,表尾,-2倒数第二个元素,依次类推
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 将list放入缓存
     *
     * @param key 键
     * @param value 值
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key 键
     * @param value 值
     */
    public boolean lPivotSet(String key,String pivot, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key,pivot, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * //右弹出 删除右边第一个
     *
     * @param key 键
     *
     */
    public Object lPop(String key) {
        try {
          Object value =  redisTemplate.opsForList().rightPop(key);
            return value;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 将list放入缓存
     *
     * @param key 键
     * @param value 值
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 将list放入缓存
     *
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0)
                expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据索引修改list中的某条数据
     *
     * @param key 键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 移除N个值为value
     *
     * @param key 键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count,
                    value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // ============================zSet=============================
    /**
     * 根据key获取Set中的所有值
     * @param key 键
     */
    public Set<Object> zSGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForZSet().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 将数据放入set缓存
     *
     * @param key 键
     * @param hashSet 值 可以是多个
     * @return 成功个数
     */
    public long zSSet(String key, HashSet hashSet) {
        try {
            return redisTemplate.opsForZSet().add(key, hashSet);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 将set数据放入缓存
     *
     * @param key 键
     * @param time 时间(秒)
     * @param hashSet 值 可以是多个
     * @return 成功个数
     */
    public long zSSetAndTime(String key, long time, HashSet hashSet) {
        try {
            Long count = redisTemplate.opsForZSet().add(key, hashSet);
            if (time > 0)
                expire(key, time);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取set缓存的长度
     * @param key 键
     * @return
     */
    public long zSGetSetSize(String key) {
        try {
            return redisTemplate.opsForZSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 移除值为value的
     *
     * @param key 键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long zSetRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForZSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

}

测试

package com.orm.mybatis.redis;
@SpringBootTest
class SpringbootMybatisRedisApplicationTests {

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Test
    void testStringRedisTemplate(){
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        stringStringValueOperations.set("age", "20");
        String age = stringStringValueOperations.get("age");
        System.out.println(age);
    }

    @Test
    void testOpsForValue(){
        SimpleDateFormat format = new SimpleDateFormat();
        User user = User.builder().name("andrew").password("123456")
                .email("123@qq.com")
                .phoneNumber("13719180727")
                .salt("123456789")
                .status(1)
                .createTime(format.format(DateUtil.now()))
                .build();

        List<User> list = new ArrayList<>();
        list.add(user);
//        ValueOperations<String, Object> ops = redisTemplate.opsForValue();

        redisUtils.set("user", list);
        Object user1 = redisUtils.get("user");
        List<User> list1 = (List<User>) redisUtils.get("user");
        System.out.println(user1);
        System.out.println(list1);
    }

    @Test
    void testOpsForValueMulti(){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        User user1 = User.builder().name("andrew").password("123456")
                .email("123@qq.com")
                .phoneNumber("13719180727")
                .salt("123456789")
                .status(1)
                .createTime(format.format(DateUtil.now()))
                .build();

        User user2 = User.builder().name("andrew1").password("123456")
                .email("123@qq.com")
                .phoneNumber("13719180727")
                .salt("123456789")
                .status(1)
                .createTime(format.format(DateUtil.now()))
                .build();

        HashMap<String,User> hashMap = new HashMap<>();
        hashMap.put("user1",user1);
        hashMap.put("user2",user2);

//        ValueOperations<String, Object> ops = redisTemplate.opsForValue();

        redisUtils.multiSet(hashMap);
        ArrayList<String> keys = new ArrayList<>();
        keys.add("user1");
        keys.add("user2");
        List<User> list1 = (List<User>) redisUtils.multiGet(keys);
        list1.forEach(System.out::println);

        redisUtils.del("user1");
        List<User> list2 = (List<User>) redisUtils.multiGet(keys);
        list2.forEach(System.out::println);
    }

    /**
     * 操作hash
     */
    @Test
    public void testHash() {

        /**
         * 添加的第一条数据
         * redis的key
         * hash的key
         * hash的值
         */
        redisUtils.hset("userall", "name", "zhangsan");

        /**
         * 获取一条数据
         * 第一个参数redis的key
         * 第二个参数hash的key
         */
        Object object = redisUtils.hget("userall", "name");
        System.out.println(object);


        //添加多条数据
        //存多条数据
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "zhangsan");
        map.put("age", "14");
        map.put("sex", "nan");
        redisUtils.hmset("userall1", map);

        //获取多条数据
        //把key装入结合中
        ArrayList<String> keys = new ArrayList<>();
        keys.add("name");
        keys.add("age");
        keys.add("sex");
        //拿取多条数据
        List user = (List) redisUtils.hMultiGet("userall1", keys);
        user.forEach(System.out::println);

        //获取hash类型的所有数据
        Map<Object, Object> entries = redisUtils.hmget("userall1");
        entries.forEach((key, value) -> System.out.println(key + "-->" + value));

        //hash自带的删除
        redisUtils.hdel("userall", "name");

        //获取hash类型的所有数据
        Map<Object, Object> entries1 = redisUtils.hmget("userall");
        entries1.forEach((key, value) -> System.out.println(key + "-->" + value));

    }

    /**
     * 操作list
     */
    @Test
    public void testList() {
        redisUtils.del("students");
        //左添加
        redisUtils.lSet("students", "张三");
        //第一个参数redis的key 第二个参数被左添加的数据
        redisUtils.lPivotSet("students", "张三", "钱二");
        redisUtils.lSet("students", "李四");

        //右添加
        redisUtils.lSet("students", "牛牛");

        //获取数据
        List students = redisUtils.lGet("students", 0, -1);
        students.forEach(System.out::println);

        //获取总条数
        Long size = redisUtils.lGetListSize("students");
        System.out.println(size);

        //删除
        redisUtils.lRemove("students", 1, "张三");

        //左弹出 删除右边第一个
        redisUtils.lPop("students");

        //右弹出 删除右边第一个
        redisUtils.lPop("students");
    }

    /**
     * 操作set
     */
    @Test
    public void testSet() {
        //添加数据
        String[] arr = new String[]{"aaa", "bbb", "ccc","aaa", "ddd"};

        redisUtils.sSet("letters", "111", "33", "334");
        redisUtils.sSet("letters", arr);

        //获取数据
        Set letters = redisUtils.sGet("letters");
        letters.forEach(System.out::println);

        //删除
        redisUtils.setRemove("letters", "aaa", "111");
    }

    /**
     * 操作sorted set
     */

    @Test
    public void testSortedSet() {

        //添加数据
        ZSetOperations.TypedTuple<Object> objectTypedTuple = new DefaultTypedTuple<>("zhangsan", 7D);
        ZSetOperations.TypedTuple<Object> objectTypedTuple2 = new DefaultTypedTuple<>("lisi", 2D);
        ZSetOperations.TypedTuple<Object> objectTypedTuple3 = new DefaultTypedTuple<>("wangwu", 9D);
        ZSetOperations.TypedTuple<Object> objectTypedTuple4 = new DefaultTypedTuple<>("zhaoliu", 3D);

        HashSet<ZSetOperations.TypedTuple<Object>> tuples = new HashSet<>();
        tuples.add(objectTypedTuple);
        tuples.add(objectTypedTuple2);
        tuples.add(objectTypedTuple3);
        tuples.add(objectTypedTuple4);
        redisUtils.zSSet("score", tuples);

        //zSetOperations.add("name","niuniu",7D);

        //获取数据
        Set set = redisUtils.zSGet("score", 0, -1);
        set.forEach(System.out::println);

        //总条数
        Long size = redisUtils.zSGetSetSize("score");
        System.out.println(size);

        //删除数据
        redisUtils.zSetRemove("score", "zhangsan", "lisi");
    }

    /**
     * 获取所有的key
     */
    @Test
    public void testAllKeys() {
        Set keys = redisUtils.getPattern("*");
        keys.forEach(System.out::println);
    }

    /**
     * 失效时间
     */
    @Test
    public void testExpire() {

        //方法一 添加key的时候设置失效时间
        redisUtils.set("code", "test", 30);

        //方法二 给已经存在的key设置失效时间
        redisUtils.set("address", "添加时未设置失效时间");
        redisUtils.expire("address", 30);

        //查看失效时间
        Long code = redisUtils.getExpire("code");
        System.out.println(code);

        Long time = redisUtils.getExpire("address");
        System.out.println(time);
    }
}

项目地址:

https://gitee.com/liuweiqiang12/springboot

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶孤崖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值