GVKun编程网logo

SpringBoot中注入RedisTemplate实例异常解决(转)(springboot redis lettuce)

14

对于SpringBoot中注入RedisTemplate实例异常解决感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍转,并为您提供关于33.Springboot系列原生方式引入Redis,非Re

对于SpringBoot中注入RedisTemplate实例异常解决感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍,并为您提供关于33. Springboot 系列 原生方式引入Redis,非RedisTemplate、Java 使用Jedis和RedisTemplate操作Redis缓存(SpringBoot)、Redis 系列-- SpringBoot 中 redisTemplate 的操作、Redis整合SpringBoot的RedisTemplate实现类(实例详解)的有用信息。

本文目录一览:

SpringBoot中注入RedisTemplate实例异常解决(转)(springboot redis lettuce)

SpringBoot中注入RedisTemplate实例异常解决(转)(springboot redis lettuce)

最近,在项目开发过程中使用了RedisTemplate,进行单元测试时提示“Field redisTemplate in com.example.demo1.dao.RedisDao required a bean of type ‘org.springframework.data.redis.core.RedisTemplate’ that could not be found”,翻译过来就是“找不到类型为RedisTemplate的bean”。当然,仅看这句话我们无法确定为什么会出现这个问题。现在,贴出详细的错误日志。

2018-08-10 14:53:49.761 - Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@5af3afd9] to prepare test instance [com.example.demo1.Demo1ApplicationTests@2361365c]
java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ''redisDao'': Unsatisfied dependency expressed through field ''redisTemplate''; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ''org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>'' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303)
    at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:120)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 25 common frames omitted
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type ''org.springframework.data.redis.core.RedisTemplate<java.lang.String, java.lang.Object>'' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
    ... 43 common frames omitted

看到这一大段错误日志是不是有点晕,其实我们只需要看关键的错误日志就可以定位到问题。错误日志中的第二个Caused by打印了关键的错误日志:No qualifying bean of type ‘org.springframework.data.redis.core.RedisTemplate< java.lang.String, java.lang.Object>

笔主回看写的代码,在注入RedisTemplate< K, V>时指定了具体的类型。

@Component
public class RedisDao {

    /**
     * 注入时指定了K、V类型
     */
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

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

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

根据错误日志查看DefaultListableBeanFactory这个类的第1493行的代码,源码如下:

/**
     * 为无法解决的依赖抛出NoSuchBeanDefinitionException或BeanNotOfRequiredTypeException。
     * Raise a NoSuchBeanDefinitionException or BeanNotOfRequiredTypeException
     * for an unresolvable dependency.
     */
    private void raiseNoMatchingBeanFound(
            Class<?> type, ResolvableType resolvableType, DependencyDescriptor descriptor) throws BeansException {

        checkBeanNotOfRequiredType(type, descriptor);
        //抛出NoSuchBeanDefinitionException
        throw new NoSuchBeanDefinitionException(resolvableType,
                "expected at least 1 bean which qualifies as autowire candidate. " +
                "Dependency annotations: " + ObjectUtils.nullSafeToString(descriptor.getAnnotations()));
    }

   /**
     * 为无法解决的依赖抛出BeanNotOfRequiredTypeException,如果适用,例如,bean的目标类型匹配但是公开的代理不匹配。
     * 
     * 
     * Raise a BeanNotOfRequiredTypeException for an unresolvable dependency, if applicable,
     * i.e. if the target type of the bean would match but an exposed proxy doesn''t.
     */
    private void checkBeanNotOfRequiredType(Class<?> type, DependencyDescriptor descriptor) {
        for (String beanName : this.beanDefinitionNames) {
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            Class<?> targetType = mbd.getTargetType();
            if (targetType != null && type.isAssignableFrom(targetType) &&
                    isAutowireCandidate(beanName, mbd, descriptor, getAutowireCandidateResolver())) {
                // Probably a proxy interfering with target type match -> throw meaningful exception.
                Object beanInstance = getSingleton(beanName, false);
                Class<?> beanType = (beanInstance != null ? beanInstance.getClass() : predictBeanType(beanName, mbd));
                if (!type.isAssignableFrom((beanType))) {
                    //抛出BeanNotOfRequiredTypeException
                    throw new BeanNotOfRequiredTypeException(beanName, type, beanType);
                }
            }
        }

        BeanFactory parent = getParentBeanFactory();
        if (parent instanceof DefaultListableBeanFactory) {
            ((DefaultListableBeanFactory) parent).checkBeanNotOfRequiredType(type, descriptor);
        }
    }

这两个方法说明了没有找到RedisTemplate< String, Object>可以匹配的Bean,那么这个问题该如何解决呢?不妨在使用RedisTemplate< K, V>时不指定具体的类型,修改代码如下:

/**
 * 注入时不指定K、V的类型 
 */
@Autowired
private RedisTemplate redisTemplate;

重新启动服务,启动日志没有报错,RedisTemplate注入Bean成功了。为什么RedisTemplate< String, Object>注入Bean会失败呢,很是纳闷。思考很久,想到RedisTemplate在SpringBoot框架中是自动配置的,容器中默认的就是RedisTemplate的实例。想到这里,就需要翻下官网的文档,看看官网文档有没有什么说明。果然,官方文档第30.1.1章节还是针对RedisTemplate做了说明。

官方文档地址:https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/

 

 

If you add your own @Bean of any of the auto-configured types, it replaces the default (except in the case of RedisTemplate, when the exclusion is based on the bean name, redisTemplate, not its type).

如果针对自动配置类型添加自己的Bean,它将取代默认的。我的代码好像写的没问题啊,等等…括号中这句话才是重点啊。翻译一波,在RedisTemplate的情况下除外,当排除基于Bean的名称,而不是它的类型。英文不太好,怎么翻译好像都不大通顺。

现在好像明白了,刚才的RedisTemplate< String, Object>注入时用到了@Autowired,@Autowired默认按照类型装配的。也就是说,想要获取RedisTemplate< String, Object>的Bean,要根据名字装配。那么自然想到使用@Resource,它默认按照名字装配。再次修改代码如下:

/**
     * 注入时指定了K、V类型
     */
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

再次重新启动服务,启动日志没有报错,RedisTemplate< String, Object>注入Bean成功了。通过这个错误,学习到SpringBoot框架中自动配置类的一个特性。同时,也反映出学习一门技术要从官网开始,避免踩坑。
在实际开发过程中,使用RedisTemplate< K, V>不是必须指定K、V的类型,使用默认的Bean就能满足需求。

最后想再验证一个小的问题,再次修改代码如下:

/**
 * Redis访问工具类
 * @author zhaoheng
 * @date   2018年8月10日
 */
@Component
public class RedisDao {

    /**
     * 注入时指定K、V类型都为String
     */
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 比较两个对象是否是同一个对象
     */
    public boolean compare () {
        LOG.info("redisTemplate的hashcode:{}", redisTemplate.hashCode());
        LOG.info("stringRedisTemplate的hashcode:{}", stringRedisTemplate.hashCode());
        LOG.info("equal()的结果:{}", redisTemplate.equals(stringRedisTemplate));
        return redisTemplate == stringRedisTemplate;
    }   
}

/**
 * 单元测试类
 * @author zhaoheng
 * @date   2018年8月10日
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo1ApplicationTests {

    private static final Logger LOG = LoggerFactory.getLogger(Demo1ApplicationTests.class);

    @Autowired
    private RedisDao redisDao;

    @Test
    public void contextLoads() {
        boolean flag = redisDao.compare();
        LOG.info("redisTemplate和stringRedisTemplate的比较结果:{}", flag);

    }
}

上边这段代码在注入RedisTemplate时指定K、V都为String类型,在compare()方法中比较redisTemplate和stringRedisTemplate是否是同一个对象。运行下单元测试类,测试结果如下:

2018-08-10 18:30:57.075 - Started Demo1ApplicationTests in 15.58 seconds (JVM running for 16.974)
2018-08-10 18:30:57.360 - redisTemplate的hashcode:1996087296
2018-08-10 18:30:57.360 - stringRedisTemplate的hashcode:1996087296
2018-08-10 18:30:57.363 - equal()的结果:true
2018-08-10 18:30:57.364 - redisTemplate和stringRedisTemplate的比较结果:true

测试结果表明redisTemplate和stringRedisTemplate是同一个对象。等等…这次注入RedisTemplate时指定K、V都为String为什么没有错呢?而且,两个对象竟然是同一个对象。还是来看下StringRedisTemplate的源码吧。

public class StringRedisTemplate extends RedisTemplate<String, String> {

    /**
     * Constructs a new <code>StringRedisTemplate</code> instance. {@link #setConnectionFactory(RedisConnectionFactory)}
     * and {@link #afterPropertiesSet()} still need to be called.
     */
    public StringRedisTemplate() {
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        setKeySerializer(stringSerializer);
        setValueSerializer(stringSerializer);
        setHashKeySerializer(stringSerializer);
        setHashValueSerializer(stringSerializer);
    }

    /**
     * Constructs a new <code>StringRedisTemplate</code> instance ready to be used.
     * 
     * @param connectionFactory connection factory for creating new connections
     */
    public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
        this();
        setConnectionFactory(connectionFactory);
        afterPropertiesSet();
    }

    protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
        return new DefaultStringRedisConnection(connection);
    }
}

看了源码是不是理解了,因为StringRedisTemplate类的父类就是RedisTemplate< String, String>,而Bean默认是单例的,两个是自然是同一个对象了。

至此,本篇文章书写完毕。由于笔主水平有限,笔误或者不当之处还请批评指正。

————————————————
版权声明:本文为CSDN博主「zhaoheng314」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhaoheng314/article/details/81564166

 

33. Springboot 系列 原生方式引入Redis,非RedisTemplate

33. Springboot 系列 原生方式引入Redis,非RedisTemplate

 0、pom.xml

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.56</version>
</dependency>

 

1.配置文件

#不用 springboot的redisTemplate,所以不用Springboot自身集成的redis配置
redis: 
  host: localhost
  port: 6379
  timeout: 3
  passpord: xiaochao
  poolMaxTotal: 10
  poolMaxIdle: 10
  poolMaxWait: 3
  passport: xiaochao

 

2.配置项映射类

package com.everjiankang.miaosha.redis;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import lombok.Data;

@Data
@Component
@ConfigurationProperties("redis")
public class RedisConfig {
    private String host;
    private String username;
    private String passport;
    private int port;
    private int timeout;
    private String   passpord;
    private int  poolMaxTotal;
    private int  poolMaxIdle;
    private int  poolMaxWait;
}

 

3.配置类

package com.everjiankang.miaosha.config;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.everjiankang.miaosha.redis.RedisConfig;

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Configuration
public class MyConfig {
    
    @Autowired
    RedisConfig redisConfig;
    
    @Bean
    public JedisPool jedisPoolFactory() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxIdle(redisConfig.getPoolMaxIdle());
        poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
        poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait() * 1000);
        return new JedisPool(poolConfig, redisConfig.getHost(), redisConfig.getPort(), redisConfig.getTimeout(), redisConfig.getPasspord());
    }
}

 

 4、前缀接口

package com.everjiankang.miaosha.redis;

/**
 * 前缀接口
 * @author guchunchao
 *
 */
public interface KeyPrefix {
    /**
     * 获取过期时间
     * @return
     */
    int expireSeconds();
    
    /**
     * 获取前缀
     * @return
     */
    String getPrefix();
}

 

5、前缀基础实现

package com.everjiankang.miaosha.redis;

public abstract class BaseKeyPrefix implements KeyPrefix{
    
    private int expireSeconds;
    
    private String prefix;

    public BaseKeyPrefix(int expireSeconds, String prefix) {
        super();
        this.expireSeconds = expireSeconds;
        this.prefix = prefix;
    }

    public BaseKeyPrefix(String prefix) {
        this.expireSeconds = 0;
        this.prefix = prefix;
    }

    @Override
    public int expireSeconds() {    //默认0代表永不过期
        return expireSeconds;
    }

    @Override
    public String getPrefix() {
        String className = getClass().getSimpleName();
        return className + ":" + prefix;
    }
}

 

6、前缀实现类

package com.everjiankang.miaosha.redis;

public class UserKey extends BaseKeyPrefix {

    private UserKey(int expireSeconds, String prefix) {
        super(expireSeconds, prefix);
    }
    
    private UserKey(String prefix) {
        super(prefix);
    }
    
    public static UserKey getById = new UserKey("id");
    public static UserKey getByName = new UserKey("name");
    
}

 

7、Jedis操作Redis类:

package com.everjiankang.miaosha.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

@Service
public class RedisService {
    
    @Autowired
    JedisPool jedisPool;

    /**
     * 获取单个对象
     * @param prefix
     * @param key
     * @param clazz
     * @return
     */
    public <T> T get(KeyPrefix prefix,String key, Class<T> clazz) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String realKey = prefix.getPrefix() + key;
            String value = jedis.get(realKey);
            T t = stringToBean(value,clazz);
            return t;
        } finally {
            returnToPool(jedis);
        }
    }
    
    /**
     * 设置对象
     * @param prefix
     * @param key
     * @param value
     * @return
     */
    public boolean set(KeyPrefix prefix, String key, Object value) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String str = beanToString(value);
            if(str == null || str.length() <=0)
                return false;
            int expireSecond = prefix.expireSeconds();
            String realKey = prefix.getPrefix() + key;
            if(expireSecond <= 0) {
                jedis.set(realKey,str);
            } else {
                jedis.setex(realKey, expireSecond, str);
            }
            return true;
        } finally {
            returnToPool(jedis);
        }
    }
    
    
    
    /**
     * 判断是否存在
     * @param prefix
     * @param key
     * @return
     */
    public boolean exist(KeyPrefix prefix, String key) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String realKey = prefix.getPrefix() + key;
            return jedis.exists(realKey);
        } finally {
            returnToPool(jedis);
        }
    }
    
    /**
     * 增加
     * @param prefix
     * @param key
     * @param clazz
     * @return
     */
    public <T> Long incri(KeyPrefix prefix,String key, Class<T> clazz) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String realKey = prefix.getPrefix() + key;
            Long incr = jedis.incr(realKey);
            return incr;
        } finally {
            returnToPool(jedis);
        }
    }
    
    /**
     * 减少
     * @param prefix
     * @param key
     * @param clazz
     * @return
     */
    public <T> Long decr(KeyPrefix prefix,String key, Class<T> clazz) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getResource();
            String realKey = prefix.getPrefix() + key;
            Long decr = jedis.decr(realKey);
            return decr;
        } finally {
            returnToPool(jedis);
        }
    }
    
    /**
     * Java对象转String
     * @param value
     * @return
     */
    private <T> String beanToString(T value) {
        if(value == null)
            return null;
        Class<?> clazz = value.getClass();
        
        if(clazz == int.class || clazz == Integer.class 
                || clazz == long.class || clazz == Long.class 
                || clazz == float.class || clazz == Float.class
                || clazz == double.class || clazz == Double.class
                )
            return "" + value;
        else if(value instanceof String)
            return (String) value;
        else
            return JSON.toJSONString(value);
        
    }
    
    /**
     * string 转Java
     * @param value
     * @param clazz
     * @return
     */
    @SuppressWarnings("unchecked")
    private <T> T stringToBean(String value,Class<T> clazz) {
        if(value == null)
            return null;
        if(clazz == int.class || clazz == Integer.class)
            return (T) Integer.valueOf(value);
        else if( clazz == long.class || clazz == Long.class)
            return (T) Long.valueOf(value);
        else if(clazz == float.class || clazz == Float.class)
            return (T) Float.valueOf(value);
        else if(clazz == double.class || clazz == Double.class)
            return (T) Double.valueOf(value);
        else if(value instanceof String) 
            return (T) value;
        else
            return JSON.toJavaObject(JSON.parseObject(value), clazz);
    }

    /**
     * 将Jedis链接还回连接池:详情close方法
     * @param jedis
     */
    private void returnToPool(Jedis jedis) {
        if(jedis != null)
            jedis.close();
    }
}

 

8、controller调用实例

package com.everjiankang.miaosha.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.everjiankang.miaosha.model.CodeMsg;
import com.everjiankang.miaosha.model.Result;
import com.everjiankang.miaosha.model.User;
import com.everjiankang.miaosha.redis.RedisService;
import com.everjiankang.miaosha.redis.UserKey;
import com.everjiankang.miaosha.service.UserService;


@Controller
@RequestMapping("/test")
public class TestController {
    
    @Autowired
    UserService userService;
    
    @Autowired
    RedisService redisService;

    @PostMapping("/test01")
    @ResponseBody
    public Result<String> test01() {
        return Result.success("hello world");
    }
    
    @PostMapping("/helloError")
    @ResponseBody
    public Result<String> helloError() {
        return Result.error(CodeMsg.SERVER_ERROR);
    }
    
    @RequestMapping("/thymeleaf")
    public String thymeleaf() {
        return "thymeleaf";
    }
    
    @RequestMapping("/getById/{id}")
    @ResponseBody
    public Result<User> getById(@PathVariable("id") int id) {
        return Result.success(userService.selectByPrimaryKey(id));
    }
    
    @RequestMapping("/redisGet/{key}")
    @ResponseBody
    public Result<String> redisGet(@PathVariable("key") String key) {
        String string = redisService.get(UserKey.getById,key, String.class);
        return Result.success(string);
    }
    
    @RequestMapping("/redisSet/{key}/{value}")
    @ResponseBody
    public Result<String> redisSet(@PathVariable("key") String key,@PathVariable("value") String value) {
        if(key != null && !"".equals(key.trim()) && value != null && !"".equals(value)) {
            boolean result = redisService.set(UserKey.getById,key, value);
            if(result)
                return Result.success(redisService.get(UserKey.getById,key, String.class));
            else
                return Result.error(CodeMsg.SERVER_ERROR);
        } else {
            return Result.error(CodeMsg.SERVER_ERROR);
        }
    }
    
    @RequestMapping("/redisSetUserTest")
    @ResponseBody
    public Result<User> redisSetUserTest(@PathVariable("key") String key) {
        User user = new User();
        user.setId(1);
        user.setAge(27);
        user.setName("xiaochao");
        user.setSex(1);
        boolean result = redisService.set(UserKey.getById,key, user);
        if(result)
            return Result.success(user);
        else
            return Result.error(CodeMsg.SERVER_ERROR);
    }
    
    @RequestMapping("/redisSetUserTest")
    @ResponseBody
    public Result<User> redisGetUserTest(@PathVariable("id") String id) {
        
        User user = redisService.get(UserKey.getById,id,User.class);
        if(user != null)
            return Result.success(user);
        else
            return Result.error(CodeMsg.SERVER_ERROR);
    }
    
}

 

Java 使用Jedis和RedisTemplate操作Redis缓存(SpringBoot)

Java 使用Jedis和RedisTemplate操作Redis缓存(SpringBoot)

package com.example.redis.controller;

import com.example.redis.entity.User;
import com.example.redis.util.JedisUtil;
import com.example.redis.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.json.JSONObject;
import org.json.JSONException;

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

@Controller
@RequestMapping(value = "/redis")
public class RedisController {
    @Autowired
    private RedisTemplate redisTemplate = null;

    @Autowired
    private StringRedisTemplate stringRedisTemplate = null;

    @Autowired
    private RedisUtil redisUtil = null;

    @Autowired
    private JedisUtil jedisUtil = null;

    @RequestMapping(value = "/test")
    @ResponseBody
    public Map<String, Object> test() throws JSONException {
        //System.out.printf("ip: %s port: %s password: %s ", redisHost, redisPort, redisPassword);

        //jedis操作
        //jedisUtil.set("lisi", "李四");
        //redis template操作redis
        //redisUtil.set("zhangsan", "张三");

        /**
         * Jedis是Redis官方推荐的面向Java的操作Redis的客户端,
         *
         * RedisTemplate是SpringDataRedis中对JedisApi的高度封装。
         * SpringDataRedis相对于Jedis来说可以方便地更换Redis的Java客户端,比Jedis多了自动管理连接池的特性,
         * 方便与其他Spring框架进行搭配使用如:SpringCache支持 jedis和lettuce
         **/


        Map<String, Object> map = new HashMap<String, Object>();
        try {
            Object zhangsan = redisUtil.get("zhangsan");
            //System.out.println("zhangsan" + zhangsan);

            /* 使用双重验证锁解决高并发环境下的缓存穿透问题 */
            if (StringUtils.isEmpty(zhangsan)) { // 第一重验证
                synchronized (this) {
                    zhangsan = redisUtil.get("zhangsan");
                    if (StringUtils.isEmpty(zhangsan)) { // 第二重验证
                        System.out.println("查询数据库............");
                        // 缓存为空,则查询数据库将相关数据存储到redis中
                        redisUtil.set("zhangsan", "张三",10); //10秒后过期
                    } else {
                        System.out.println("2 查询缓存............");
                    }
                }
            } else {
                System.out.println("1 查询缓存............");
            }

            map.put("success", true);

            ////entity实体类
            //User user = new User();
            //user.setUserId(1000);
            //user.setUserName("张三");
            //user.setAddress("深圳市南山区");
            //user.setMobile("13988886666");
            //redisUtil.set("userInfo", user.toString(), 10);  //10秒后过期自动删除
            ////获取显示
            //String str = String.valueOf(redisUtil.get("userInfo"));
            //JSONObject jsonObj = new JSONObject(str);
            //map.put("userInfo", jsonObj.get("userId"));
        } catch (Exception e) {
            map.put("success", false);
            e.printStackTrace();
        } finally {
        }
        return map;
    }

    /**
     * 操作redis字符串和hash散列
     *
     * @return
     * @Date 2018年11月1日 下午1:56:30
     * @Author lay
     */
    @RequestMapping(value = "/stringAndHash")
    @ResponseBody
    public Map<String, Object> testStringAndHash() {
        //set字符串
        redisTemplate.opsForValue().set("key1", "value1");
        System.out.println("-------------set字符串-------------------: " + redisTemplate.opsForValue().get("key1"));

        //定义一个hashmap散列
        Map<String, String> hash = new HashMap<String, String>();
        hash.put("field1", "value1");
        hash.put("field2", "value2");
        //存入一个散列数据类型
        stringRedisTemplate.opsForHash().putAll("hash", hash);
        System.out.println("-------------存入一个散列数据类型-------------------: ");


        System.out.println("-------------map 遍历-------------------: ");
        redisTemplate.opsForHash().entries("hash").forEach((k, v) -> {
            System.out.println(k + ": " + v);
        });
        System.out.println("-------------map->set 遍历-------------------: ");
        redisTemplate.opsForHash().keys("hash").forEach(key -> {
            System.out.println(key + ": " + redisTemplate.opsForHash().get("hash", key));
        });


        Map<String, Object> map = new HashMap<String, Object>();
        map.put("success", true);
        return map;
    }
}
package com.example.redis.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.BinaryClient;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

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

/**
 * JedisUtil工具类
 */
@Component
public class JedisUtil {
    private JedisPool pool = null;

    @Autowired
    private PropertiesUtils propertiesUtils = null;

    private JedisUtil() {
        System.out.println("JedisUtil.JedisUtil");

        if (pool == null) {
            propertiesUtils = new PropertiesUtils();
            String ip = String.valueOf(propertiesUtils.getYml("spring.redis.host"));
            int port = Integer.valueOf(propertiesUtils.getYml("spring.redis.port").toString());
            String password = String.valueOf(propertiesUtils.getYml("spring.redis.password"));
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            System.out.printf("----------------ip: %s port: %s password: %s ----------------", ip, port, password);
            //jedisPoolConfig.setMaxTotal(SysConfigUtil.getSysConfigUtil("redis.properties").getInt("redis.maxTotal"));
            //jedisPoolConfig.setMaxIdle(SysConfigUtil.getSysConfigUtil("redis.properties").getInt("redis.maxIdle"));
            //jedisPoolConfig.setMaxWaitMillis(SysConfigUtil.getSysConfigUtil("redis.properties").getLong("redis.maxWaitMillis"));
            //jedisPoolConfig.setTestOnBorrow(SysConfigUtil.getSysConfigUtil("redis.properties").getBoolean("redis.testOnBorrow"));
            if (password != null && !"".equals(password)) {
                // redis 设置了密码
                pool = new JedisPool(jedisPoolConfig, ip, port, 10000, password);
            } else {
                // redis 未设置密码
                pool = new JedisPool(jedisPoolConfig, ip, port, 10000);
            }
        }
    }

    /**
     * 获取指定key的值,如果key不存在返回null,如果该Key存储的不是字符串,会抛出一个错误
     *
     * @param key
     * @return
     */
    public String get(String key) {
        Jedis jedis = getJedis();
        String value = null;
        value = jedis.get(key);
        return value;
    }

    /**
     * 设置key的值为value
     *
     * @param key
     * @param value
     * @return
     */
    public String set(String key, String value) {
        Jedis jedis = getJedis();
        return jedis.set(key, value);
    }

    /**
     * 删除指定的key,也可以传入一个包含key的数组
     *
     * @param keys
     * @return
     */
    public Long del(String... keys) {
        Jedis jedis = getJedis();
        return jedis.del(keys);
    }

    /**
     * 通过key向指定的value值追加值
     *
     * @param key
     * @param str
     * @return
     */
    public Long append(String key, String str) {
        Jedis jedis = getJedis();
        return jedis.append(key, str);
    }

    /**
     * 判断key是否存在
     *
     * @param key
     * @return
     */
    public Boolean exists(String key) {
        Jedis jedis = getJedis();
        return jedis.exists(key);
    }

    /**
     * 设置key value,如果key已经存在则返回0
     *
     * @param key
     * @param value
     * @return
     */
    public Long setnx(String key, String value) {
        Jedis jedis = getJedis();
        return jedis.setnx(key, value);
    }

    /**
     * 设置key value并指定这个键值的有效期
     *
     * @param key
     * @param seconds
     * @param value
     * @return
     */
    public String setex(String key, int seconds, String value) {
        Jedis jedis = getJedis();
        return jedis.setex(key, seconds, value);
    }

    /**
     * 通过key 和offset 从指定的位置开始将原先value替换
     *
     * @param key
     * @param offset
     * @param str
     * @return
     */
    public Long setrange(String key, int offset, String str) {
        Jedis jedis = getJedis();
        return jedis.setrange(key, offset, str);
    }

    /**
     * 通过批量的key获取批量的value
     *
     * @param keys
     * @return
     */
    public List<String> mget(String... keys) {
        Jedis jedis = getJedis();
        return jedis.mget(keys);
    }

    /**
     * 批量的设置key:value,也可以一个
     *
     * @param keysValues
     * @return
     */
    public String mset(String... keysValues) {
        Jedis jedis = getJedis();
        return jedis.mset(keysValues);
    }

    /**
     * 批量的设置key:value,可以一个,如果key已经存在则会失败,操作会回滚
     *
     * @param keysValues
     * @return
     */
    public Long msetnx(String... keysValues) {
        Jedis jedis = getJedis();
        return jedis.msetnx(keysValues);
    }

    /**
     * 设置key的值,并返回一个旧值
     *
     * @param key
     * @param value
     * @return
     */
    public String getSet(String key, String value) {
        Jedis jedis = getJedis();
        return jedis.getSet(key, value);
    }

    /**
     * 通过下标 和key 获取指定下标位置的 value
     *
     * @param key
     * @param startOffset
     * @param endOffset
     * @return
     */
    public String getrange(String key, int startOffset, int endOffset) {
        Jedis jedis = getJedis();
        return jedis.getrange(key, startOffset, endOffset);
    }

    /**
     * 通过key 对value进行加值+1操作,当value不是int类型时会返回错误,当key不存在是则value为1
     *
     * @param key
     * @return
     */
    public Long incr(String key) {
        Jedis jedis = getJedis();
        return jedis.incr(key);
    }

    /**
     * 通过key给指定的value加值,如果key不存在,则这是value为该值
     *
     * @param key
     * @param integer
     * @return
     */
    public Long incrBy(String key, long integer) {
        Jedis jedis = getJedis();
        return jedis.incrBy(key, integer);
    }

    /**
     * 对key的值做减减操作,如果key不存在,则设置key为-1
     *
     * @param key
     * @return
     */
    public Long decr(String key) {
        Jedis jedis = getJedis();
        return jedis.decr(key);
    }

    /**
     * 减去指定的值
     *
     * @param key
     * @param integer
     * @return
     */
    public Long decrBy(String key, long integer) {
        Jedis jedis = getJedis();
        return jedis.decrBy(key, integer);
    }

    /**
     * 通过key获取value值的长度
     *
     * @param key
     * @return
     */
    public Long strLen(String key) {
        Jedis jedis = getJedis();
        return jedis.strlen(key);
    }

    /**
     * 通过key给field设置指定的值,如果key不存在则先创建,如果field已经存在,返回0
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long hsetnx(String key, String field, String value) {
        Jedis jedis = getJedis();
        return jedis.hsetnx(key, field, value);
    }

    /**
     * 通过key给field设置指定的值,如果key不存在,则先创建
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long hset(String key, String field, String value) {
        Jedis jedis = getJedis();
        return jedis.hset(key, field, value);
    }

    /**
     * 通过key同时设置 hash的多个field
     *
     * @param key
     * @param hash
     * @return
     */
    public String hmset(String key, Map<String, String> hash) {
        Jedis jedis = getJedis();
        return jedis.hmset(key, hash);
    }

    /**
     * 通过key 和 field 获取指定的 value
     *
     * @param key
     * @param failed
     * @return
     */
    public String hget(String key, String failed) {
        Jedis jedis = getJedis();
        return jedis.hget(key, failed);
    }

    /**
     * 设置key的超时时间为seconds
     *
     * @param key
     * @param seconds
     * @return
     */
    public Long expire(String key, int seconds) {
        Jedis jedis = getJedis();
        return jedis.expire(key, seconds);
    }

    /**
     * 通过key 和 fields 获取指定的value 如果没有对应的value则返回null
     *
     * @param key
     * @param fields 可以是 一个String 也可以是 String数组
     * @return
     */
    public List<String> hmget(String key, String... fields) {
        Jedis jedis = getJedis();
        return jedis.hmget(key, fields);
    }

    /**
     * 通过key给指定的field的value加上给定的值
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long hincrby(String key, String field, Long value) {
        Jedis jedis = getJedis();
        return jedis.hincrBy(key, field, value);
    }

    /**
     * 通过key和field判断是否有指定的value存在
     *
     * @param key
     * @param field
     * @return
     */
    public Boolean hexists(String key, String field) {
        Jedis jedis = getJedis();
        return jedis.hexists(key, field);
    }

    /**
     * 通过key返回field的数量
     *
     * @param key
     * @return
     */
    public Long hlen(String key) {
        Jedis jedis = getJedis();
        return jedis.hlen(key);
    }

    /**
     * 通过key 删除指定的 field
     *
     * @param key
     * @param fields 可以是 一个 field 也可以是 一个数组
     * @return
     */
    public Long hdel(String key, String... fields) {
        Jedis jedis = getJedis();
        return jedis.hdel(key, fields);
    }

    /**
     * 通过key返回所有的field
     *
     * @param key
     * @return
     */
    public Set<String> hkeys(String key) {
        Jedis jedis = getJedis();
        return jedis.hkeys(key);
    }

    /**
     * 通过key返回所有和key有关的value
     *
     * @param key
     * @return
     */
    public List<String> hvals(String key) {
        Jedis jedis = getJedis();
        return jedis.hvals(key);
    }

    /**
     * 通过key获取所有的field和value
     *
     * @param key
     * @return
     */
    public Map<String, String> hgetall(String key) {
        Jedis jedis = getJedis();
        return jedis.hgetAll(key);
    }

    /**
     * 通过key向list头部添加字符串
     *
     * @param key
     * @param strs 可以是一个string 也可以是string数组
     * @return 返回list的value个数
     */
    public Long lpush(String key, String... strs) {
        Jedis jedis = getJedis();
        return jedis.lpush(key, strs);
    }

    /**
     * 通过key向list尾部添加字符串
     *
     * @param key
     * @param strs 可以是一个string 也可以是string数组
     * @return 返回list的value个数
     */
    public Long rpush(String key, String... strs) {
        Jedis jedis = getJedis();
        return jedis.rpush(key, strs);
    }

    /**
     * 通过key在list指定的位置之前或者之后 添加字符串元素
     *
     * @param key
     * @param where LIST_POSITION枚举类型
     * @param pivot list里面的value
     * @param value 添加的value
     * @return
     */
    public Long linsert(String key, BinaryClient.LIST_POSITION where,
                        String pivot, String value) {
        Jedis jedis = getJedis();
        return jedis.linsert(key, where, pivot, value);
    }

    /**
     * 通过key设置list指定下标位置的value
     * 如果下标超过list里面value的个数则报错
     *
     * @param key
     * @param index 从0开始
     * @param value
     * @return 成功返回OK
     */
    public String lset(String key, Long index, String value) {
        Jedis jedis = getJedis();
        return jedis.lset(key, index, value);
    }

    /**
     * 通过key从对应的list中删除指定的count个 和 value相同的元素
     *
     * @param key
     * @param count 当count为0时删除全部
     * @param value
     * @return 返回被删除的个数
     */
    public Long lrem(String key, long count, String value) {
        Jedis jedis = getJedis();
        return jedis.lrem(key, count, value);
    }

    /**
     * 通过key保留list中从strat下标开始到end下标结束的value值
     *
     * @param key
     * @param start
     * @param end
     * @return 成功返回OK
     */
    public String ltrim(String key, long start, long end) {
        Jedis jedis = getJedis();
        return jedis.ltrim(key, start, end);
    }

    /**
     * 通过key从list的头部删除一个value,并返回该value
     *
     * @param key
     * @return
     */
    public synchronized String lpop(String key) {

        Jedis jedis = getJedis();
        return jedis.lpop(key);
    }

    /**
     * 通过key从list尾部删除一个value,并返回该元素
     *
     * @param key
     * @return
     */
    synchronized public String rpop(String key) {
        Jedis jedis = getJedis();
        return jedis.rpop(key);
    }

    /**
     * 通过key从一个list的尾部删除一个value并添加到另一个list的头部,并返回该value
     * 如果第一个list为空或者不存在则返回null
     *
     * @param srckey
     * @param dstkey
     * @return
     */
    public String rpoplpush(String srckey, String dstkey) {
        Jedis jedis = getJedis();
        return jedis.rpoplpush(srckey, dstkey);
    }

    /**
     * 通过key获取list中指定下标位置的value
     *
     * @param key
     * @param index
     * @return 如果没有返回null
     */
    public String lindex(String key, long index) {
        Jedis jedis = getJedis();
        return jedis.lindex(key, index);
    }

    /**
     * 通过key返回list的长度
     *
     * @param key
     * @return
     */
    public Long llen(String key) {
        Jedis jedis = getJedis();
        return jedis.llen(key);
    }

    /**
     * 通过key获取list指定下标位置的value
     * 如果start 为 0 end 为 -1 则返回全部的list中的value
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<String> lrange(String key, long start, long end) {
        Jedis jedis = getJedis();
        return jedis.lrange(key, start, end);
    }

    /**
     * 通过key向指定的set中添加value
     *
     * @param key
     * @param members 可以是一个String 也可以是一个String数组
     * @return 添加成功的个数
     */
    public Long sadd(String key, String... members) {
        Jedis jedis = getJedis();
        return jedis.sadd(key, members);
    }

    /**
     * 通过key删除set中对应的value值
     *
     * @param key
     * @param members 可以是一个String 也可以是一个String数组
     * @return 删除的个数
     */
    public Long srem(String key, String... members) {
        Jedis jedis = getJedis();
        return jedis.srem(key, members);
    }

    /**
     * 通过key随机删除一个set中的value并返回该值
     *
     * @param key
     * @return
     */
    public String spop(String key) {
        Jedis jedis = getJedis();
        return jedis.spop(key);
    }

    /**
     * 通过key获取set中的差集
     * 以第一个set为标准
     *
     * @param keys 可以 是一个string 则返回set中所有的value 也可以是string数组
     * @return
     */
    public Set<String> sdiff(String... keys) {
        Jedis jedis = getJedis();
        return jedis.sdiff(keys);
    }

    /**
     * 通过key获取set中的差集并存入到另一个key中
     * 以第一个set为标准
     *
     * @param dstkey 差集存入的key
     * @param keys   可以 是一个string 则返回set中所有的value 也可以是string数组
     * @return
     */
    public Long sdiffstore(String dstkey, String... keys) {
        Jedis jedis = getJedis();
        return jedis.sdiffstore(dstkey, keys);
    }

    /**
     * 通过key获取指定set中的交集
     *
     * @param keys 可以 是一个string 也可以是一个string数组
     * @return
     */
    public Set<String> sinter(String... keys) {
        Jedis jedis = getJedis();
        return jedis.sinter(keys);
    }

    /**
     * 通过key获取指定set中的交集 并将结果存入新的set中
     *
     * @param dstkey
     * @param keys   可以 是一个string 也可以是一个string数组
     * @return
     */
    public Long sinterstore(String dstkey, String... keys) {
        Jedis jedis = getJedis();
        return jedis.sinterstore(dstkey, keys);
    }

    /**
     * 通过key返回所有set的并集
     *
     * @param keys 可以 是一个string 也可以是一个string数组
     * @return
     */
    public Set<String> sunion(String... keys) {
        Jedis jedis = getJedis();
        return jedis.sunion(keys);
    }

    /**
     * 通过key返回所有set的并集,并存入到新的set中
     *
     * @param dstkey
     * @param keys   可以 是一个string 也可以是一个string数组
     * @return
     */
    public Long sunionstore(String dstkey, String... keys) {
        Jedis jedis = getJedis();
        return jedis.sunionstore(dstkey, keys);
    }

    /**
     * 通过key将set中的value移除并添加到第二个set中
     *
     * @param srckey 需要移除的
     * @param dstkey 添加的
     * @param member set中的value
     * @return
     */
    public Long smove(String srckey, String dstkey, String member) {
        Jedis jedis = getJedis();
        return jedis.smove(srckey, dstkey, member);
    }

    /**
     * 通过key获取set中value的个数
     *
     * @param key
     * @return
     */
    public Long scard(String key) {
        Jedis jedis = getJedis();
        return jedis.scard(key);
    }

    /**
     * 通过key判断value是否是set中的元素
     *
     * @param key
     * @param member
     * @return
     */
    public Boolean sismember(String key, String member) {
        Jedis jedis = getJedis();
        return jedis.sismember(key, member);
    }

    /**
     * 通过key获取set中随机的value,不删除元素
     *
     * @param key
     * @return
     */
    public String srandmember(String key) {
        Jedis jedis = getJedis();
        return jedis.srandmember(key);
    }

    /**
     * 通过key获取set中所有的value
     *
     * @param key
     * @return
     */
    public Set<String> smembers(String key) {
        Jedis jedis = getJedis();
        return jedis.smembers(key);
    }


    /**
     * 通过key向zset中添加value,score,其中score就是用来排序的
     * 如果该value已经存在则根据score更新元素
     *
     * @param key
     * @param score
     * @param member
     * @return
     */
    public Long zadd(String key, double score, String member) {
        Jedis jedis = getJedis();
        return jedis.zadd(key, score, member);
    }

    /**
     * 通过key删除在zset中指定的value
     *
     * @param key
     * @param members 可以 是一个string 也可以是一个string数组
     * @return
     */
    public Long zrem(String key, String... members) {
        Jedis jedis = getJedis();
        return jedis.zrem(key, members);
    }

    /**
     * 通过key增加该zset中value的score的值
     *
     * @param key
     * @param score
     * @param member
     * @return
     */
    public Double zincrby(String key, double score, String member) {
        Jedis jedis = getJedis();
        return jedis.zincrby(key, score, member);
    }

    /**
     * 通过key返回zset中value的排名
     * 下标从小到大排序
     *
     * @param key
     * @param member
     * @return
     */
    public Long zrank(String key, String member) {
        Jedis jedis = getJedis();
        return jedis.zrank(key, member);
    }

    /**
     * 通过key返回zset中value的排名
     * 下标从大到小排序
     *
     * @param key
     * @param member
     * @return
     */
    public Long zrevrank(String key, String member) {
        Jedis jedis = getJedis();
        return jedis.zrevrank(key, member);
    }

    /**
     * 通过key将获取score从start到end中zset的value
     * socre从大到小排序
     * 当start为0 end为-1时返回全部
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Set<String> zrevrange(String key, long start, long end) {
        Jedis jedis = getJedis();
        return jedis.zrevrange(key, start, end);
    }

    /**
     * 通过key返回指定score内zset中的value
     *
     * @param key
     * @param max
     * @param min
     * @return
     */
    public Set<String> zrangebyscore(String key, String max, String min) {
        Jedis jedis = getJedis();
        return jedis.zrevrangeByScore(key, max, min);
    }

    /**
     * 通过key返回指定score内zset中的value
     *
     * @param key
     * @param max
     * @param min
     * @return
     */
    public Set<String> zrangeByScore(String key, double max, double min) {
        Jedis jedis = getJedis();
        return jedis.zrevrangeByScore(key, max, min);
    }

    /**
     * 返回指定区间内zset中value的数量
     *
     * @param key
     * @param min
     * @param max
     * @return
     */
    public Long zcount(String key, String min, String max) {
        Jedis jedis = getJedis();
        return jedis.zcount(key, min, max);
    }

    /**
     * 通过key返回zset中的value个数
     *
     * @param key
     * @return
     */
    public Long zcard(String key) {
        Jedis jedis = getJedis();
        return jedis.zcard(key);
    }

    /**
     * 通过key获取zset中value的score值
     *
     * @param key
     * @param member
     * @return
     */
    public Double zscore(String key, String member) {
        Jedis jedis = getJedis();
        return jedis.zscore(key, member);
    }

    /**
     * 通过key删除给定区间内的元素
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Long zremrangeByRank(String key, long start, long end) {
        Jedis jedis = getJedis();
        return jedis.zremrangeByRank(key, start, end);
    }

    /**
     * 通过key删除指定score内的元素
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public Long zremrangeByScore(String key, double start, double end) {
        Jedis jedis = getJedis();
        return jedis.zremrangeByScore(key, start, end);
    }

    /**
     * 返回满足pattern表达式的所有key
     * keys(*)
     * 返回所有的key
     *
     * @param pattern
     * @return
     */
    public Set<String> keys(String pattern) {
        Jedis jedis = getJedis();
        return jedis.keys(pattern);
    }

    /**
     * 通过key判断值得类型
     *
     * @param key
     * @return
     */
    public String type(String key) {
        Jedis jedis = getJedis();
        return jedis.type(key);
    }


    private void close(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }

    private Jedis getJedis() {
        return pool.getResource();
    }

    public static RedisUtil getRedisUtil() {
        return new RedisUtil();
    }

}
package com.example.redis.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

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

/**
 * RedisTemplate 工具类
 */
@Component
public class RedisUtil {
    @Autowired
    private RedisTemplate redisTemplate;


    //- - - - - - - - - - - - - - - - - - - - -  公共方法 - - - - - - - - - - - - - - - - - - - -

    /**
     * 给一个指定的 key 值附加过期时间
     *
     * @param key
     * @param time
     * @return
     */
    public boolean expire(String key, long time) {
        return redisTemplate.expire(key, time, TimeUnit.SECONDS);
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key
     * @return
     */
    public long getTime(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 根据key 获取过期时间
     *
     * @param key
     * @return
     */
    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 移除指定key 的过期时间
     *
     * @param key
     * @return
     */
    public boolean persist(String key) {
        return redisTemplate.boundValueOps(key).persist();
    }

    //- - - - - - - - - - - - - - - - - - - - -  String类型 - - - - - - - - - - - - - - - - - - - -

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

    /**
     * 将值放入缓存
     *
     * @param key   键
     * @param value 值
     * @return true成功 false 失败
     */
    public void set(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 将值放入缓存并设置时间
     *
     * @param key   键
     * @param value 值
     * @param time  时间(秒) -1为无期限
     * @return true成功 false 失败
     */
    public void set(String key, String value, long time) {
        if (time > 0) {
            redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
        } else {
            redisTemplate.opsForValue().set(key, value);
        }
    }

    /**
     * 批量添加 key (重复的键会覆盖)
     *
     * @param keyAndValue
     */
    public void batchSet(Map<String, String> keyAndValue) {
        redisTemplate.opsForValue().multiSet(keyAndValue);
    }

    /**
     * 批量添加 key-value 只有在键不存在时,才添加
     * map 中只要有一个key存在,则全部不添加
     *
     * @param keyAndValue
     */
    public void batchSetIfAbsent(Map<String, String> keyAndValue) {
        redisTemplate.opsForValue().multiSetIfAbsent(keyAndValue);
    }

    /**
     * 对一个 key-value 的值进行加减操作,
     * 如果该 key 不存在 将创建一个key 并赋值该 number
     * 如果 key 存在,但 value 不是长整型 ,将报错
     *
     * @param key
     * @param number
     */
    public Long increment(String key, long number) {
        return redisTemplate.opsForValue().increment(key, number);
    }

    /**
     * 对一个 key-value 的值进行加减操作,
     * 如果该 key 不存在 将创建一个key 并赋值该 number
     * 如果 key 存在,但 value 不是 纯数字 ,将报错
     *
     * @param key
     * @param number
     */
    public Double increment(String key, double number) {
        return redisTemplate.opsForValue().increment(key, number);
    }

    //- - - - - - - - - - - - - - - - - - - - -  set类型 - - - - - - - - - - - - - - - - - - - -

    /**
     * 将数据放入set缓存
     *
     * @param key 键
     * @return
     */
    public void sSet(String key, String value) {
        redisTemplate.opsForSet().add(key, value);
    }

    /**
     * 获取变量中的值
     *
     * @param key 键
     * @return
     */
    public Set<Object> members(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 随机获取变量中指定个数的元素
     *
     * @param key   键
     * @param count 值
     * @return
     */
    public void randomMembers(String key, long count) {
        redisTemplate.opsForSet().randomMembers(key, count);
    }

    /**
     * 随机获取变量中的元素
     *
     * @param key 键
     * @return
     */
    public Object randomMember(String key) {
        return redisTemplate.opsForSet().randomMember(key);
    }

    /**
     * 弹出变量中的元素
     *
     * @param key 键
     * @return
     */
    public Object pop(String key) {
        return redisTemplate.opsForSet().pop("setValue");
    }

    /**
     * 获取变量中值的长度
     *
     * @param key 键
     * @return
     */
    public long size(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 根据value从一个set中查询,是否存在
     *
     * @param key   键
     * @param value 值
     * @return true 存在 false不存在
     */
    public boolean sHasKey(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     * 检查给定的元素是否在变量中。
     *
     * @param key 键
     * @param obj 元素对象
     * @return
     */
    public boolean isMember(String key, Object obj) {
        return redisTemplate.opsForSet().isMember(key, obj);
    }

    /**
     * 转移变量的元素值到目的变量。
     *
     * @param key     键
     * @param value   元素对象
     * @param destKey 元素对象
     * @return
     */
    public boolean move(String key, String value, String destKey) {
        return redisTemplate.opsForSet().move(key, value, destKey);
    }

    /**
     * 批量移除set缓存中元素
     *
     * @param key    键
     * @param values 值
     * @return
     */
    public void remove(String key, Object... values) {
        redisTemplate.opsForSet().remove(key, values);
    }

    /**
     * 通过给定的key求2个set变量的差值
     *
     * @param key     键
     * @param destKey 键
     * @return
     */
    public Set<Set> difference(String key, String destKey) {
        return redisTemplate.opsForSet().difference(key, destKey);
    }


    //- - - - - - - - - - - - - - - - - - - - -  hash类型 - - - - - - - - - - - - - - - - - - - -

    /**
     * 加入缓存
     *
     * @param key 键
     * @param map 键
     * @return
     */
    public void add(String key, Map<String, String> map) {
        redisTemplate.opsForHash().putAll(key, map);
    }

    /**
     * 获取 key 下的 所有  hashkey 和 value
     *
     * @param key 键
     * @return
     */
    public Map<Object, Object> getHashEntries(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 验证指定 key 下 有没有指定的 hashkey
     *
     * @param key
     * @param hashKey
     * @return
     */
    public boolean hashKey(String key, String hashKey) {
        return redisTemplate.opsForHash().hasKey(key, hashKey);
    }

    /**
     * 获取指定key的值string
     *
     * @param key  键
     * @param key2 键
     * @return
     */
    public String getMapString(String key, String key2) {
        return redisTemplate.opsForHash().get("map1", "key1").toString();
    }

    /**
     * 获取指定的值Int
     *
     * @param key  键
     * @param key2 键
     * @return
     */
    public Integer getMapInt(String key, String key2) {
        return (Integer) redisTemplate.opsForHash().get("map1", "key1");
    }

    /**
     * 弹出元素并删除
     *
     * @param key 键
     * @return
     */
    public String popValue(String key) {
        return redisTemplate.opsForSet().pop(key).toString();
    }

    /**
     * 删除指定 hash 的 HashKey
     *
     * @param key
     * @param hashKeys
     * @return 删除成功的 数量
     */
    public Long delete(String key, String... hashKeys) {
        return redisTemplate.opsForHash().delete(key, hashKeys);
    }

    /**
     * 给指定 hash 的 hashkey 做增减操作
     *
     * @param key
     * @param hashKey
     * @param number
     * @return
     */
    public Long increment(String key, String hashKey, long number) {
        return redisTemplate.opsForHash().increment(key, hashKey, number);
    }

    /**
     * 给指定 hash 的 hashkey 做增减操作
     *
     * @param key
     * @param hashKey
     * @param number
     * @return
     */
    public Double increment(String key, String hashKey, Double number) {
        return redisTemplate.opsForHash().increment(key, hashKey, number);
    }

    /**
     * 获取 key 下的 所有 hashkey 字段
     *
     * @param key
     * @return
     */
    public Set<Object> hashKeys(String key) {
        return redisTemplate.opsForHash().keys(key);
    }

    /**
     * 获取指定 hash 下面的 键值对 数量
     *
     * @param key
     * @return
     */
    public Long hashSize(String key) {
        return redisTemplate.opsForHash().size(key);
    }

    //- - - - - - - - - - - - - - - - - - - - -  list类型 - - - - - - - - - - - - - - - - - - - -

    /**
     * 在变量左边添加元素值
     *
     * @param key
     * @param value
     * @return
     */
    public void leftPush(String key, Object value) {
        redisTemplate.opsForList().leftPush(key, value);
    }

    /**
     * 获取集合指定位置的值。
     *
     * @param key
     * @param index
     * @return
     */
    public Object index(String key, long index) {
        return redisTemplate.opsForList().index("list", 1);
    }

    /**
     * 获取指定区间的值。
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<Object> range(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 把最后一个参数值放到指定集合的第一个出现中间参数的前面,
     * 如果中间参数值存在的话。
     *
     * @param key
     * @param pivot
     * @param value
     * @return
     */
    public void leftPush(String key, String pivot, String value) {
        redisTemplate.opsForList().leftPush(key, pivot, value);
    }

    /**
     * 向左边批量添加参数元素。
     *
     * @param key
     * @param values
     * @return
     */
    public void leftPushAll(String key, String... values) {
//        redisTemplate.opsForList().leftPushAll(key,"w","x","y");
        redisTemplate.opsForList().leftPushAll(key, values);
    }

    /**
     * 向集合最右边添加元素。
     *
     * @param key
     * @param value
     * @return
     */
    public void leftPushAll(String key, String value) {
        redisTemplate.opsForList().rightPush(key, value);
    }

    /**
     * 向左边批量添加参数元素。
     *
     * @param key
     * @param values
     * @return
     */
    public void rightPushAll(String key, String... values) {
      //redisTemplate.opsForList().leftPushAll(key,"w","x","y");
        redisTemplate.opsForList().rightPushAll(key, values);
    }

    /**
     * 向已存在的集合中添加元素。
     *
     * @param key
     * @param value
     * @return
     */
    public void rightPushIfPresent(String key, Object value) {
        redisTemplate.opsForList().rightPushIfPresent(key, value);
    }

    /**
     * 向已存在的集合中添加元素。
     *
     * @param key
     * @return
     */
    public long listLength(String key) {
        return redisTemplate.opsForList().size(key);
    }

    /**
     * 移除集合中的左边第一个元素。
     *
     * @param key
     * @return
     */
    public void leftPop(String key) {
        redisTemplate.opsForList().leftPop(key);
    }

    /**
     * 移除集合中左边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
     *
     * @param key
     * @return
     */
    public void leftPop(String key, long timeout, TimeUnit unit) {
        redisTemplate.opsForList().leftPop(key, timeout, unit);
    }

    /**
     * 移除集合中右边的元素。
     *
     * @param key
     * @return
     */
    public void rightPop(String key) {
        redisTemplate.opsForList().rightPop(key);
    }

    /**
     * 移除集合中右边的元素在等待的时间里,如果超过等待的时间仍没有元素则退出。
     *
     * @param key
     * @return
     */
    public void rightPop(String key, long timeout, TimeUnit unit) {
        redisTemplate.opsForList().rightPop(key, timeout, unit);
    }
}

  

Redis 系列-- SpringBoot 中 redisTemplate 的操作

Redis 系列-- SpringBoot 中 redisTemplate 的操作

SpringBoot中 集成 redisTemplate 对 Redis 的操作(一)

在Java 操作redis 时,有很多工具,redis 官网中,就有很多操作,

目前主流开发框架SpringBoot 中,当然也有集成好的操作redis的工具--redisTemplate,下面就来说一说它的基本操作。

依赖包
 <dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
redisTemplate 序列化规则

Spring Data JPA 提供的序列化 Serializer:

1、GenericToStringSerializer

2、Jackson2JsonRedisSerializer

3、JacksonJsonRedisSerializer

4、JdkSerializationRedisSerializer

5、OxmSerializer

6、StringRedisSerializer

我们通过操作

User user = new User(1, "su", new Date());
redisTemplate.opsForValue().set("name","su");
redisTemplate.opsForValue().set("user",user);

查看 redis 可以发现

redisTemplate 默认的是 JdkSerializationRedisSerializer 序列化方法。

如果说 我们想以json 的方法进行 序列化 可以自定义redisTemplate

@Configuration
public class RedisTemplateConfig {

	[@Bean](https://my.oschina.net/bean)
	public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(redisConnectionFactory);
		//定义key 序列化 方式
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		//定义value 序列化 方式
		redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
		return redisTemplate;
	}
}

操作 可以发现

String 类型的操作

1⃣️ 添加数据

 User user = new User(1, "su", new Date());
 redisTemplate.opsForValue().set("name","su");
 redisTemplate.opsForValue().set("user",user);

2⃣️ 添加数据,并设置过期时间

redisTemplate.opsForValue().set("age",18,10000, TimeUnit.MILLISECONDS);

3⃣️ 批量添加数据

HashMap<Object, Object> map = new HashMap<>();
map.put("name", "susu");
map.put("age", 18);
map.put("address", "shanghai");
redisTemplate.opsForValue().multiSet(map);

4⃣️ 原子操作数据

    Long num = (Long) redisTemplate.opsForValue().getAndSet("num", 1);

5⃣️ 追加数据

    Integer num = redisTemplate.opsForValue().append("name", "susu");

6⃣️ 根据key 获取数据

    User user = (User) redisTemplate.opsForValue().get("user");

7⃣️ 批量获取数据

    List<Object> list = new ArrayList<>();
    list.add("name");
    list.add("address");
    list.add("user");
    List listResult = redisTemplate.opsForValue().multiGet(list);

8⃣️ 自增运算 并设置自增步长 (默认是1)

    Long num = redisTemplate.opsForValue().increment("num", 2);

9⃣️ 自减运算,并设置步长 (默认是1)

    redisTemplate.opsForValue().decrement("num");

Redis整合SpringBoot的RedisTemplate实现类(实例详解)

Redis整合SpringBoot的RedisTemplate实现类(实例详解)

Redis整合SpringBoot》》RedisService 接口

package com.tuan.common.base.redis;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public interface RedisService {

 //Redis 字符串(String)

 /**
  * 模糊值再删除
  * @param key
  * @return
  */
 boolean delslike(String key);

 /**
  * 通过键来获取值
  * @param key
  * @return String
  */
 String get(String key);

 /**
  * 获取值装成Int类型
  * @param key
  * @return
  */
 Integer getInt(String key);

 /**
  * 删除一个键
  * @param key
  * @return
  */
 boolean del(String key);

 /**
  * key设置value 没有失效时间
  * @param key
  * @param value
  */
 void set(String key, String value);
 /**
  * key设置value 有失效时间
  * @param key
  * @param value
  * @param expire
  */
 void set(String key, String value, Integer expire);

 /**
  * 向key递增1
  * @param key
  * @return
  */
 Long incr(String key);

 /**
  * 向key递增1 ,设置expire失效时间
  * @param key
  * @param expire
  * @return
  */
 Long incr(String key, Integer expire);

 /**
  * 向key递增delta数值 并设置expire失效时间
  * @param key
  * @param delta
  * @param expire
  * @return
  */
 Long incr(String key, int delta, Integer expire);
 /**
  * 向key递减1
  * @param key
  * @return
  */
 Long decr(String key);
 /**
  * 向key递减1 ,设置expire失效时间
  * @param key
  * @param expire
  * @return
  */
 Long decr(String key, Integer expire);

 /**
  * 向key设置expire失效时间
  * @param key
  * @param expire
  */
 void expire(String key, Integer expire);

 /**
  * 判断key是不存在,设值为1和设置失效时间 成功返回 true
  * 判断key是存在,直接返回false
  * @param key
  * @param expire
  * @return
  */
 boolean setnx(String key, Integer expire);
 /**
  * 判断key是不存在,设值为value和设置失效时间 成功返回 true
  * 判断key是存在,直接返回false
  * @param key
  * @param expire
  * @return
  */
 boolean setnxv(String key,String value ,Integer expire);

 /**
  * 判断键是否存在
  * @param key
  * @return
  */
 Boolean hasKey(String key);
 //Redis 集合(Set)
 /**
 Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
 Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
  */

 /**
  * Redis Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。
  * 假如集合 key 不存在,则创建一个只包含添加的元素作成员的集合。
  * 当集合 key 不是集合类型时,返回一个错误。
  * 注意:在 Redis2.4 版本以前, SADD 只接受单个成员值。
  */
 /**
  * 设置set 不重复的值,
  * 向key插入value值 ,
  * expire为键的失效时间
  * @param key
  * @param value
  * @param expire null 无时间
  */
 void sadd(String key, String value, Integer expire);

 /**
  * 向key键 的set 删除一个元素memeber
  * @param key
  * @param memeber
  */
 void srem(String key, String memeber);

 /**
  * set中命令判断成员元素是否是集合的成员。
  * @param key
  * @param value
  * @return
  */
 boolean sismember(String key, String value);

 /**
  * set取出key所有的数据
  * @param key
  * @return
  */
 Set<String> smembers(String key);

 /**
  * set中这个key值的数量
  * @param key
  * @return
  */
 Long ssize(String key);

 //Redis 列表(List)
 /**
 Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
 一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
  */

 /**
  * 取得key分页的数据
  * @param key list 的键
  * @param start 开始下标
  * @param end 结束下标
  * @return
  */
 List<String> lrange(String key, int start, int end);

 /**
  * list取key的下值的数量
  * @param key
  * @return
  */
 int llen(String key);

 /**
  *   开始---结尾
  * 向右添加数据 左---→右 添加数据
  * @param key list 键
  * @param value 添加到list的值
  * @param expire list 失效时间
  */
 void rpush(String key, String value, Integer expire);
 /**
  *   结尾---开始
  * 向左添加数据 右---→左 添加数据
  * @param key list 键
  * @param value 添加到list的值
  * @param expire list 失效时间
  */
 void lpush(String key, String value, Integer expire);

 /**
  * list中这个key键下删除count个value值
  * @param key list 键
  * @param count 删除多少个值
  * @param value list 中的值
  */
 void rmpush(String key,Integer count, String value);

 /**
  * 移出并获取列表的第一个元素(下标为0的元素)
  * @param key list 键
  * @return
  */
 String lpop(String key);

 // Redis 有序集合(sorted set)
	/**
	Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
	不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
	有序集合的成员是唯一的,但分数(score)却可以重复。
	集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
	 */

 /**
  * Redis Zadd 命令用于将一个或多个成员元素及其分数值加入到有序集当中。
  * 如果某个成员已经是有序集的成员,那么更新这个成员的分数值,并通过重新插入这个成员元素,来保证该成员在正确的位置上。
  * 分数值可以是整数值或双精度浮点数。
  * 如果有序集合 key 不存在,则创建一个空的有序集并执行 ZADD 操作。
  * 当 key 存在但不是有序集类型时,返回一个错误。
  * 注意: 在 Redis 2.4 版本以前, ZADD 每次只能添加一个元素。
  */

  /**
  * @param key 有序集合 key
  * @param member 成员元素
  * @param score 成员的分数值
  * @return 成功与否
  */
 boolean zadd(String key, String member, double score, Integer expire);

 /**
  * Redis Zinterstore 命令计算给定的一个或多个有序集的交集,其中给定 key 的数量必须以 numkeys 参数指定,并将该交集(结果集)储存到 destination 。
  * 默认情况下,结果集中某个成员的分数值是所有给定集下该成员分数值之和
  */
 long zinterstore(String key, List<String> otherKeys, String destKey, Integer expire);

 /**
  * 获取有序集合的第一个元素,通过索引区间来实现,而不是通过分数
  * @param key
  * @return
  */
 String zfirst(String key);

 /**
  * 删除zset中指定的member值
  * @param key
  * @param member
  * @return
  */
 boolean zrem(String key, String member);

 /**
  * zset取出key中所有的数据
  * @param key
  * @return
  */
 Map<String, Double> zscan(String key);

 /**
  * 对key的zset中member进行递增或者递减incrScore值
  * @param key zset 键
  * @param member 目标
  * @param incrScore 要改变的数值
  * @param expire 失效时间
  * @return
  */
 Double zincrby(String key, String member, double incrScore, Integer expire);

 /**
  * 找到对key的zset中member值(也就是这个member分数)
  * @param key
  * @param member
  * @return
  */
 Double zscore(String key, String member);

 //Redis 哈希(Hash)

 /**
 Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。
 Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。
  */

 /**
  * 添加 hash对象
  * hash一般存储对象 key 标记那个用户
  * hashKey用户下的什么信息
  * value 具体数据
  * @param key hash 的键
  * @param hashKey 目标键
  * @param value 存储的值
  * @param expire 失效时间
  */
 void hput(String key, String hashKey, Object value, Integer expire);

 /**
  * 删除 hash对象 key键 中的 hashKey
  * @param key
  * @param hashKey
  */
 void hdel(String key, String hashKey);

 /**
  * 获取 hash对象 key键 中的 hashKey具体的数据
  * @param key
  * @param hashKey
  */
 Object hget(String key, String hashKey);

 /**
  * 获取 hash对象 key键 下有多少个对象数量
  * @param key
  * @return
  */
 Long hsize(String key);

 /**
  *获 取 hash对象 key键 下有所有的对象
  * @param key
  * @return
  */
 List<Object> hgetAll(String key);

 //Redis 管道(Pipeline)

 /**
  * 这个过程称为Round trip time(简称RTT, 往返时间),mget mset有效节约了RTT,
  * 但大部分命令(如hgetall,并没有mhgetall)不支持批量操作,需要消耗N次RTT ,
  * 这个时候需要pipeline来解决这个问题
  */

 /**
  * 管道批量插入
  * @author DuanLinpeng
  * @date 2021/01/08 15:15
  * @param saveList
  * @param unit
  * @param timeout
  * @return void
  */
  void batchInsert(List<Map<String, String>> saveList, TimeUnit unit, int timeout);

 /**
  * batchGet管道形式(推荐,性能高,类型多)
  * @param keyList
  * @return
  */
  List<String> batchGet(List<String> keyList);

 /**
  * multiGet批量查询(只能是str)
  * @param keys
  * @return List<String>
  */
 List<String> getmultiet(List<String> keys);

}

Redis整合SpringBoot》》 RedisServiceImpl 实现

package com.tuan.common.base.redis.impl;

import com.tuan.common.base.redis.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.StringRedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

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

@Service
public class RedisServiceImpl implements RedisService {
 private final String KVS_KEY_SPLIT = "-";

 @Value("${spring.application.name}")
 private String applicationName;
 @Value("${spring.profiles.active}")
 private String profileActive;
 @Value("${customize.copyright.name.en}")
 private String copyrightEn;
 @Autowired
 private StringRedisTemplate stringRedisTemplate;

 /**
  * stringRedisTemplate.opsForValue();  //操作字符串
  * stringRedisTemplate.opsForHash();   //操作hash
  * stringRedisTemplate.opsForList();   //操作list
  * stringRedisTemplate.opsForSet();   //操作set
  * stringRedisTemplate.opsForZSet();   //操作有序set
  */

 /**
  * assembleCacheKey所有键的拼接
  * @param key
  * @return
  */
 private String assembleCacheKey(String key) {
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return copyrightEn + KVS_KEY_SPLIT + applicationName + KVS_KEY_SPLIT + profileActive + KVS_KEY_SPLIT + key;
 }

 @Override
 public List<String> getmultiet(List<String> keys) {
  if (CollectionUtils.isEmpty(keys)) {
   return null;
  }
  keys= keys.stream().map( key -> assembleCacheKey(key)).collect(Collectors.toList());
  return stringRedisTemplate.opsForValue().multiGet(keys);
 }

 @Override
 public String get(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return stringRedisTemplate.opsForValue().get(key);
 }

 @Override
 public List<String> lrange(String key, int start, int end) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return stringRedisTemplate.opsForList().range(key, start, end);
 }

 @Override
 public int llen(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return 0;
  }
  Long size = stringRedisTemplate.opsForList().size(key);
  return null == size ? 0 : size.intValue();
 }

 @Override
 public Integer getInt(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  String value = stringRedisTemplate.opsForValue().get(key);
  if (StringUtils.isEmpty(value)) {
   return null;
  }
  try {
   return Integer.valueOf(value);
  } catch (NumberFormatException e) {
   e.printStackTrace();
   return null;
  }
 }

 @Override
 public boolean del(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return false;
  }
  try {
   Boolean delete = stringRedisTemplate.delete(key);
   return null != delete && delete;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }

 @Override
 public boolean delslike(String key) {
  key = assembleCacheKey(key);
  Set<String> keys = stringRedisTemplate.keys(key);
  if (StringUtils.isEmpty(key)) {
   return false;
  }
  try {
   Long delete = stringRedisTemplate.delete(keys);
   return delete > 0 ?true:false;
  } catch (Exception e) {
   e.printStackTrace();
   return false;
  }
 }

 @Override
 public void set(String key, String value) {
  set(key, value, null);
 }

 @Override
 public void set(String key, String value, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
   return;
  }
  if (null != expire) {
   stringRedisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
  } else {
   stringRedisTemplate.opsForValue().set(key, value);
  }
 }

 @Override
 public Long incr(String key) {
  return incr(key, 1, null);
 }

 @Override
 public Long incr(String key, Integer expire) {
  return incr(key, 1, expire);
 }

 @Override
 public Long incr(String key, int delta, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  Long ret = stringRedisTemplate.opsForValue().increment(key, delta);
  if (null != expire) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
  return ret;
 }

 @Override
 public Long decr(String key) {
  return incr(key, -1, null);
 }

 @Override
 public Long decr(String key, Integer expire) {
  return incr(key, -1, expire);
 }

 @Override
 public void rpush(String key, String value, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
   return;
  }
  stringRedisTemplate.opsForList().rightPush(key, value);
  if (null != expire) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
 }

 @Override
 public void lpush(String key, String value, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
   return;
  }
  stringRedisTemplate.opsForList().leftPush(key, value);
  if (null != expire) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
 }

 @Override
 public void rmpush(String key, Integer count, String value) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
   return;
  }
  stringRedisTemplate.opsForList().remove(key,count, value);
 }

 @Override
 public String lpop(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return stringRedisTemplate.opsForList().leftPop(key);
 }

 @Override
 public void expire(String key, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return;
  }
  if (null != expire) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
 }

 @Override
 public boolean setnx(String key, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return false;
  }
  Boolean ret = stringRedisTemplate.opsForValue().setIfAbsent(key, "1");
  if (null == ret || !ret) {
   return false;
  }
  if (null != expire) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
  return true;
 }

 @Override
 public boolean setnxv(String key,String value ,Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return false;
  }
  Boolean ret = stringRedisTemplate.opsForValue().setIfAbsent(key, value);
  if (null == ret || !ret) {
   return false;
  }
  if (null != expire) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
  return true;
 }

 @Override
 public Boolean hasKey(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return false;
  }
  Boolean result = stringRedisTemplate.hasKey(key);
  return null == result ? false : result;
 }

 @Override
 public void sadd(String key, String value, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
   return;
  }
  Long result = stringRedisTemplate.opsForSet().add(key, value);
  if (null != expire && null != result && result > 0) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
 }

 @Override
 public void srem(String key, String memeber) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key) || StringUtils.isEmpty(memeber)) {
   return;
  }
  stringRedisTemplate.opsForSet().remove(key, memeber);
 }

 @Override
 public boolean sismember(String key, String value) {
  if (StringUtils.isEmpty(value)) {
   return false;
  }
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return false;
  }
  Boolean result = stringRedisTemplate.opsForSet().isMember(key, value);
  return null == result ? false : result;
 }

 @Override
 public Set<String> smembers(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return stringRedisTemplate.opsForSet().members(key);
 }

 @Override
 public Long ssize(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return stringRedisTemplate.opsForSet().size(key);
 }

 @Override
 public boolean zadd(String key, String member, double score, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return false;
  }
  Boolean result = stringRedisTemplate.opsForZSet().add(key, member, score);
  if (null == result || !result) {
   return false;
  }
  if (null != expire) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
  return true;
 }

 @Override
 public long zinterstore(String key, List<String> otherKeys, String destKey, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return 0;
  }
  destKey = assembleCacheKey(destKey);
  if (StringUtils.isEmpty(destKey)) {
   return 0;
  }
  if (CollectionUtils.isEmpty(otherKeys)) {
   return 0;
  }
  List<String> finalOtherKeys = new ArrayList<>();
  for (String eachOtherKey : otherKeys) {
   finalOtherKeys.add(assembleCacheKey(eachOtherKey));
  }
  Long result = stringRedisTemplate.opsForZSet().intersectAndStore(key, finalOtherKeys, destKey);
  if (null == result || result <= 0) {
   return 0;
  }
  if (null != expire) {
   stringRedisTemplate.expire(destKey, expire, TimeUnit.SECONDS);
  }
  return result;
 }

 @Override
 public String zfirst(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  Set<String> stringSet = stringRedisTemplate.opsForZSet().range(key, 0, 0);
  return CollectionUtils.isEmpty(stringSet) ? null : stringSet.toArray()[0].toString();
 }

 @Override
 public boolean zrem(String key, String member) {
  if (StringUtils.isEmpty(member)) {
   return false;
  }
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return false;
  }
  Long result = stringRedisTemplate.opsForZSet().remove(key, member);
  return null != result && result > 0;
 }

 @Override
 public Map<String, Double> zscan(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  try {
   Cursor<ZSetOperations.TypedTuple<String>> tupleCursor = stringRedisTemplate.opsForZSet().scan(key, ScanOptions.scanOptions().build());
   Map<String, Double> result = new HashMap<>();
   while (tupleCursor.hasNext()) {
    ZSetOperations.TypedTuple<String> tuple = tupleCursor.next();
    result.put(tuple.getValue(), tuple.getScore());
   }
   return result;
  } catch (Exception e) {
   e.printStackTrace();
   return null;
  }
 }

 @Override
 public Double zincrby(String key, String member, double incrScore, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  Double score = stringRedisTemplate.opsForZSet().incrementScore(key, member, incrScore);
  if (null != expire && expire > 0) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
  return score;
 }

 @Override
 public Double zscore(String key, String member) {
  if (StringUtils.isEmpty(member)) {
   return null;
  }
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return stringRedisTemplate.opsForZSet().score(key, member);
 }

 @Override
 public void hput(String key, String hashKey, Object value, Integer expire) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return;
  }
  stringRedisTemplate.opsForHash().put(key, hashKey, value);
  if (null != expire && expire > 0) {
   stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
  }
 }

 @Override
 public void hdel(String key, String hashKey) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return;
  }
  stringRedisTemplate.opsForHash().delete(key, hashKey);
 }

 @Override
 public Object hget(String key, String hashKey) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return stringRedisTemplate.opsForHash().get(key, hashKey);
 }

 @Override
 public Long hsize(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return stringRedisTemplate.opsForHash().size(key);
 }

 @Override
 public List<Object> hgetAll(String key) {
  key = assembleCacheKey(key);
  if (StringUtils.isEmpty(key)) {
   return null;
  }
  return stringRedisTemplate.opsForHash().values(key);
 }

 @Override
 public void batchInsert(List<Map<String, String>> saveList, TimeUnit unit, int timeout) {
  /* 插入多条数据 */
  stringRedisTemplate.executePipelined(new SessionCallback<Object>() {
   @Override
   public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
    for (Map<String, String> needSave : saveList) {
     stringRedisTemplate.opsForValue().set(needSave.get("key"), needSave.get("value"), timeout,unit);
    }
    return null;
   }
  });
 }

 @Override
 public List<String> batchGet(List<String> keyList) {
  /* 批量获取多条数据 */
  List<Object> objects = stringRedisTemplate.executePipelined(new RedisCallback<String>() {
   @Override
   public String doInRedis(RedisConnection redisConnection) throws DataAccessException {
    StringRedisConnection stringRedisConnection = (StringRedisConnection) redisConnection;
    for (String key : keyList) {
     stringRedisConnection.get(key);
    }
    return null;
   }
  });

  List<String> collect = objects.stream().map(val -> String.valueOf(val)).collect(Collectors.toList());

  return collect;
 }

}

到此这篇关于Redis整合SpringBoot的RedisTemplate实现类的文章就介绍到这了,更多相关Redis整合SpringBoot实现类内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

您可能感兴趣的文章:
  • spring boot整合redis主从sentinel方式
  • 关于SpringBoot整合redis使用Lettuce客户端超时问题
  • SpringBoot整合Redisson的步骤(单机版)
  • SpringBoot整合Redis的步骤
  • 微服务Spring Boot 整合 Redis 实现UV 数据统计的详细过程

今天关于SpringBoot中注入RedisTemplate实例异常解决的分享就到这里,希望大家有所收获,若想了解更多关于33. Springboot 系列 原生方式引入Redis,非RedisTemplate、Java 使用Jedis和RedisTemplate操作Redis缓存(SpringBoot)、Redis 系列-- SpringBoot 中 redisTemplate 的操作、Redis整合SpringBoot的RedisTemplate实现类(实例详解)等相关知识,可以在本站进行查询。

本文标签: