SpringBoot整合

SpringBoot操作数据:是封装在Spring-data中的,jpa、jdbc、mongodb、redis

在SpringBoot2.x以后与原来使用的jedis被替换成来看lettuce,底层已经不使用jedis了

  • jedis:采用的直连,多个线程操作的话,不安全,要提高安全性要使用jedis pool连接池
  • lettuce:采用netty,高性能网络框架,异步请求,实例在多线程中可以共享,不存在线程不安全的情况,dubbo底层也是用netty,可以减少线程数量,更像NIO
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

原理讲解

  • SpringBoot所有配置类,都会有一个自动配置类

  • image-20201123181024492

  • 自动配置类都会绑定一个properties配置文件

  • RedisAutoConfiguation

  • image-20201123184404313

  • 启动配置类中有一个RedisProperties配置类

  • image-20201123184540147

  • 里面有很多以前缀spring.redis开头的配置,可以在application中配置

  • 如host、password、、配置

  • RedisAutoConfiguation中封装了两个Bean

    • RedisTemplate

      • @Bean
        @ConditionalOnMissingBean(name = "redisTemplate")
        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
              throws UnknownHostException {
           RedisTemplate<Object, Object> template = new RedisTemplate<>();
           template.setConnectionFactory(redisConnectionFactory);
           return template;
        }
        
      • 没有过多的设置,Redis的对象都是需要序列化的

      • 两个泛型都是object,后面使用需要强制转换

      • 靠自己重写config来替换这个template

    • StringRedisTamplate

      • 大部分情况下String类型是最常用的,就会多一个stringRedisTemplate
  • @ConditionalOnMissingBean(name = "redisTemplate")
    //重写一个redisTemplate就能替换掉这个bean
    

整合实现

  • 导入依赖
  • 配置连接
  • 测试

实现

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

  • 根据在properties中看到的配置参数,以spring.redis为prefix的配置

  • 但是建议使用lettuce

  • 在redisTemplate的parameter中需要给入一个RedisConnectionFactory

  • image-20201123190946352

  • 有两个方法实现了这个接口

  • 在Jedis中有多个爆红,没下载完整

  • image-20201123191158826

  • lettuce中下载完整,为了避免不必要的错误,建议使用lettuce,默认生效

  • 测试

  • image-20201123192421507

  • 注入,RedisTamplate,里面有ops,表示operations 操作

  • 操作value字符串,hash、list、set、cluter集群、、、

  • 操作的几种数据类型,有些操作也直接拿出来了,可以直接调用,其他比较细化的操作就要进入各自的数据类型的操作

  •     @Test
        void contextLoads() {
            redisTemplate.opsForValue().set("name","haoyun");
            System.out.println(redisTemplate.opsForValue().get("name"));
            RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
            connection.flushAll();
            connection.close();
    
        }
    
  • 能直接操作也能获取连接

  • 127.0.0.1:6379> keys *
    1) "\xac\xed\x00\x05t\x00\x04name"
    127.0.0.1:6379> 
    
  • 但是会出现乱码

  • Redis的对象都需要序列化serialization

  • 默认的序列化是JDK序列化,可能要使用JSON来序列化

  • 需要自己来定义配置类

  • 创建对象时需要序列化、implement Serializable

  •     @Test
        void test2() throws JsonProcessingException {
            User user = new User();
    //        String jsonUser = new ObjectMapper().writeValueAsString(user);
            redisTemplate.opsForValue().set("user",user);
            System.out.println(redisTemplate.opsForValue().get("user"));
        }
    
  • 直接将user给入会产生defaultSerializer序列化问题

  •     @Test
        void test2() throws JsonProcessingException {
            User user = new User();
    //        String jsonUser = new ObjectMapper().writeValueAsString(user);
            redisTemplate.opsForValue().set("user",user);
            System.out.println(redisTemplate.opsForValue().get("user"));
        }
    
  • 直接给入user对象,会报错DefaultSerializer错误

  • image-20201123201835889

  • 将对象序列化,或通过fastjson的方法专为string类型

  • 正式的开发一般通过json来传不会直接传对象

  • 虽然不报错了,但是存储的数据还是乱码

  • 127.0.0.1:6379> keys *
    1) "\xac\xed\x00\x05t\x00\x04name"
    2) "\xac\xed\x00\x05t\x00\x04user"
    127.0.0.1:6379> 
    
  • 默认序列化是JDKSerializer

  • RedisSerializer有多种实现方法

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hnhHrbf-1606724738964)(…/…/…/Library/Application Support/typora-user-images/image-20201123202648831.png)]

  • 选取一个实现方法,给setKeySerializer

  • template.setKeySerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
    
  • 多使用cmd+p查看方法需要的parameter,给进去就好

  • RedisConfig

  • package com.haoyun.redisspringboot.config;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    import java.net.UnknownHostException;
    
    @Configuration
    @SuppressWarnings("all")
    //镇压所有警告
    public class RedisConfig {
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
                throws UnknownHostException {
            RedisTemplate<String, Object> template = new RedisTemplate<>();
    //      默认的连接配置
            template.setConnectionFactory(redisConnectionFactory);
    
    //        序列化配置
    //        new 一个Jackson序列化对象,用于后面的设置
            Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
            ObjectMapper objectMapper = new ObjectMapper();
    //        用于转义
            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    
            objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);
    //       创建string的序列化
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    
    //       string的key和hash的key都采用string的序列化
    //        value都采用Jackson的序列化
    
            //key采用string序列化方式
            template.setKeySerializer(stringRedisSerializer);
            //hash的key采用string序列化方式
            template.setHashKeySerializer(stringRedisSerializer);
            //value采用Jackson序列化方式
            template.setValueSerializer(objectJackson2JsonRedisSerializer);
            //hash的value采用Jackson序列化方式
            template.setHashValueSerializer(objectJackson2JsonRedisSerializer);
    
    
            return template;
        }
    }
    
  • 测试

  • package com.haoyun.redisspringboot;
    
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.haoyun.redisspringboot.pojo.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.data.redis.core.RedisTemplate;
    
    @SpringBootTest
    class RedisSpringbootApplicationTests {
        @Autowired
        @Qualifier("redisTemplate")
        private RedisTemplate redisTemplate;
    
        @Test
        void test1() throws JsonProcessingException {
            User name1 = new User("name", 3);
            String name = new ObjectMapper().writeValueAsString(name1);
            redisTemplate.opsForValue().set("key1", name);
            System.out.println(redisTemplate.opsForValue().get("key"));
    
        }
    
    
    }
    
    
  • 通过这样的序列化之后key就不会乱码了,但是在企业开发中一般不直接以原生的编写,将常用的操作封装为RedisUtils,自己写一些工具类来使用

  • 在工具类中应该加入一些容错操作,能抛出异常

  • 在公司能看到一些封装的RedisUtils

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐