1. SpringBoot整合

  Jedis是官方推荐的Java链接开发工具,使用Java操作Redis中间件。


1.1 创建一个SpringBoot项目

  参考 => SpringBoot常用注解、lombok常用注解 中的〇、创建springboot项目;注意额外还要选中NoSQL的Spring Data Redis

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_美食


  新建的项目检查一下maven位置是否正确

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_宠物_02


【说明】Jedis -> lettuce

  说明: Spring2.X 之后,原来使用的Jedis被替换成了lettuce

  jedis: 底层采用直连server,多个线程操作是不安全的,如果想要避免不安全的,使用 jedis pool 连接池。就会带来一系列问题(线程过多会导致redis server很大,类似于同步阻塞模式BIO)。

  lettuce: 采用netty,实例可以在多个线程中共享,不存在线程不安全的情况,可以减少线程数量,性能更好(类似于同步非阻塞式NIO)。

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_nosql_03

   lettuce底层使用了netty。

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_redis_04


1.2 Redis配置文件

参考源码 RedisProperties,如果是本机,6379端口完全可以不用配置,因为已经有默认值了。

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_spring_05


Step1. 导包

  pom.xml:创建springboot项目时,勾选NoSQL->Spring Data Redis自动就导入了。

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

Step2. 配置连接
  application.properties

# SpringBoot所有的配置类,都有一个自动配置类    RedisAutoConfiguration
# 自动配置类都会绑定一个 properties 配置文件    RedisProperties

# 配置redis
    # 主机ip:
    spring.redis.host=localhost
    # 端口号:默认为6379
    spring.redis.port=6379
    # 数据库:默认为0
    spring.redis.database=0

1.3 测试编码

Step3. 测试编码,RedisTemplate操作是比较麻烦的,最好再自己封装一个模板来操作。

package com.groupies.springbootredis;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class SpringbootRedisApplicationTests {

    //Redis相关
    @Autowired
    RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        redisTemplate.getConnectionFactory().getConnection().flushDb();//清空当前数据库

        redisTemplate.opsForValue().set("springboot", "redis");
        redisTemplate.opsForValue().set("hello", "world");

        System.out.println(redisTemplate.opsForValue().get("springboot"));
        System.out.println(redisTemplate.opsForValue().get("hello"));
        redisTemplate.getConnectionFactory().getConnection().close();//关闭连接
    }
        /* 1) 五种数据类型
           redisTemplate.opsForValue 操作字符串类型 类似String
           redisTemplate.opsForList 操作List列表
           redisTemplate.opsForSet 操作Set集合
           redisTemplate.opsForZSet 操作Zset有序集合
           redisTemplate.opsForHash 操作Hash散列
           redisTemplate.opsForGeo 操作Geo地理空间
           redisTemplate.opsForHyperLogLog 操作Hyper基数统计

                redisTemplate.opsForValue().set("k1", "v1");
        */
        /*
           2)除了基本的操作,常用方法可以直接通过redisTemplate操作,比如事务和基本的curd
                redisTemplate.watch("money");//开启监控
                redisTemplate.multi();//开启事务
        */
        /*
           3) 获取redis的连接对象
                RedisConnection conn = redisTemplate.getConnectionFactory().getConnection();
                conn.flushDb();//清空当前数据库
                conn.close();//关闭连接
        */
}

 redis-cli查看显示是乱码,原因是没有做序列化。

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_美食_06


2. Serialize 序列化问题

需要准备一个pojo类User,在SpringbootRedisApplicationTests中测试。

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_redis_07


2.1 User未序列化


User


package com.groupies.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User{
    private String name;
    private Integer age;
}


SpringbootRedisApplicationTests


package com.groupies.springbootredis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.groupies.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class SpringbootRedisApplicationTests {

    //Redis相关
    @Autowired
    RedisTemplate redisTemplate;

    @Test
    public void test() throws JsonProcessingException {
        //准备数据
        User user = new User("张三", 3);
        //pojo -> String
        String jsonUser = new ObjectMapper().writeValueAsString(user);

        //清空当前数据库
        redisTemplate.getConnectionFactory().getConnection().flushDb();

        //执行命令
        redisTemplate.opsForValue().set("user", jsonUser);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果: {"name":"张三","age":3}

        redisTemplate.opsForValue().set("user", user);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果:

        //关闭连接
        redisTemplate.getConnectionFactory().getConnection().close();
    }
}

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_redis_08


2.2 User序列化


User


package com.groupies.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User implements Serializable{
    private String name;
    private Integer age;
}


SpringbootRedisApplicationTests


package com.groupies.springbootredis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.groupies.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class SpringbootRedisApplicationTests {

    //Redis相关
    @Autowired
    RedisTemplate redisTemplate;

    @Test
    public void test() throws JsonProcessingException {
        //准备数据
        User user = new User("张三", 3);
        //pojo -> String
        String jsonUser = new ObjectMapper().writeValueAsString(user);

        //清空当前数据库
        redisTemplate.getConnectionFactory().getConnection().flushDb();

        //执行命令
        redisTemplate.opsForValue().set("user", jsonUser);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果: {"name":"张三","age":3}

        redisTemplate.opsForValue().set("user", user);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果:User(name=张三, age=3)

        //关闭连接
        redisTemplate.getConnectionFactory().getConnection().close();
    }
}

 RedisTemplate中默认序列化jdk序列化,jdk序列化会丢字符串进行转义,这是导致乱码的原因。



3. RedisTemplate自定义模板解决乱码


3.1 自定义模板原理

  通过springboot的autoconfigure找到redis配置文件 RedisAutoConfiguration。

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_spring_09

  源码分析: @ConditionalOnMissingBean如果而注册相同类型的bean,就不会成功。以此来保证bean只有一个。当你注册多个相同的bean时,会出现异常。因此可以自定义一个 redisTemplate 来让默认的模板失效。

public class RedisAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean(name = {"redisTemplate"})
    @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

 【说明】乱码问题:RedisAutoConfiguration使用默认的RedisTemplate,这里是jdk序列化,会产生乱码,所以需要自自定义一个redisTemplate



3.2 模板内容

package com.groupies.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
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;

/**
 * @author GroupiesM
 * @date 2022/03/08
 * @introduction 编写自己的 redisTemplate
 *
 * 从RedisAutoConfiguration复制一份,进行修改
 */

@Configuration
public class RedisConfig {

    @Bean
    @SuppressWarnings("all")
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        // 为了开发方便 将<Obj,Obj> 改为<Str,Obj>
        RedisTemplate<String, Object> template = new RedisTemplate();

        template.setConnectionFactory(factory);

        //配置具体的序列化方式
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        //json对象通过ObjectMapper转义
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        //Json类型序列化
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //String类型序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key的序列化方式:String
        template.setKeySerializer(stringRedisSerializer);
        // hash的key的序列化方式:String
        template.setHashKeySerializer(stringRedisSerializer);
        // hash的value的序列化方式:jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();

        return template;
    }
}

3.3 自定义Template测试


User


package com.groupies.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User implements Serializable{
    private String name;
    private Integer age;
}


SpringbootRedisApplicationTests


package com.groupies.springbootredis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.groupies.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class SpringbootRedisApplicationTests {

    //Redis相关
    @Autowired
    @Qualifier("redisTemplate")
    RedisTemplate redisTemplate;

    @Test
    public void test() throws JsonProcessingException {
        //准备数据
        User user = new User("张三", 3);
        //pojo -> String
        String jsonUser = new ObjectMapper().writeValueAsString(user);

        //清空当前数据库
        redisTemplate.getConnectionFactory().getConnection().flushDb();

        //执行命令
        redisTemplate.opsForValue().set("user", jsonUser);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果: {"name":"张三","age":3}

        redisTemplate.opsForValue().set("user", user);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果:User(name=张三, age=3)

        //关闭连接
        redisTemplate.getConnectionFactory().getConnection().close();
    }
}

仍然是乱码,自定义模板未生效,原因不详

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_redis_10


4. StringRedisTemplate解决乱码

  StringRedisTemplate可以解决乱码问题英文乱码问题,但是不支持json格式数据,而且中文仍然显示为乱码。


4.1 测试


User


package com.groupies.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User implements Serializable{
    private String name;
    private Integer age;
}


SpringbootRedisApplicationTests


package com.groupies.springbootredis;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.groupies.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class SpringbootRedisApplicationTests {

    //Redis相关
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    public void test() throws JsonProcessingException {
        //准备数据
        User user = new User("张三", 3);
        //pojo -> String
        String jsonUser = new ObjectMapper().writeValueAsString(user);

        //清空当前数据库
        redisTemplate.getConnectionFactory().getConnection().flushDb();

        //执行命令
        redisTemplate.opsForValue().set("user", jsonUser);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果: {"name":"张三","age":3}

        redisTemplate.opsForValue().set("user", user);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果:User(name=张三, age=3)

        //关闭连接
        redisTemplate.getConnectionFactory().getConnection().close();
    }
}

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_nosql_11


5. RedisTemplate解决乱码2

  StringRedisTemplate可以解决乱码问题英文乱码问题,但是不支持json格式数据,而且中文仍然显示为乱码。


5.1 测试


User


package com.groupies.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User implements Serializable{
    private String name;
    private Integer age;
}


SpringbootRedisApplicationTests


package com.groupies.springbootredis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.groupies.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
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;

@SpringBootTest
class SpringbootRedisApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void redisTemplateSet() throws JsonProcessingException {
        //初始化redisTemplate
        redisSerializer(redisTemplate);

        //准备数据
        User user = new User("张三", 3);
        //pojo -> String
        String userStr = new ObjectMapper().writeValueAsString(user);
        //清空当前数据库
        redisTemplate.getConnectionFactory().getConnection().flushDb();

        //执行命令
        redisTemplate.opsForValue().set("user", userStr);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果:{"name":"张三","age":3}

        redisTemplate.opsForValue().set("userPojo", user);
        System.out.println(redisTemplate.opsForValue().get("user"));//打印结果:{"name":"张三","age":3}

        //关闭连接
        redisTemplate.getConnectionFactory().getConnection().close();
    }


    /**
     *  @introduction 序列化redisTemplate方法
     */
    public static void redisSerializer(RedisTemplate template){
        //配置具体的序列化方式
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        template.setKeySerializer(jackson2JsonRedisSerializer);

        //json对象通过ObjectMapper转义
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        //Json类型序列化
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //String类型序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // key的序列化方式:String
        template.setKeySerializer(stringRedisSerializer);
        // value的序列化方式:String
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的key的序列化方式:String
        template.setHashKeySerializer(stringRedisSerializer);
        // hash的value的序列化方式:jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
    }
}

springboot redis 实现订单超时自动取消 springboot redis lettuce 大量等待_spring_12


6. RedisUtil

/**
 * 定义为一个组件
 */
@Component
public final class RedisUtil {

    /**
     * 注入RedisTemplate
     */
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 指定缓存失效时间
     *
     * @param key  键
     * @param time 时间(秒)
     * @return
     * @author twy
     */
    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
     * @return 返回时间(秒),返回0代表永久有效
     * @author twy
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     *
     * @param key 键
     * @return 存在true  不存在false
     * @author twy
     */
    public boolean hasKey(String key) {
        try {
            redisTemplate.hasKey(key);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     *
     * @param key 可以传一个或者多个值(相当于数组)
     * @author twy
     */
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 0) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete(Arrays.asList(key));
            }
        }
    }

    /******************************************************String*******************************************************/

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

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


    /**
     * 普通缓存放入并设置过期时间(秒)
     *
     * @param key
     * @param value
     * @return
     * @author twy
     */
    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                redisTemplate.opsForValue().set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     *
     * @param key
     * @param delta 增加的数值(大于0)
     * @return
     * @author twy
     */
    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)
     * @return
     * @author twy
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    /******************************************************Map*******************************************************/

    /**
     * 根据key和vale获取对应的值
     *
     * @param key
     * @param item
     * @return
     * @author twy
     */
    public Object hGet(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }


    /**
     * 获取hash的key对应的所有值
     *
     * @param key
     * @return
     * @author twy
     */
    public Map<Object, Object> hMget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet 以map格式存入
     *
     * @param key 键
     * @param map 对应多个键值
     * @return
     * @author twy
     */
    public boolean hMset(String key, Map<Object, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * HashSet 以map格式存入(并设置过期时间)
     *
     * @param key  键
     * @param map  对应多个键值
     * @param time 时间(秒)
     * @return true 成功  false 失败
     * @author twy
     */
    public boolean hMset(String key, Map<Object, 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
     * @author twy
     */
    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  过期时间,如果已存在time,则会替换掉原有的时间
     * @return
     * @author twy
     */
    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
     * @param item 项  可以有多个但是不能为null
     * @author twy
     */
    public void hDel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判断hash中是否存在该项的值
     *
     * @param key
     * @param item
     * @return
     * @author twy
     */
    public boolean hHaskey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

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

    /**
     * hash递减
     *
     * @param key   键
     * @param item  项
     * @param detal 递减的值(小于0)
     * @return
     * @author twy
     */
    public double hDecr(String key, String item, double detal) {
        return redisTemplate.opsForHash().increment(key, item, -detal);
    }

    /******************************************************Set*******************************************************/

    /**
     * 根据key获取set中所有的值
     *
     * @param key
     * @return
     * @author twy
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 根据key和value查询在set中是否存在
     *
     * @param key
     * @param value
     * @return
     * @author twy
     */
    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 返回成功的个数
     * @author twy
     */
    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 values 值(可以是多个)
     * @param time   过期时间
     * @return 返回成功的个数
     * @author twy
     */
    public long sSet(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
     * @author twy
     */
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 在set缓存中移出值为values的key
     *
     * @param key
     * @param values 值可以为多个
     * @return
     * @author twy
     */
    public long setRemove(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().remove(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /******************************************************List*******************************************************/

    /**
     * 获取lis缓存的内容
     *
     * @param key
     * @param start 开始
     * @param end   结束    (0 -1)-->获取所有值
     * @return
     * @author twy
     */
    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缓存d 长度
     *
     * @param key
     * @return
     * @author twy
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 通过索引获取list中的值
     *
     * @param key
     * @param index 索引 0:表头 1:第二个元素 -1:表尾 -2:倒数第二个元素
     * @return
     * @author twy
     */
    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
     * @return
     * @author twy
     */
    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
     * @param time
     * @return
     * @author twy
     */
    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缓存放入值,放入list
     *
     * @param key
     * @param value
     * @return
     * @author twy
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * list缓存放入值,放入list,增加过期时间
     *
     * @param key
     * @param value
     * @return
     * @author twy
     */
    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;
        }
    }

    /**
     * 移出count个值为value的key
     *
     * @param key
     * @param count 移出多少个
     * @param value
     * @return
     * @author twy
     */
    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;
        }
    }
    //先写到这里啦.....按照这种样式写就完事了
}

22/03/08

M