springcache配置

本文介绍了如何在Spring项目中启用Spring Cache,并详细配置了RedisTemplate,包括使用Jackson2JsonRedisSerializer解决序列化问题。涉及到了RedisCacheManager的创建和配置参数的设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先redis配置中加入@EnableCaching注解 启用springcache
在这里插入图片描述
加入配置 即可使用springcache缓存注解
在这里插入图片描述

下面贴源码

package com.tongsheng.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;

/**
 * @author Yw
 * @version 1.0
 * @date 2021/7/23 15:24
 * @description redis配置 集群下启动session共享,需打开@EnableRedisHttpSession 单机下不需要
 */
//@EnableRedisHttpSession
@EnableCaching
@Configuration
@SuppressWarnings({"unchecked", "rawtypes"})
public class RedisConfig {

    @Bean("redisTemplate")
    public RedisTemplate redisTemplate(@Lazy RedisConnectionFactory factory) {
        RedisTemplate redis = new RedisTemplate();
        GenericToStringSerializer<String> keySerializer = new GenericToStringSerializer<String>(String.class);
        redis.setKeySerializer(keySerializer);
        redis.setHashKeySerializer(keySerializer);
        GenericJackson2JsonRedisSerializer valueSerializer = new GenericJackson2JsonRedisSerializer();
        redis.setValueSerializer(valueSerializer);
        redis.setHashValueSerializer(valueSerializer);
        redis.setConnectionFactory(factory);
        return redis;
    }

    @Bean
    public ValueOperations<String, String> valueOperations(RedisTemplate<String, String> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }

    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForZSet();
    }

    @Bean
    CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        // 配置序列化(解决乱码的问题)
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                //设置七天
                .entryTtl((Duration.ofDays(7)))
                //变双冒号为单冒号
                .computePrefixWith(((name -> name + ":")))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerialize()))
                .disableCachingNullValues();
        return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build();
    }


    private Jackson2JsonRedisSerializer jackson2JsonRedisSerialize() {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //这个方法已被废弃 使用activateDefaultTyping替代
        //om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        return jackson2JsonRedisSerializer;
    }

}

### Spring Cache 配置前缀失效的原因分析 Spring Cache 的配置前缀可能因多种原因而失效。以下是可能导致此问题的主要因素以及解决方案: #### 1. 缓存提供程序的默认行为覆盖了自定义配置 某些缓存实现(如 EhCache 或 JCS)可能会忽略全局设置中的 `prefix` 属性,转而依赖于其内部机制来命名缓存实例。如果未显式指定缓存名称,则可能会导致前缀无法生效。 对于这种情况,可以尝试通过强制指定缓存名称的方式解决问题。例如,在基于 XML 的配置中,可以通过如下方式明确声明缓存名称[^1]: ```xml <cache:annotation-driven /> <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager"> <property name="cacheNames"> <list> <value>myCustomPrefix.myCache</value> </list> </property> </bean> ``` #### 2. 缓存管理器未正确定义或注入 当使用第三方缓存库时(如 Redis、Infinispan),如果没有正确初始化缓存管理器或者未将其绑定到上下文中,也可能导致前缀功能不可用。例如,Redis 的连接工厂需要被明确定义并关联至缓存管理器[^3]。 以下是一个典型的 Redis 缓存管理器配置示例: ```java @Configuration @EnableCaching public class CacheConfig { @Bean public LettuceConnectionFactory redisConnectionFactory() { return new LettuceConnectionFactory("localhost", 6379); } @Bean public RedisCacheConfiguration cacheConfiguration() { return RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)) .disableCachingNullValues(); } @Bean public RedisCacheManager cacheManager(LettuceConnectionFactory redisConnectionFactory) { return RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(cacheConfiguration()) .build(); } } ``` 在此基础上,确保所有缓存键都带有统一的前缀。这通常可以在 `RedisCacheConfiguration` 中完成。 #### 3. 自定义 KeyGenerator 导致冲突 如果项目中存在自定义的 `KeyGenerator` 实现类,并且该实现忽略了前缀逻辑,则即使在全局范围内设置了前缀,实际生成的缓存键仍不会包含预期的内容。此时应检查 `key-generator` 是否已正确集成前缀支持。 一种推荐的做法是在方法级别标注中手动添加前缀信息: ```java @Cacheable(value = "products", key = "'customPrefix.' + #id") public Product findProductById(Long id) { // 方法体省略... } ``` #### 4. 使用内存型存储而非持久化存储 如果是采用纯内存模式运行的任务(比如利用 `MapJobRepositoryFactoryBean` 来保存批处理状态数据的情况),则由于这些临时结构本身不具备跨会话共享能力,因此任何外部化的前缀设定均无意义[^4]。这种场景下建议切换回数据库驱动版本以获得更稳定的性能表现。 --- ### 总结 综上所述,要解决 Spring Cache 前缀不起作用的问题,需逐一排查以上提到的各种可能性,并针对性调整相应组件的行为参数直至恢复正常为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值