• springboot( 三)redis demo


    redis介绍

    Redis是目前业界使用最广泛的内存数据存储。相比memcached,Redis支持更丰富的数据结构,例如hashes, lists, sets等,同时支持数据持久化。除此之外,Redis还提供一些类数据库的特性,比如事务,HA,主从库。可以说Redis兼具了缓存系统和数据库的一些特性,因此有着丰富的应用场景。本文介绍Redis在Spring Boot中两个典型的应用场景。

    如何使用

    1、引入 spring-boot-starter-data-redis

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

    2、添加配置文件

    #redis配置
    # REDIS (RedisProperties)
    # Redis服务器地址
    spring.redis.host=192.168.31.151
    # Redis服务器连接端口
    spring.redis.port=6379  
    # Redis服务器连接密码(默认为空)
    spring.redis.password=  
    #Redis数据库索引(默认为0)
    spring.redis.database=0  
    #连接池最大连接数(使用负值表示没有限制)
    spring.redis.jedis.pool.max-active=50
    #连接池最大阻塞等待时间(使用负值表示没有限制)
    spring.redis.jedis.pool.max-wait=3000
    #连接池中的最大空闲连接
    spring.redis.jedis.pool.max-idle=20
    #连接池中的最小空闲连接
    spring.redis.jedis.pool.min-idle=2
    #连接超时时间(毫秒)
    spring.redis.timeout=5000

    至于redis的安装配置,可见分布式进阶redis,一种安装传统的redis,一种用docker ,建议先安装docker,直接用docker pull redis 比较方便

    redisConfig->根据StringRedisTemplate对象命名我们可以知道该对象支持String类型,但是在实际的应用中,我们可能需要存入Object对象。那该怎么存储呢。聪明的你,肯定立刻想到了,直接把对象转成json格式字符串,不就可以存储了嘛。这里我使用jackson依赖转换成json数据

    @Configuration
    public class RedisConfig {
    
    //    /**
    //     * 连接 redis 需要 RedisConnection 和 RedisConnectionFactory,
    //     * RedisConnection 是通过 RedisConnectionFactory 进行创建
    //     * RedisConnection 提供较低级的数据操作 (byte arrays)
    //     */
    //    @Bean
    //    RedisConnectionFactory initJedisConnectionFactory(){
    //        //在这里设置redis连接对象配置
    //        return new JedisConnectionFactory();
    //    }
        
        /**
         * 配置RedisTemplate实例
         * @param factory
         * @return
         */
        @Bean
        public RedisTemplate<Serializable, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
            RedisTemplate<Serializable, Object> template = new RedisTemplate<Serializable, Object>();
            template.setConnectionFactory(connectionFactory);
            template.afterPropertiesSet();
            template.setKeySerializer(new StringRedisSerializer());
            template.setValueSerializer(new ObjectRedisSerializer());//自定义
            //template.setValueSerializer(new Jackson2JsonRedisSerializer(Object.class));//redis提供现有的
            return template;
        }
    }
    ObjectRedisSerializer类
    @Slf4j
    public class ObjectRedisSerializer implements RedisSerializer<Object>{
    
        
        
        /**
         * 定义序列化和发序列化转化类
         */
        private Converter<Object, byte[]> serializer = new SerializingConverter();
        private Converter<byte[], Object> deserializer = new DeserializingConverter();
        
        /**
         * 定义转换空字节数组
         */
        private static final byte[] EMPTY_ARRAY = new byte[0]; 
        
        @Override
        public byte[] serialize(Object obj) throws SerializationException {
            byte[] byteArray = null;
            if (null == obj) {
                log.warn("Redis待序列化的对象为空.");
                byteArray = EMPTY_ARRAY;
            } else {
                try {
                    byteArray = serializer.convert(obj);
                } catch (Exception e) {
                    log.error("Redis序列化对象失败,异常:"+e.getMessage());
                    byteArray = EMPTY_ARRAY;
                }
            }
            return byteArray;
        }
    
        @Override
        public Object deserialize(byte[] datas) throws SerializationException {
            Object obj = null;
            if(isNullOrEmpty(datas)){
                log.warn("Redis待反序列化的对象为空.");
            }else{
                try {
                    obj = deserializer.convert(datas);
                } catch (Exception e) {
                    log.error("Redis反序列化对象失败,异常:"+e.getMessage());
                }
            }
            return obj;
        }
        
        private boolean isNullOrEmpty(byte[] datas){
          return (null == datas)|| (datas.length == 0);
        }
    }

    RedisController

    @RestController
    @Slf4j
    public class RedisController {
        
        @Autowired
        private IUserService userService;
        
        @Autowired
        private RedisUtils redisUtils;
        
        @Autowired
        private RedisTemplate<Serializable, Object> redisTemplate;
         
        @RequestMapping("redis/getUser")
        public User getUser() throws Exception {
            String username = "lisi";
            User user  = (User) redisTemplate.opsForValue().get("user"+username);
            if(user ==null){
                log.info("未命中缓存!");
                user=userService.findByUsername(username);
                redisTemplate.opsForValue().set("user"+username, user);
            }
            return user;
        }
        
        @RequestMapping("redis/getUser2")
        public User getUser2() throws Exception {
            String username = "zhangsan";
            User user  = (User) redisUtils.get("user"+username);
            if(user ==null){
                log.info("未命中缓存!");
                user=userService.findByUsername(username);
                redisUtils.set("user"+username, user);
            }
            return user;
        }
        
    }

    也可以将常用操作提取出来,封装成RedisUtils,直接使用即可

    RedisUtils

    @Component
    public class RedisUtils {
     
        @Autowired
        private RedisTemplate<Serializable, Object> redisTemplate;
     
        /**
         * 读取缓存
         * 
         * @param key
         * @return
         */
        public Object get(final String key) {
            return redisTemplate.opsForValue().get(key);
        }
     
        /**
         * 写入缓存
         */
        public boolean set(final String key, Object value) {
            boolean result = false;
            try {
                redisTemplate.opsForValue().set(key, value);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
     
        /**
         * 更新缓存
         */
        public boolean getAndSet(final String key, Object value) {
            boolean result = false;
            try {
                redisTemplate.opsForValue().getAndSet(key, value);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
     
        /**
         * 删除缓存
         */
        public boolean delete(final String key) {
            boolean result = false;
            try {
                redisTemplate.delete(key);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    }

    测试:

     发现第一次未走缓存,第二次走了缓存

    如果redis获取的User不能强转,即xxx不能转换为xxx,按常理说不通,A怎么不能cast成A呢,debug仔细检查了是否有拼错类名及不一致情况,确实xxx就是xxx,
    怎么就不能cast呢?

    google一通得知和热部署有关,和用到的spring-boot-devtools有关,和classloader有关,这样就说的通了。看了许多帖子,都是比较直接的解决方案,把spring-boot-devtools注释掉,不要热部署了

    共享Session-spring-session-data-redis

    分布式系统中,sessiong共享有很多的解决方案,其中托管到缓存中应该是最常用的方案之一,

    Spring Session官方说明

    Spring Session provides an API and implementations for managing a user’s session information.

    如何使用

    1、引入依赖

    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-data-redis</artifactId>
    </dependency>
    2、Session配置:
    
    @Configuration
    @EnableRedisHttpSession(maxInactiveIntervalInSeconds
    = 86400*30)//失效时间一个月 public class SessionConfig { }

    注意:maxInactiveIntervalInSeconds: 设置Session失效时间,使用Redis Session之后,原Boot的server.session.timeout属性不再生效

    redis 客户端 输入 keys '*sessions*'

    1) "spring:session:expirations:1591092540000"
    2) "spring:session:sessions:expires:88fda400-dc85-4a22-8126-e1858febdc60"
    3) "userzhangsan"
    4) "spring:session:sessions:88fda400-dc85-4a22-8126-e1858febdc60"
    5) "user"
    6) "userlisi"
    127.0.0.1:6379> 

    其中 1591092540000为失效时间,意思是这个时间后session失效,88fda400-dc85-4a22-8126-e1858febdc60 为sessionId,登录http://localhost:8080/uid 发现会一致,就说明session 已经在redis里面进行有效的管理了。

    如何在两台或者多台中共享session

    其实就是按照上面的步骤在另一个项目中再次配置一次,启动后自动就进行了session共享。

    代码路径:

     
  • 相关阅读:
    设备树实践
    设备树实例解析
    设备树语法
    设备树基本概念
    设备树中#address-cells和#size-cells作用
    Linux设备驱动详解 宋宝华 硬件基础
    jffs2镜像制作
    ltp-ddt eth_iperf_tcp iperf dualtest遇到的问题
    shell 函数传递参数的几种方式
    windows logstash配置
  • 原文地址:https://www.cnblogs.com/flgb/p/12822708.html
Copyright © 2020-2023  润新知