1.集成Redis
1.导入依赖
<!--spirngboot springdata对redis支持-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.配置信息
#数据源配置
spring:redis:database: 0host: 127.0.0.1port: 6379password: 123456jedis:pool:max-wait: 2000msmax-active: 8
3.注入redisTemplate使用
@RunWith(SpringRunner.class) //使用springboot2.6.13的版本可以省略这个注解
@SpringBootTest(classes = App.class) //如果测试类和启动不在同一个包下classes必须要写
public class SpringbootDataRedisApplicationTests {@Autowiredprivate RedisTemplate redisTemplate;@Testpublic void test() throws Exception{redisTemplate.opsForValue().set("name","zs");System.out.println(redisTemplate.opsForValue().get("name"));}
}
4.自定义配置redis中key和value的序列化
@Configuration
public class RedisConfig {// 注入Redis连接工厂@Resourceprivate RedisConnectionFactory factory;/*** @Description: 自定义RedisTemplate对象注入Bean容器中* @Author: Neuronet* @Date: 2023/10/22 18:49**/@Beanpublic RedisTemplate<Object, Object> redisTemplate() {// 1.创建一个RedisTemplate对象RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();// 2.指定Redis连接工厂redisTemplate.setConnectionFactory(factory);// 3.创建一个JSON格式序列化对象,此处使用的是Redis自己的的序列化器GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer();// 4.指定除开hash数据类型之外的数据key和value使用什么序列化器redisTemplate.setKeySerializer(serializer);redisTemplate.setValueSerializer(serializer);// 5.指定hash数据类型的key和value序列化器redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(serializer);return redisTemplate;}
}
2.SpringCahe缓存管理
1. SpringCache概述
Spring 3.1 引入了激动人心的基于注解(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(比如EHCache 或者 OSCache),而是一个对缓存使用的抽象,通过在既有代码中加入少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果
Spring 的缓存技术还具备相当的灵活性。不仅能够使用 SpEL(Spring Expression Language)来定义缓存的 key 和各种 condition,还提供开箱即用的缓存暂时存储方案,也支持和主流的专业缓存比如 EHCache 集成
说人话:SpringCahce对缓存流程进行了简化封装,提供了一些注解,我们通过简单的打注解就能实现缓存的添加,修改,删除等,注解如下:
- @Cacheable:触发缓存写入
- @CacheEvict:触发缓存清除
- @CachePut:更新缓存(不会影响到方法的运行)
- @Caching:重新组合要应用于方法的多个缓存操作
- @CacheConfig:设置类级别上共享的一些常见缓存设置
2.SpringCache大致原理
- 1.Spring Cache利用了AOP,实现了基于注解的缓存功能,并且进行了合理的抽象,业务代码不用关心底层是使用了什么缓存框架,只需要简单地加一个注解,就能实现缓存功能了,做到了对代码侵入性做小。
- 2.由于市面上的缓存工具实在太多,SpringCache框架还提供了CacheManager接口,可以实现降低对各种缓存框架的耦合。它不是具体的缓存实现,它只提供一整套的接口和代码规范、配置、注解等,用于整合各种缓存方案,比如Caffeine、Guava Cache、Ehcache。
3.SpringCache注解
3.1. @Cacheable:写缓存
- 方式一:@Cacheable可以用来进行缓存的写入,先也会根据缓存名和key去查询,
如果没有查询到,自动将方法的返回结果存储在缓存中,以便于在后续调用的时候可以直接返回缓存中的值,而不必再执行实际的方法
@Cacheable(cacheNames=“books”,key=”’book1’”) // books::book1
public Book findBook(ISBN isbn) {.//查询数据库return 数据;
}
- 方式二:一个方法可以对应多个缓存名称
@Cacheable(cacheNames={“books”, “isbns”},key=”’book1’”)
public Book findBook(ISBN isbn) {..…}
- 方式三@Cacheable的缓存名称是可以配置动态参数的,比如选择传入的参数,如下: (以下示例是使用SpEL声明,如果您不熟悉SpEL,可以阅读Spring Expression Language)
@Cacheable(cacheNames=“books”, key=“#isbn”) //参数值作为Key
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)@Cacheable(cacheNames=“books”, key=“#isbn.rawNumber”)
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
- 方式四
@Cacheable还可以设置根据条件判断是否需要缓存
condition:取决于给定的参数是否满足条件
unless:取决于返回值是否满足条件(除非)
以下是一个简单的例子:key有默认的名字
@Cacheable(cacheNames=“book”, condition=“#name.length() < 32”)
public Book findBook(String name)@Cacheable(cacheNames=“book”,condition=“#name.length()<32”, unless=“#result.hardback”)
public Book findBook(String name)
3.2. @CachePut:修改缓存
@CachePut:当需要更新缓存而不干扰方法的运行时 ,可以使用该注解。也就是说,始终执行该方法,并将结果放入缓存
(已经有缓存就更新缓存),注解参数与@Cacheable相同。 以下是一个简单的例子:
@CachePut(cacheNames="book", key="#isbn")
public Book updateBook(ISBN isbn, BookDescriptor descriptor) {}
通常强烈建议不要对同一方法同时使用@CachePut和@Cacheable注解,因为它们具有不同的行为。可能会产生不可思议的BUG哦
3.3. @CacheEvict:删除缓存
@CacheEvict:删除缓存的注解,这对删除旧的数据和无用的数据是非常有用的。这里还多了一个参数(allEntries),设置allEntries=true时,可以对整个条目进行批量删除。 以下是个简单的例子:
@CacheEvict(cacheNames="books", key="'book1'")
public void loadBooks(InputStream batch)//对cacheNames进行批量删除
@CacheEvict(cacheNames="books", allEntries=true)
public void loadBooks(InputStream batch)
3.4. @Caching:组合注解
@Caching在使用缓存的时候,有可能会同时进行更新和删除,会出现同时使用多个注解的情况。而@Caching可以实现。 以下是个简单的例子:
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
public Book importBooks(String deposit, Date date)
3.5. @CacheConfig: 统一配置
@CacheConfig:缓存提供了许多的注解选项,但是有一些公用的操作,我们可以使用@CacheConfig在类上进行全局设置。 以下是个简单的例子:
@CacheConfig(cacheName="books")
public class BookRepositoryImpl implements BookRepository {//注意:如果没有指定key的话,keyGenerator会自动生成key导致删除缓存失败,所以下面的缓存操作需要指定key@Cacheable(key="'book1'")public Book findBook(ISBN isbn) {...}
}
4.SpringCache实战
1.导入依赖
<!-- SpringCache依赖 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
2.配置SpringCache集成redis
/*** @Description: SpringCache配置* @Author: Neuronet* @Date: 2023/10/22 19:32**/
@Configuration
public class CacheConfig extends CachingConfigurerSupport {@Resourceprivate RedisConnectionFactory factory;@Bean@Overridepublic CacheResolver cacheResolver() {return new SimpleCacheResolver(cacheManager());}@Bean@Overridepublic CacheErrorHandler errorHandler() {// 用于捕获从Cache中进行CRUD时的异常的回调处理器。return new SimpleCacheErrorHandler();}//缓存管理器@Bean@Overridepublic CacheManager cacheManager() {RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues() //不允许空值.serializeValuesWith(RedisSerializationContext.SerializationPair//值使用JSON序列化.fromSerializer(new GenericJackson2JsonRedisSerializer()));return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();}
}
3.开启springCache
在启动类注解:@EnableCaching
4.添加缓存
缓存注解不能加在内部方法上,比如:方法A调用方法B,给方法B加上缓存注解会失效,因为内部方法调用代理会失效,在A方法上打注解即可
//会先根据articleType::typeTree从redis获取,如果有直接用缓存的。如果没有就执行方法体的代码查询数据库
@Cacheable(cacheNames = "articleType", key = "'typeTree'")
public List<ArticleType> getTypeTree() {Object obj = redisTemplate.opsForValue().get("typeTree");if(obj == null){//redis没有List<ArticleType> typeTree = typeTree();redisTemplate.opsForValue().set("typeTree",typeTree);return typeTree;}return typeTree();
}