zoukankan      html  css  js  c++  java
  • redis学习1

    redis学习1

    一、概念复习

    关系型数据库和非关系型数据库的区别
    关系型数据库:数据之间有关联关系,数据存储在硬盘上,以表的形式存储数据。
    非关系型数据库:redis,数据之间没有关联关系,以键值对的形式存储,存储在内存中。
    与数据库交互比较耗时,查询一些不经常发生变化的数据时可以把其缓存在redis中,加快访问速度。
    redis支持存储的值数据类型:
    字符串,list,map,set,有序set
    redis持久化方式:
    RDB方式,在一定的间隔时间中检测key的变化,然后持久化数据。
    jedis客户端操作redis

    二、用jedis操作redis

    
    public class Test1 {
        public static void main(String[] args) {
            //获取连接
            //Jedis jedis=new Jedis("localhost",6379);
            Jedis jedis = getJedisClien();//使用jedis连接池来获取jedis
            //设置字符串值
            jedis.set("username","zhangsan");
            //带过期时间设置值
            jedis.setex("password",10,"123");
            //获取字符串
            System.out.println(jedis.get("username"));
    
            //存储hash
            jedis.hset("student","name","zhangsan");
            jedis.hset("student","age","18");
            //获取map中的某个值
            System.out.println(jedis.hget("student","age"));
            //获取整个map
            Map<String, String> map = jedis.hgetAll("student");
            Set<Map.Entry<String, String>> entries = map.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                System.out.println(entry.getKey()+":"+entry.getValue());
            }
    
            //存储列表
    //        jedis.lpush("list","a");
    //        jedis.lpush("list","b");
    //        jedis.rpush("list","c");
            //list范围获取
            List<String> list = jedis.lrange("list", 0, -1);
            System.out.println(list);
            //list弹出
            String ele = jedis.lpop("list");
            System.out.println(ele);
            String ele2 = jedis.rpop("list");
            System.out.println(ele2);
    
            //set集合类型数据
            jedis.sadd("myset","java","php","c_sharp");
            jedis.srem("myset","java");//移除set集合中的某个元素
            Set<String> myset = jedis.smembers("myset");//获取set集合的全部元素
            System.out.println(myset);
    
            //有序set存储,根据给定的分数排序,分数越大越靠后
            jedis.zadd("mysortSet",1,"a");
            jedis.zadd("mysortSet",10,"c");
            jedis.zadd("mysortSet",100,"b");
            System.out.println(jedis.zrange("mysortSet",0,-1));
    
            //指定某个key的过期时间
            jedis.expire("student",15);
            jedis.close();//使用连接池获取到的连接,调用close方法就是把连接归还连接池
        }
    
        /**
         * 用jedis连接池来获取jedis对象
         * @return
         */
        public static Jedis getJedisClien(){
            JedisPoolConfig config=new JedisPoolConfig();
            config.setMaxTotal(10);
            config.setMaxIdle(10);
            JedisPool pool=new JedisPool(config,"localhost",6379);
            return pool.getResource();
        }
    }
    

    三、springboot整合redis

    spring提供了一个RedisTemplate对象可以用来操作redis,在springboot中当然也可以使用redisTemplate

    3.1 整合步骤

    引入redis的起步依赖

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

    在配置文件中对redis和jedis的连接信息进行配置

    spring:
      redis:
        host: localhost
        port: 6379
        jedis:
          pool:
            max-idle: 10
            max-active: 8
            max-wait: -1
            min-idle: 0
    

    在需要操作redis的地方注入redisTemplate的对象,就可以使用

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = RedisStudyApplication.class)
    public class Test1 {
    
        @Autowired
        private RedisTemplate redisTemplate;//这个对象的泛型是<Object,Object>
    
        @Test
        public void test1(){
            //存储和获取字符串
            redisTemplate.boundValueOps("username").set("zhangsan");
            //使用泛型是<Object,Object>的模板对象,get方法返回的是Object
            Object value = redisTemplate.boundValueOps("username").get();
            System.out.println(value);
    
            //存储和获取map
            redisTemplate.boundHashOps("demoMap").put("key1","value1");
            Object value2 = redisTemplate.boundHashOps("demoMap").get("key1");
            System.out.println(value2);
        }
    }
    

    3.2 自动注入的redistemplate对象详解

    springboot提供了redis的自动配置类来创建redisTemplate对象,配置类如下:

    
    @Configuration
    @ConditionalOnClass(RedisOperations.class)
    @EnableConfigurationProperties(RedisProperties.class)
    @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
    public class RedisAutoConfiguration {
    
    	@Bean
    	@ConditionalOnMissingBean(name = "redisTemplate")
    	public RedisTemplate<Object, Object> redisTemplate(
    			RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
    		RedisTemplate<Object, Object> template = new RedisTemplate<>();
    		template.setConnectionFactory(redisConnectionFactory);
    		return template;
    	}
    
    	@Bean
    	@ConditionalOnMissingBean
    	public StringRedisTemplate stringRedisTemplate(
    			RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
    		StringRedisTemplate template = new StringRedisTemplate();
    		template.setConnectionFactory(redisConnectionFactory);
    		return template;
    	}
    
    }
    

    可以看到其中提供了两个redisTemplate对象,一个泛型是RedisTemplate<Object, Object>,另一个的泛型是<String,String>。

    使用这种方式注入的是泛型是<Object, Object>的redisTemplate对象

    @Autowired
    private RedisTemplate redisTemplate;
    

    所以使用这个redisTemplate操作redis存储的key和value都是object类型的。

    3.3 使用StringRedisTemplate

    	/**
         * 测试 StringRedisTemplate来操作redis,序列化器使用的是 StringRedisSerializer
         */
        @Test
        public void test2(){
            //1.存储和获取字符串
            stringRedisTemplate.boundValueOps("accountName").set("lyy");
            //使用指定泛型的模板对象来操作redis,get方法返回的对象就是指定的泛型类型的
            String value = stringRedisTemplate.boundValueOps("accountName").get();
            System.out.println(value);
    
            //2.redis中存取hash类型的数据
            stringRedisTemplate.boundHashOps("stringMap").put("key1","value1");
            //通过redistemplate来获取hash类型的数据
            Object value2 = stringRedisTemplate.boundHashOps("stringMap").get("key1");
            System.out.println(value2);
        }
    

    3.4序列化器

    将一个对象存储到redis中,需要把一个对象序列化即保存这个对象的状态,再把序列化的结果保存到redis中。

    同样的,从redis中把一个对象读取到内存中需要反序列化这个对象。

    spring提供了几个序列化器

    Jackson2JsonRedisSerializer
    JdkSerializationRedisSerializer
    OxmSerializer
    StringRedisSerializer
    GenericToStringRedisSerializer
    GenericJackson2JsonRedisSerializer
    

    当我们自动注入泛型是<Object,Object>的redisTemplate对象时,默认使用的是jdk自己的序列化器,所以序列化后存储到redis的结果会和实际的内容有出入,不管是key还是value都多了一些特殊内容。

    当使用StringRedisTemplate时,序列化使用的是StringRedisSerializer这个序列化器,部分源码如下

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

    使用这个序列化器把字符串序列化后再存储到redis中,序列化的结果和实际的内容是一样的

    3.5 自定义redisTemplate的泛型和序列化器

    springboot自定配置的redisTemplate不满足使用要求时,可以自己在配置类中配置一个redisTemplate对象。

    	/**
         * 自定义的redisTemplate对象
         * @param redisConnectionFactory
         * @return
         */
        @Bean
        public RedisTemplate<String, Object> objectRedisTemplate(
                RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
            //设置template的序列化器
            template.setKeySerializer(new StringRedisSerializer());//设置key的序列化器
            Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
            //配置序列化器的属性
            ObjectMapper mapper=new ObjectMapper();
            mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            //配置这个属性后从redis中再拿取到的就还是原来的对象,不配置这个属性存进去的是对象,获取到的会是一个map
            serializer.setObjectMapper(mapper);
            template.setValueSerializer(serializer);//设置value的序列化器
            template.setHashKeySerializer(serializer);
            template.setHashValueSerializer(serializer);
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    

    使用自定义的redisTemplate

    	/**
         * 使用自定义的redisTemplate,key的序列化器使用StringRedisSerializer,value的序列化器使用Jackson2JsonRedisSerializer
         */
        @Test
        public void test3(){
            //1.存储和获取字符串
            myRedisTemplate.boundValueOps("demo3").set("demo3-value");
            Object demo3Value = myRedisTemplate.boundValueOps("demo3").get();
            System.out.println(demo3Value);
            //2.将一个map对象序列化成字符串然后存入redis中 redis中存储key-string类型
            Map<String,String> map=new HashMap<>();
            map.put("key1","value1");
            map.put("key2","value2");
            myRedisTemplate.boundValueOps("mapString").set(map);
            Object map1 = myRedisTemplate.boundValueOps("mapString").get();
            System.out.println(map1);
    
            //2.把一个自定义对象序列化成字符串存入redis reids中存储 key-string类型
            Student stu=new Student("1","zhangsan",18);
            myRedisTemplate.boundValueOps("student").set(stu);
            Object student = myRedisTemplate.boundValueOps("student").get();
            System.out.println(student);
    
            //3.给redis中存入hash类型的数据,hash中存储的是student对象(序列化成字符串),redis中存储的是key-hash类型
            Student st1=new Student("2","st1",19);
            Student st2=new Student("3","st2",19);
            myRedisTemplate.boundHashOps("studentMap").put("st1",st1);
            myRedisTemplate.boundHashOps("studentMap").put("st2",st2);
            Object obj = myRedisTemplate.boundHashOps("studentMap").get("st1");
            System.out.println(obj);
        }
    

    注意:

    在配置value的序列化器时使用了

    		//配置序列化器的属性
            ObjectMapper mapper=new ObjectMapper();
            mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            //配置这个属性后从redis中再拿取到的就还是原来的对象,不配置这个属性存进去的是对象,获取到的会是一个map
            serializer.setObjectMapper(mapper);
    

    是因为配置了这个后对象序列化成字符并存储到redis时字符串中会包含它的来源对象的信息,这样反序列时就可以重新反序列化成原来的对象。

    此序列化器序列化对象的字符串的信息如下:

    "["com.lyy.entity.Student",{"id":"1","userName":"zhangsan","age":18}]"
    

    这个字符串中包含了原始类Student的全类名,所以反序列化时就可以根据这个把其还原成原来的对象。

    四、总结

    redis中可以存储五种数据类型:String,List,hash,set,sortSet

    springboot操作redis使用的核心对象是redisTemplate

    springboot的redis自动配置类配置了两个redisTemplate<Object,Object>,和StringRedisTemplate<String,String>

    存储一个对象到redis中需要把对象序列化,spring提供了多个序列化器。

    可以自己配置指定泛型的redisTemplate,并指定序列化器。

  • 相关阅读:
    管线命令
    CentOS7搭建本地YUM仓库,并定期同步阿里云源
    linux日志分割脚本
    Centos 7 命令整理
    python实现变脸动画测试
    python打印杨辉三角
    python打印乘法口诀,敏感字替换
    python食人蛇代码
    用python写的考勤自动打卡程序
    tomcat发版脚本
  • 原文地址:https://www.cnblogs.com/chengxuxiaoyuan/p/12985328.html
Copyright © 2011-2022 走看看