• Springboot 整合redis


    本项目基于springboot+ spring-boot-starter-data-redis

    简单的boot demo可以参考:SpringBoot实战基础搭建

    先看下项目结构:


     
    redis.jpg

    boot整合redis只需要在pom加入

    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.0.4.RELEASE</version>
    </dependency>

    yml中加入

    spring:
        redis:
            database: 0
            host: 127.0.0.1
            port: 6379
            password:******  
            jedis:
              pool:
                max-active: 100
                max-idle: 10
                max-wait: 100000
            timeout: 5000    

    注意:password要换成自己的密码

    application.properties(用yml或application.properties 其中一个就可以)

     1 # Redis数据库索引(默认为0)  
      spring.redis.database=0  
     5 # Redis服务器地址  
     7 spring.redis.host=192.168.0.24  
     8 
     9 # Redis服务器连接端口  
    10 
    11 spring.redis.port=6379  
    12 
    13 # Redis服务器连接密码(默认为空)  
    14 
    15 spring.redis.password=  
    16 
    17 # 连接池最大连接数(使用负值表示没有限制)  
    18 
    19 spring.redis.pool.max-active=200  
    20 
    21 # 连接池最大阻塞等待时间(使用负值表示没有限制)  
    22 
    23 spring.redis.pool.max-wait=-1  
    24 
    25 # 连接池中的最大空闲连接  
    26
    27 spring.redis.pool.max-idle=10 
    28 
    29 # 连接池中的最小空闲连接  
    30 
    31 spring.redis.pool.min-idle=0  
    32 
    33 # 连接超时时间(毫秒)  
    34
    35 spring.redis.timeout=1000 

    有以上配置,其实就可以直接使用,
    但是因为我们用了RedisTemplate,不管是RedisTemplate还是StringRedisTemplate,序列化都有问题,会出现乱码的情况比如:


     
    乱码.jpg

    我用代码插入到redis,它会在前面加些乱码,但是用代码去查询是没有问题的,直接在redis客户端操作是有问题的,所以我们都会在config包下面来设置RedisTemplate的序列化
    我们看下代码:

    package com.yzl.config;
    
    
    import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    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.RedisOperations;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.data.redis.serializer.StringRedisSerializer;
    
    @Configuration
    @ConditionalOnClass(RedisOperations.class)
    @EnableConfigurationProperties(RedisProperties.class)
    public class RedisConfig {
    
    
        @Bean
        @ConditionalOnMissingBean(name = "redisTemplate")
        public RedisTemplate<Object, Object> redisTemplate(
                RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<Object, Object> template = new RedisTemplate<>();
            //使用fastjson序列化
            FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
            // value值的序列化采用fastJsonRedisSerializer
            template.setValueSerializer(fastJsonRedisSerializer);
            template.setHashValueSerializer(fastJsonRedisSerializer);
            // key的序列化采用StringRedisSerializer
            template.setKeySerializer(new StringRedisSerializer());
            template.setHashKeySerializer(new StringRedisSerializer());
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    
        @Bean
        @ConditionalOnMissingBean(StringRedisTemplate.class)
        public StringRedisTemplate stringRedisTemplate(
                RedisConnectionFactory redisConnectionFactory) {
            StringRedisTemplate template = new StringRedisTemplate();
            template.setConnectionFactory(redisConnectionFactory);
            return template;
        }
    
    }

    为了方便使用redis,笔者封装了redis的工具类:

    package com.yzl.utils;
    
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.stereotype.Component;
    import org.springframework.util.CollectionUtils;
    
    import javax.annotation.Resource;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    @Component
    public final class RedisUtil {
    
        @Resource
        private RedisTemplate<String, Object> redisTemplate;
    
    
        public Set<String> keys(String keys){
            try {
                return redisTemplate.keys(keys);
            }catch (Exception e){
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 指定缓存失效时间
         * @param key 键
         * @param time 时间(秒)
         * @return
         */
        public boolean expire(String key, long time) {
            try {
                if (time > 0) {
                    redisTemplate.expire(key, time, TimeUnit.SECONDS);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 根据key 获取过期时间
         * @param key 键 不能为null
         * @return 时间(秒) 返回0代表为永久有效
         */
        public long getExpire(String key) {
            return redisTemplate.getExpire(key, TimeUnit.SECONDS);
        }
        /**
         * 判断key是否存在
         * @param key 键
         * @return true 存在 false不存在
         */
        public boolean hasKey(String key) {
            try {
                return redisTemplate.hasKey(key);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 删除缓存
         * @param key 可以传一个值 或多个
         */
        @SuppressWarnings("unchecked")
        public void del(String... key) {
            if (key != null && key.length > 0) {
                if (key.length == 1) {
                    redisTemplate.delete(key[0]);
                } else {
                    redisTemplate.delete(CollectionUtils.arrayToList(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 boolean set(String key, Object value) {
            try {
                redisTemplate.opsForValue().set(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
         /**
         * 普通缓存放入, 不存在放入,存在返回
         * @param key 键
         * @param value 值
         * @return true成功 false失败
         */
        public boolean setnx(String key, Object value) {
            try {
                redisTemplate.opsForValue().setIfAbsent(key,value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 普通缓存放入并设置时间
         * @param key 键
         * @param value 值
         * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
         * @return true成功 false 失败
         */
        public boolean set(String key, Object value, long time) {
            try {
                if (time > 0) {
                    redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
                } else {
                    set(key, value);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
      /**
         * 普通缓存放入并设置时间,不存在放入,存在返回
         * @param key 键
         * @param value 值
         * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
         * @return true成功 false 失败
         */
        public boolean setnx(String key, Object value, long time) {
            try {
                if (time > 0) {
                    redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS);
                } else {
                    set(key, value);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 递增
         * @param key 键
         * @param delta 要增加几(大于0)
         * @return
         */
        public long incr(String key, long delta) {
            if (delta < 0) {
                throw new RuntimeException("递增因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, delta);
        }
        /**
         * 递减
         * @param key 键
         * @param delta 要减少几(小于0)
         * @return
         */
        public long decr(String key, long delta) {
            if (delta < 0) {
                throw new RuntimeException("递减因子必须大于0");
            }
            return redisTemplate.opsForValue().increment(key, -delta);
        }
        /**
         * HashGet
         * @param key 键 不能为null
         * @param item 项 不能为null
         * @return*/
        public Object hget(String key, String item) {
            return redisTemplate.opsForHash().get(key, item);
        }
        /**
         * 获取hashKey对应的所有键值
         * @param key 键
         * @return 对应的多个键值
         */
        public Map<Object, Object> hmget(String key) {
            return redisTemplate.opsForHash().entries(key);
        }
        /**
         * HashSet
         * @param key 键
         * @param map 对应多个键值
         * @return true 成功 false 失败
         */
        public boolean hmset(String key, Map<String, Object> map) {
            try {
                redisTemplate.opsForHash().putAll(key, map);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * HashSet 并设置时间
         * @param key 键
         * @param map 对应多个键值
         * @param time 时间(秒)
         * @return true成功 false失败
         */
        public boolean hmset(String key, Map<String, Object> map, long time) {
            try {
                redisTemplate.opsForHash().putAll(key, map);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         * @param key 键
         * @param item 项
         * @param value 值
         * @return true 成功 false失败
         */
        public boolean hset(String key, String item, Object value) {
            try {
                redisTemplate.opsForHash().put(key, item, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 向一张hash表中放入数据,如果不存在将创建
         * @param key 键
         * @param item 项
         * @param value 值
         * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
         * @return true 成功 false失败
         */
        public boolean hset(String key, String item, Object value, long time) {
            try {
                redisTemplate.opsForHash().put(key, item, value);
                if (time > 0) {
                    expire(key, time);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 删除hash表中的值
         * @param key 键 不能为null
         * @param item 项 可以使多个 不能为null
         */
        public void hdel(String key, Object... item) {
            redisTemplate.opsForHash().delete(key, item);
        }
        /**
         * 判断hash表中是否有该项的值
         * @param key 键 不能为null
         * @param item 项 不能为null
         * @return true 存在 false不存在
         */
        public boolean hHasKey(String key, String item) {
            return redisTemplate.opsForHash().hasKey(key, item);
        }
        /**
         * hash递增 如果不存在,就会创建一个 并把新增后的值返回
         * @param key 键
         * @param item 项
         * @param by 要增加几(大于0)
         * @return
         */
        public double hincr(String key, String item, double by) {
            return redisTemplate.opsForHash().increment(key, item, by);
        }
        /**
         * hash递减
         * @param key 键
         * @param item 项
         * @param by 要减少记(小于0)
         * @return
         */
        public double hdecr(String key, String item, double by) {
            return redisTemplate.opsForHash().increment(key, item, -by);
        }
        /**
         * 根据key获取Set中的所有值
         * @param key 键
         * @return
         */
        public Set<Object> sGet(String key) {
            try {
                return redisTemplate.opsForSet().members(key);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        /**
         * 根据value从一个set中查询,是否存在
         * @param key 键
         * @param value 值
         * @return true 存在 false不存在
         */
        public boolean sHasKey(String key, Object value) {
            try {
                return redisTemplate.opsForSet().isMember(key, value);
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 将数据放入set缓存
         * @param key 键
         * @param values 值 可以是多个
         * @return 成功个数
         */
        public long sSet(String key, Object... values) {
            try {
                return redisTemplate.opsForSet().add(key, values);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
        /**
         * 将set数据放入缓存
         * @param key 键
         * @param time 时间(秒)
         * @param values 值 可以是多个
         * @return 成功个数
         */
        public long sSetAndTime(String key, long time, Object... values) {
            try {
                Long count = redisTemplate.opsForSet().add(key, values);
                if (time > 0)
                    expire(key, time);
                return count;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
        /**
         * 获取set缓存的长度
         * @param key 键
         * @return
         */
        public long sGetSetSize(String key) {
            try {
                return redisTemplate.opsForSet().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
        /**
         * 移除值为value的
         * @param key 键
         * @param values 值 可以是多个
         * @return 移除的个数
         */
        public long setRemove(String key, Object... values) {
            try {
                Long count = redisTemplate.opsForSet().remove(key, values);
                return count;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
        // ===============================list=================================
        /**
         * 获取list缓存的内容
         * @param key 键
         * @param start 开始
         * @param end 结束 0 到 -1代表所有值
         * @return
         */
        public List<Object> lGet(String key, long start, long end) {
            try {
                return redisTemplate.opsForList().range(key, start, end);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        /**
         * 获取list缓存的长度
         * @param key 键
         * @return
         */
        public long lGetListSize(String key) {
            try {
                return redisTemplate.opsForList().size(key);
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
        /**
         * 通过索引 获取list中的值
         * @param key 键
         * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
         * @return
         */
        public Object lGetIndex(String key, long index) {
            try {
                return redisTemplate.opsForList().index(key, index);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        /**
         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @return
         */
        public boolean lSet(String key, Object value) {
            try {
                redisTemplate.opsForList().rightPush(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @param time 时间(秒)
         * @return
         */
        public boolean lSet(String key, Object value, long time) {
            try {
                redisTemplate.opsForList().rightPush(key, value);
                if (time > 0)
                    expire(key, time);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 将list放入缓存
         * @param key 键
         * @param value 值
         * @return
         */
        public boolean lSet(String key, List<Object> value) {
            try {
                redisTemplate.opsForList().rightPushAll(key, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 将list放入缓存
         *
         * @param key 键
         * @param value 值
         * @param time 时间(秒)
         * @return
         */
        public boolean lSet(String key, List<Object> value, long time) {
            try {
                redisTemplate.opsForList().rightPushAll(key, value);
                if (time > 0)
                    expire(key, time);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 根据索引修改list中的某条数据
         * @param key 键
         * @param index 索引
         * @param value 值
         * @return
         */
        public boolean lUpdateIndex(String key, long index, Object value) {
            try {
                redisTemplate.opsForList().set(key, index, value);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
        /**
         * 移除N个值为value
         * @param key 键
         * @param count 移除多少个
         * @param value 值
         * @return 移除的个数
         */
        public long lRemove(String key, long count, Object value) {
            try {
                Long remove = redisTemplate.opsForList().remove(key, count, value);
                return remove;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
    }

    项目中使用时只需要注入即可

    package com.yzl.controller;
    
    import com.yzl.utils.RedisUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @Slf4j
    @RestController
    @RequestMapping("/a")
    public class TestController {
    
        @Autowired
        private RedisUtil redisUtil;
    
        @GetMapping("redis")
        public Object getRedis(){
            redisUtil.set("r","aaaaaa");
            return redisUtil.get("r");
        }
    
    }

    使用很简单,就是笔者发现一个问题,配置了RedisConfig之后,控制台说一直找不到RedisTemplate,后来找了一下午发现和AOP有冲突
    AOP代码如下:

    package com.yzl.aop;
    
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Arrays;
    
    
    @Slf4j
    @Aspect
    //@Component
    public class LogAspect {
        @Pointcut("execution(public * com.yzl.*.*.*(..))")
        public void logPointcut(){
    
        }
    
        @Before("logPointcut()")
        public void  methodBefore(JoinPoint joinPoint){
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = requestAttributes.getRequest();
            //打印请求内容
            log.info("---------------请求内容---------------");
            log.info("请求地址:"+request.getRequestURL().toString());
            log.info("请求方式:"+request.getMethod());
            log.info("请求类方法:"+joinPoint.getSignature().getName());
            log.info("请求类方法参数:"+ Arrays.toString(joinPoint.getArgs()));
            log.info("---------------请求内容---------------");
        }
    
    
        @AfterReturning(returning = "o",pointcut = "logPointcut()")
        public void methodAfterReturning(Object o){
            log.info("===============返回内容===============");
            log.info("返回的内容:"+ o.toString());
            log.info("===============返回内容===============");
        }
    
    
        @AfterThrowing(pointcut = "logPointcut()",throwing = "e")
        public void logThrowing(JoinPoint joinPoint,Throwable e){
            log.info("***************抛出异常***************");
    
            log.info("请求类方法:"+joinPoint.getSignature().getName());
            log.info("异常内容:"+e);
            log.info("***************抛出异常***************");
        }
    
    }

    这里暂时没找到什么原因,用了@order注解也没用,所以暂时取消了AOP统一日志处理
    如果各位也有类似的情况,可以欢迎讨论。

    谢谢!

    ps:问题找到了,应该是AOP加载优先级高于bean的@Configuration加载,所以AOP扫到RedisConfig的类的时候,没有得到redisTemplate,得到空指针,也可能是其他原因,暂时解决方法:
    aop扫描的时候,不要扫描配置bean,也就是不要扫描config包下的东西,可以写改为

    @Pointcut("execution(public * com.yzl.serviceImpl.*.*(..))")
        public void logPointcut(){
    
        }

    这样只扫描业务层代码,在实际中可能更常用
    或者也可以这么写,扫描指定包下的所有类:

    execution(public * com.yzl.serviceImpl.*.*(..) && public * com.yzl.controller.*.*(..) )


    作者:灵_芝
    链接:https://www.jianshu.com/p/8e71737a1101
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    本文转自:https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html

  • 相关阅读:
    node eventLoop
    apply call bind
    crm项目-业务实现
    crm项目-stark组件分析
    OA项目-需求分析
    OA项目-表结构
    OA项目-xadmin使用
    路飞学城项目-表结构
    路飞学城项目-支付相关-支付宝第三方支付
    路飞学城项目-支付相关-支付接口
  • 原文地址:https://www.cnblogs.com/minmin123/p/13595734.html
Copyright © 2020-2023  润新知