springboot使用redis做缓存

此文纯属第一次用redis时记的笔记;
1 .springboot整合redis有两种方式:分别是jedis连接和redisTemplate
  • jedis是redis官方推荐的面向java的操作redis的客户端,存储起来的是字符串
  • 而redisTemplate是springDataRedis中对jedisapi的高度封装,存储的是二进制字节编码。其实在spring boot的官网上我们也能看到,官方现在推荐的是springdataredis形式相对于jedis来说可以方便的更换redis的java客户端,其比jedis多了自动管理连接池的特性,方便与其他spring框架进行搭配使用。例如:SpringCache;
2 .pom.xml中引入jar宝版本
  • springboot1.4版本以前依赖为spring-boot-starter-redis:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
    <version>1.3.2.RELEASE</version>
</dependency>
  • b.springboot1.4版本后依赖为spring-boot-starter-data-redis:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
    <version>1.3.2.RELEASE</version>
</dependency>
  • c.如果用jedis 就是 redis.clients
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
3. 引入jar包之后,我们再来看看配置文件:application.yml
# redis单服务器配置
spring:   
  redis:
    database: 0 # 使用第一个数据库,默认一共创建16个数据库
    host: 10.175.94.63  # Redis服务器地址  测试服务器中的redis
    port: 6379 # Redis服务器连接端口  
    password: # Redis服务器连接密码(默认为空) 
    pool:
      max-active: 8 # 连接池最大连接数(使用负值表示没有限制) 
      max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
      max-idle: 8 # 连接池中的最大空闲连接
      min-idle: 0 # 连接池中的最小空闲连接
    timeout: 0 # 连接超时时间(毫秒)
    commandTimeout: 5000
4 . 再来看看序列化问题:请参考 https://blog.csdn.net/f641385712/article/details/84679456,我觉得讲的很具体;

这边写一下比较常用的几种,大家酌情选用:

@Configuration
@EnableCaching // 启用缓存,这个注解很重要
public class RedisConfig  implements CachingConfigurer{

private Logger logger = LoggerFactory.getLogger(this.getClass());
//-----------------------序列化配置-------------------------------
@Bean
    public RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<?, ?> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        // key序列化方式;但是如果方法上有Long等非String类型的话,会报类型转换错误;
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();// Long类型不可以会出现异常信息;
        redisTemplate.setKeySerializer(redisSerializer);
        redisTemplate.setHashKeySerializer(redisSerializer);

        // JdkSerializationRedisSerializer序列化方式;
        JdkSerializationRedisSerializer jdkRedisSerializer = new JdkSerializationRedisSerializer();
        redisTemplate.setValueSerializer(jdkRedisSerializer);
        redisTemplate.setHashValueSerializer(jdkRedisSerializer);
        redisTemplate.afterPropertiesSet();
        
        // Json序列化方式
//      Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//      ObjectMapper om = new ObjectMapper();
//      om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//      om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//      jackson2JsonRedisSerializer.setObjectMapper(om);
//      RedisSerializer stringSerializer = new StringRedisSerializer();
//      redisTemplate.setKeySerializer(stringSerializer);// key序列化;
//      redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// value序列化 
//      redisTemplate.setHashKeySerializer(stringSerializer);//Hash key序列化
//      redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);//Hash value序列化 
//      redisTemplate.afterPropertiesSet();
        
        return redisTemplate;
    }


//------------------------连接配置---------------------------------------




    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.password}")
    private String password;

    @Value("${spring.redis.database}")
    private int database;

    @Value("${spring.redis.pool.max-idle}")
    private int maxIdle;

    @Value("${spring.redis.pool.min-idle}")
    private int minIdle;
/**
     * redis连接的基础设置
     * 
     * @Description:
     * @return
     */
    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(host);
        factory.setPort(port);
        factory.setPassword(password);
        // 存储的库
        factory.setDatabase(database);
        // 设置连接超时时间
        factory.setTimeout(timeout);
        factory.setUsePool(true);
        factory.setPoolConfig(jedisPoolConfig());
        return factory;
    }

    /**
     * 连接池配置
     * 
     * @Description:
     * @return
     */
    @Bean
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxIdle(maxIdle);
        jedisPoolConfig.setMinIdle(minIdle);
        // jedisPoolConfig.set ...
        return jedisPoolConfig;
    }

    /**
     * redis数据操作异常处理 这里的处理:在日志中打印出错误信息,但是放行
     * 保证redis服务器出现连接等问题的时候不影响程序的正常运行,使得能够出问题时不用缓存
     * 
     * @return
     */
    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
        CacheErrorHandler cacheErrorHandler = new CacheErrorHandler() {
            @Override
            public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
                logger.error("redis异常:key=[{}]", key, e);
            }

            @Override
            public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
                logger.error("redis异常:key=[{}]", key, e);
            }

            @Override
            public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
                logger.error("redis异常:key=[{}]", key, e);
            }

            @Override
            public void handleCacheClearError(RuntimeException e, Cache cache) {
                logger.error("redis异常:", e);
            }
        };
        return cacheErrorHandler;
    }

}

5. key的自定义策略:
@Configuration
public class RedisConfig{
/**
     * 注解@Cache key生成规则
     */
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }

        };
    }


      /**
     * 
     * @Title: appProjectCacheKeyGenerator
     * @Description: 自定key生成規則
     * @author admin
     * @return
     */
    @Bean
    public KeyGenerator appProjectCacheKeyGenerator() {
        AppProjectCacheKeyGenerator apckg = new AppProjectCacheKeyGenerator();
        return apckg;
    }
}

上面自定义key中的AppProjectCacheKeyGenerator是👇自定义的keyGenerator

public class AppProjectCacheKeyGenerator implements KeyGenerator {

    @Override
    public Object generate(Object target, Method method, Object... params) {
        return "MODEL-USER-ROLE";//自定义的key;
    }

}

这个KeyGenerator在注解缓存中的用法如下:相当于自定义key


@Cacheable(value = "user-resource",  keyGenerator = "appProjectCacheKeyGenerator")
    public List<GroupLevel> listuser() {
        return groupUserMapper.listAllUser();
    }

6. 关于注解:
  • @Cacheable:表明spring在调用方法之前,手下应该在缓存中查找方法的返回值,如果这个值能被找到,就会返回缓存的值,否则的话,这个方法就会被调用,返回值会放到缓存之中;
    语法: @Cacheable(value = "redis", keyGenerator = "cacheKeyGenerator")
    value:缓存位置的一段名称,不能为空;
    key:缓存的key,默认为空,表示使用方法的参数类型及参数值作为key;
    keyGenerator:指定key的生成策略;
    condition:触发条件,满足条件就加入缓存,默认为空,表示全部加入缓存;

  • @CacheEvict :
    语法:@CacheEvict(value = "redis", allEntries = true) 清除缓存
    value:缓存位置的一段名称,不能为空
    key:缓存的key,默认为空,表示使用方法的参数类型及参数值作为key,支持SpEL
    condition:触发条件,满足条件就加入缓存,默认为空,表示全部都加入缓存,支持SpEL
    allEntries:true表示清除value中的全部缓存,默认为false

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容