• Springboot+redis 整合


    运行环境:

    JDK1.7.

    SpringBoot1.4.7

    redis3.0.4

    1.生成Springboot项目,分别添加web,redis依赖,具体的maven依赖如下

     1      <dependency>
     2             <groupId>org.springframework.boot</groupId>
     3             <artifactId>spring-boot-starter-data-redis</artifactId>
     4         </dependency>
     5         <dependency>
     6             <groupId>org.springframework.boot</groupId>
     7             <artifactId>spring-boot-starter-web</artifactId>
     8         </dependency>
     9 
    10         <dependency>
    11             <groupId>org.springframework.boot</groupId>
    12             <artifactId>spring-boot-starter-test</artifactId>
    13             <scope>test</scope>
    14         </dependency>

    数据源

    使用spring的默认配置

    在 src/main/resources/application.properties 中配置数据源信息。

     1 server.context-path=/redis
     2 server.port=9099
     3 
     4 # REDIS (RedisProperties)
     5 # Redis数据库索引(默认为0)
     6 spring.redis.database=0
     7 # Redis服务器地址
     8 spring.redis.host=192.168.0.106
     9 # Redis服务器连接端口
    10 spring.redis.port=6379
    11 # Redis服务器连接密码(默认为空)
    12 #Sspring.redis.password=
    13 # 连接池最大连接数(使用负值表示没有限制)
    14 spring.redis.pool.max-active=8
    15 # 连接池最大阻塞等待时间(使用负值表示没有限制)
    16 spring.redis.pool.max-wait=-1
    17 # 连接池中的最大空闲连接
    18 spring.redis.pool.max-idle=8
    19 # 连接池中的最小空闲连接
    20 spring.redis.pool.min-idle=0
    21 # 连接超时时间(毫秒)
    22 spring.redis.timeout=10

    然后我们需要一个配置类,将配置文件与对象进行关联

    新建一个RedisConfig类

    @Configuration
    @EnableAutoConfiguration
    public class RedisConfig extends CachingConfigurerSupport {}

    通过

    @ConfigurationProperties

    注解,将属性文件注入进来

    @Bean
        @ConfigurationProperties(prefix = "spring.redis")
        public JedisPoolConfig getRedisConfig() {
            JedisPoolConfig config = new JedisPoolConfig();
            //System.out.println(config.getMaxWaitMillis());
            return config;
        }

    这里需要注意的是,我们的属性文件并没有全部的注入进来,这里只是配置连接池的属性

    我们还需要将redis的host,port等信息也注入进来

     1 @Autowired
     2     private Environment env;
     3 
     4 @Bean
     5     @ConfigurationProperties(prefix = "spring.redis")
     6     public JedisConnectionFactory getConnectionFactory() {
     7         JedisConnectionFactory factory = new JedisConnectionFactory();
     8         JedisPoolConfig config = getRedisConfig();
     9         factory.setPoolConfig(config);
    10         factory.setHostName(env.getProperty("spring.redis.host"));
    11         factory.setPort(Integer.parseInt(env.getProperty("spring.redis.port").trim()));
    12         factory.setDatabase(Integer.parseInt(env.getProperty("spring.redis.database").trim()));
    13         logger.info("JedisConnectionFactory bean init success.");
    14         return factory;
    15     }

    这样我们的属性信息就都配置好了

    我们就要开始连接redis服务器,实现我们的业务了,这里我们先介绍下 RedisTemplate

    spring 封装了 RedisTemplate 对象来进行对redis的各种操作,它支持所有的 redis 原生的 api。

    RedisTemplate中定义了对5种数据结构操作

    1 redisTemplate.opsForValue();//操作字符串
    2 redisTemplate.opsForHash();//操作hash
    3 redisTemplate.opsForList();//操作list
    4 redisTemplate.opsForSet();//操作set
    5 redisTemplate.opsForZSet();//操作有序set

    StringRedisTemplate与RedisTemplate

    • 两者的关系是StringRedisTemplate继承RedisTemplate。

    • 两者的数据是不共通的;也就是说StringRedisTemplate只能管理StringRedisTemplate里面的数据,RedisTemplate只能管理RedisTemplate中的数据。

    • SDR默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。

      StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。

      RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。

    我们先来写一个简单的例子,来看看RedisTemplate是怎么操作的

    还是在RedisConfig类里面

    1 @Bean
    2     public RedisTemplate<String, ?> getRedisTemplate() {
    3         RedisTemplate<String, ?> template = new RedisTemplate();
    4         template.setConnectionFactory(getConnectionFactory());
    5 
    6         return template;
    7     }

    然后我们新建一个service类,注入redisTemplate,操作相关的api,将键值对写入到redis服务器

     1 @Autowired
     2     private RedisTemplate<String, Object> redisTemplate; 6 
     7     public void setKey(Map<String, Map<?, ?>> map) {
     8         ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
     9         for (Map.Entry<String, Map<?, ?>> entry : map.entrySet()) {
    10             String jsonStringFromMap = JsonUtils.getJsonStringFromMap(entry.getValue());
    11             opsForValue.set(entry.getKey(), jsonStringFromMap);
    12         }
    13     }
    再写一个controller类,注入service
    @RequestMapping(value = "set")
        public ResponseVo setKey() {
            ResponseVo responseVo = new ResponseVo();
            try {
                Map<String, Map<?, ?>> map = new HashMap<String, Map<?, ?>>();
                Map<String, String> map2 = new HashMap<>();
                map2.put("value", "2");
                map.put("boxUid", map2);
                demoService.setKey(map);
                responseVo.setInfo("操作成功");
                responseVo.setData(map);
            } catch (Exception e) {
                responseVo.setInfo("操作失败");
                responseVo.setData(e.getMessage());
            }
    
            return responseVo;
        }

    请求:http://localhost:9099/redis/demo/set

    数据就写到redis数据库了。


    序列化

    RedisTemplate对象默认使用jdkSerializer实现序列化,如果想要更换序列化的实现方式,例如使用json实现value的序列化,可以进行如下配置

     1 @Bean
     2     Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer(ObjectMapper objectMapper) {
     3         Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
     4                 Object.class);
     5         jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
     6         return jackson2JsonRedisSerializer;
     7     }
     8 
     9     @Bean
    10     RedisTemplate<String, Object> objRedisTemplate(JedisConnectionFactory connectionFactory,
    11             Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer) {
    12         RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
    13         redisTemplate.setConnectionFactory(getConnectionFactory());
    14         redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
    15         StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    16         redisTemplate.setKeySerializer(stringRedisSerializer);
    17         redisTemplate.setHashKeySerializer(stringRedisSerializer);
    18         return redisTemplate;
    19     }

    redis的value将会以jason形式保存

    对象序列化

    除了String类型,实战中我们还经常会在Redis中存储对象,这时候我们就会想是否可以使用类似RedisTemplate<String, User>来初始化并进行操作。但是Spring Boot并不支持直接使用,需要我们自己实现RedisSerializer<T>接口来对传入对象进行序列化和反序列化,下面我们通过一个实例来完成对象的读写操作。

    • 创建要存储的对象:User
     1 public class User implements Serializable {
     2 
     3     /**
     4      * 
     5      */
     6     private static final long serialVersionUID = -8289770787953160443L;
     7 
     8     private String username;
     9     private Integer age;
    10 
    11     public User() {
    12         super();
    13         // TODO Auto-generated constructor stub
    14     }
    15 
    16     public User(String username, Integer age) {
    17         this.username = username;
    18         this.age = age;
    19     }
    20 
    21     public String getUsername() {
    22         return username;
    23     }
    24 
    25     public void setUsername(String username) {
    26         this.username = username;
    27     }
    28 
    29     public Integer getAge() {
    30         return age;
    31     }
    32 
    33     public void setAge(Integer age) {
    34         this.age = age;
    35     }
    36 
    37 }
    • 实现对象的序列化接口
     1 public class RedisObjectSerializer implements RedisSerializer<Object> {
     2     // private Converter<Object, byte[]> serializer = new SerializingConverter();
     3     // private Converter<byte[], Object> deserializer = new
     4     // DeserializingConverter();
     5     static final byte[] EMPTY_ARRAY = new byte[0];
     6 
     7     @Override
     8     public Object deserialize(byte[] bytes) {
     9         if (isEmpty(bytes)) {
    10             return null;
    11         }
    12         ObjectInputStream oii = null;
    13         ByteArrayInputStream bis = null;
    14         bis = new ByteArrayInputStream(bytes);
    15         try {
    16             oii = new ObjectInputStream(bis);
    17             Object obj = oii.readObject();
    18             return obj;
    19         } catch (Exception e) {
    20 
    21             e.printStackTrace();
    22         }
    23         return null;
    24     }
    25 
    26     @Override
    27     public byte[] serialize(Object object) {
    28         if (object == null) {
    29             return EMPTY_ARRAY;
    30         }
    31         ObjectOutputStream obi = null;
    32         ByteArrayOutputStream bai = null;
    33         try {
    34             bai = new ByteArrayOutputStream();
    35             obi = new ObjectOutputStream(bai);
    36             obi.writeObject(object);
    37             byte[] byt = bai.toByteArray();
    38             return byt;
    39         } catch (IOException e) {
    40             e.printStackTrace();
    41         }
    42         return null;
    43     }
    44 
    45     private boolean isEmpty(byte[] data) {
    46         return (data == null || data.length == 0);
    47     }
    48 }
    • 配置针对User的RedisTemplate实例
    @Bean
        public RedisTemplate<String, User> redisTemplate(RedisConnectionFactory factory) {
            RedisTemplate<String, User> template = new RedisTemplate<String, User>();
            template.setConnectionFactory(getConnectionFactory());
            template.setKeySerializer(new StringRedisSerializer());
            template.setValueSerializer(new RedisObjectSerializer());
            return template;
        }
    • 完成了配置工作后,编写测试用例实验效果
    @Autowired
        private RedisTemplate<String, User> redisUserTemplate;
    
    public void setUser(User user) {
            ValueOperations<String, User> opsForValue = redisUserTemplate.opsForValue();
            opsForValue.set(user.getUsername(), user);
            Integer age = opsForValue.get(user.getUsername()).getAge();
            String username = opsForValue.get(user.getUsername()).getUsername();
            System.out.println(age + " " + username);
        }

    最后的结果是会输出年龄和姓名。

    源代码

    相关示例代码在redisBoot

  • 相关阅读:
    没有被实例化的类 中的 非static成员函数竟然也可以被调用。。。前提是该成员函数没有用到成员变量
    c++注意
    关于类大小的小试验
    C语言|博客作业02
    在C#中进行时间和时间戳的转换
    正则表达式中匹配中括号 [ ]
    在C#中将对象序列化成Json格式
    在MSSQL中的简单数据类型递归
    HTML中padding和margin的区别和用法
    C#中的对称加密
  • 原文地址:https://www.cnblogs.com/xmzJava/p/7336918.html
Copyright © 2020-2023  润新知