首页 文章资讯内容详情

SpringBoot(七) SpringBoot中的缓存机制

2026-06-01 2 花语

本文内容纲要:

-SpringBoot中的Cache缓存 -1、基本概念 -2、整合项目 -Cache注解 -使用Redis做集中式缓存

随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一。Spring3开始提供了强大的基于注解的缓存支持,可以通过注解配置方式低侵入的给原有Spring应用增加缓存功能,提高数据访问性能。

SpringBoot中的Cache缓存

1、基本概念

Spring从3.1开始定义了org.springframework.cache.Cache和org.springframework.cache.CacheManager接口来统一不同的缓存技术;同时支持JCache(JSR-107)注解。

Cache 缓存接口,定义缓存操作,实现有:RedisCache、EhCacheCache、ConcurrentMapCache等 CacheManager 缓存管理器,管理各种缓存(Cache)组件 @Cacheable 针对方法配置,根据方法的请求参数对其结果进行缓存 @CacheEvict 清空缓存 @CachePut 保证方法被调用,又希望结果被缓存update,调用,将信息更新缓存 @EnableCaching 开启基于注解的缓存 KeyGenerator 缓存数据时key生成的策略 serialize 缓存数据时value序列化策略

2、整合项目

1、新建一个SpringBoot1.5+web+mysql+mybatis+cache

2、编写配置文件,连接Mysql

spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://192.168.1.125:3306/test01 spring.datasource.username=root spring.datasource.password=root mybatis.configuration.map-underscore-to-camel-case=true server.port=9000

3、创建JaveBean实例

publicclassEmployee{ privateIntegerid; privateStringlastName; privateStringgender; privateStringemail; privateIntegerdId; publicIntegergetId(){ returnid; } publicvoidsetId(Integerid){ this.id=id; } publicStringgetLastName(){ returnlastName; } publicvoidsetLastName(StringlastName){ this.lastName=lastName; } publicStringgetGender(){ returngender; } publicvoidsetGender(Stringgender){ this.gender=gender; } publicStringgetEmail(){ returnemail; } publicvoidsetEmail(Stringemail){ this.email=email; } publicIntegergetdId(){ returndId; } publicvoidsetdId(IntegerdId){ this.dId=dId; } @Override publicStringtoString(){ return"Employee{"+ "id="+id+ ",lastName="+lastName+\+ ",gender="+gender+\+ ",email="+email+\+ ",dId="+dId+ }; } }

4、创建mapper接口映射数据库,并访问数据库中的数据

importcom.wdjr.cache.bean.Employee; importorg.apache.ibatis.annotations.Mapper; importorg.apache.ibatis.annotations.Select; importorg.apache.ibatis.annotations.Update; @Mapper publicinterfaceEmployeeMapper{ @Select("SELECT*FROMemployeeWHEREid=#{id}") publicEmployeegetEmpById(Integerid); @Update("UPDATEemployeeSETlastName=#{lastName},email=#{email},gender=#{gender},d_id=#{dId}WHEREid=#{id}") publicvoidupdateEmp(Employeeemployee); }

5、在pom.xml中引入cache依赖

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

6、主程序添加注解MapperScan,并且使用@EnableCaching,开启缓存功能

importorg.mybatis.spring.annotation.MapperScan; importorg.springframework.boot.SpringApplication; importorg.springframework.boot.autoconfigure.SpringBootApplication; importorg.springframework.cache.annotation.EnableCaching; @EnableCaching @MapperScan("com.wdjr.cache.mapper") @SpringBootApplication publicclassSpringboot01CacheApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(Springboot01CacheApplication.class,args); } }

7、编写service,来具体实现mapper中的方法,使用@Cacheable增加缓存

importcom.wdjr.cache.bean.Employee; importcom.wdjr.cache.mapper.EmployeeMapper; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.cache.annotation.Cacheable; importorg.springframework.stereotype.Service; @Service publicclassEmployeeService{ @Autowired EmployeeMapperemployeeMapper; /** *将方法的运行结果进行缓存,以后要是再有相同的数据,直接从缓存中获取,不用调用方法 *CacheManager中管理多个Cache组件,对缓存的真正CRUD操作在Cache组件中,每个缓存组件都有自己的唯一名字; * *属性: *CacheName/value:指定存储缓存组件的名字 *key:缓存数据使用的key,可以使用它来指定。默认是使用方法参数的值,或方法的返回值 *编写Spel表达式:#id参数id的值,#a0/#p0#root.args[0] *keyGenerator:key的生成器,自己可以指定key的生成器的组件id *key/keyGendertor二选一使用 * *cacheManager指定Cache管理器,或者cacheReslover指定获取解析器 *condition:指定符合条件的情况下,才缓存; *unless:否定缓存,unless指定的条件为true,方法的返回值就不会被缓存,可以获取到结果进行判断 *sync:是否使用异步模式,unless不支持 * * */ @Cacheable(cacheNames={"emp"},key="#id",condition="#id>0",unless="#result==null") publicEmployeegetEmp(Integerid){ System.out.println("查询id="+id+"的员工"); returnemployeeMapper.getEmpById(id); } }

8、编写controller测试

@RestController publicclassEmployeeController{ @Autowired EmployeeServiceemployeeService; @GetMapping("/emp/{id}") publicEmployeegetEmp(@PathVariable("id")Integerid){ returnemployeeService.getEmp(id); } }

9、查看结果。具体结果就不截图了,缓存功能开启,如果条件相同,只会查询一次数据库。

Cache注解

@CacheConfig:主要用于配置该类中会用到的一些共用的缓存配置。在这里@CacheConfig(cacheNames="users"):配置了该数据访问对象中返回的内容将存储于名为users的缓存对象中,我们也可以不使用该注解,直接通过@Cacheable自己配置缓存集的名字来定义。

该注解是整合了Cacheable/Cacheput/CacheEvict。设置在类上,该类的方法上面的cache注解均不用设置name。

@Cacheable:配置了findByName函数的返回值将被加入缓存。同时在查询时,会先从缓存中获取,若不存在才再发起对数据库的访问。该注解主要有下面几个参数:

value、cacheNames:两个等同的参数(cacheNames为Spring4新增,作为value的别名),用于指定缓存存储的集合名。由于Spring4中新增了@CacheConfig,因此在Spring3中原本必须有的value属性,也成为非必需项了 key:缓存对象存储在Map集合中的key值,非必需,缺省按照函数的所有参数组合作为key值,若自己配置需使用SpEL表达式,比如:@Cacheable(key="#p0"):使用函数第一个参数作为缓存的key值,更多关于SpEL表达式的详细内容可参考官方文档 condition:缓存对象的条件,非必需,也需使用SpEL表达式,只有满足表达式条件的内容才会被缓存,比如:@Cacheable(key="#p0",condition="#p0.length()<3"),表示只有当第一个参数的长度小于3的时候才会被缓存,若做此配置上面的AAA用户就不会被缓存,读者可自行实验尝试。 unless:另外一个缓存条件参数,非必需,需使用SpEL表达式。它不同于condition参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对result进行判断。 keyGenerator:用于指定key生成器,非必需。若需要指定一个自定义的key生成器,我们需要去实现org.springframework.cache.interceptor.KeyGenerator接口,并使用该参数来指定。需要注意的是:该参数与key是互斥的 cacheManager:用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用 cacheResolver:用于指定使用那个缓存解析器,非必需。需通过org.springframework.cache.interceptor.CacheResolver接口来实现自己的缓存解析器,并用该参数指定。

除了上面的两个注解外,还有一些其他的注解。

@Cacheput:既调用方法,又更新缓存数据。也就是修改数据库的某个数据,同时更新缓存。步骤:先运行方法,再将目标结果缓存起来。

如果需要使用该注解,不仅需要加入注解,还需要设置注解的key的值需要和查询出来的key一致,否则不会改变cache缓存中的数据。

@CacheEvict:清除缓存。使用key删除缓存数据。

特有的两个属性:

allEntries=true,代表不论清除哪个key,都重新刷新缓存 beforeInvocation=true.方法执行前,清空缓存,无论发不发生异常,都会清除缓存。false则是方法执行后,情况缓存。默认是false,如果程序异常,就不会清除缓存。

使用Redis做集中式缓存

默认的缓存是在内存中定义HashMap,在实际的开发生产中,经常使用Redis作为缓存中间件,而不使用cache。

Redis是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。也是以key-value的形式进行存储数据的一款非关系型数据库。

步骤:

1、安装Redis:将安装redis在虚拟机中(docker)。推荐去docker中国中去下载。

#拉取redis镜像 dockerpullredis #启动redis,并对外发开,使外部可以连接到虚拟机中的rdeis dockerrun-d-p6379:6379--nameredis01bfcb1f6df2db

安装后可以使用RedisDesktopManager管理工具去管理redis。

2、Redis的Tempate

Redis的常用五大数据类型

String【字符串】、List【列表】、Set【集合】、Hash【散列】、ZSet【有序集合】

分为两种一种是StringRedisTemplate,另一种是RedisTemplate

根据不同的数据类型,大致的操作也分为这5种,以StringRedisTemplate为例

tringRedisTemplate.opsForValue()--String stringRedisTemplate.opsForList()--List stringRedisTemplate.opsForSet()--Set stringRedisTemplate.opsForHash()--Hash stringRedisTemplate.opsForZset()-Zset

a.导入Redis依赖

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

b.修改配置文件

spring.redis.host=192.168.1.125

3.添加测试类

@Autowired StringRedisTemplatestringRedisTemplate;//操作字符串【常用】 @Autowired RedisTemplateredisTemplate;//操作k-v都是对象 @Test publicvoidtest01(){ //stringRedisTemplate.opsForValue().append("msg","hello"); Stringmsg=stringRedisTemplate.opsForValue().get("msg"); System.out.println(msg); }

我们需要做的配置和测试到这里就已经完成了。

并且SpringBoot会在侦测到存在Redis的依赖并且Redis的配置是可用的情况下,还可以使用RedisCacheManager初始化CacheManager。

3、保存对象

如果要直接保存对象,需要使用JDK序列化机制,现将对象序列化后再近些保存Redis中。

将对象转换成JSON格式,存储到Redis中。

第一种方式:自己将对象转换成JSON。(fastJson) 第二种方式:新建一个Redis的配置类MyRedisConfig。(redisTemplate中默认改变的序列化规则)

@Configuration publicclassMyRedisConfig{ @Bean publicRedisTemplate<Object,Employee>empRedisTemplate( RedisConnectionFactoryredisConnectionFactory) throwsUnknownHostException{ RedisTemplate<Object,Employee>template=newRedisTemplate<Object,Employee>(); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializerjsonRedisSerializer=newJackson2JsonRedisSerializer(Employee.class); template.setDefaultSerializer(jsonRedisSerializer); returntemplate; }

本文内容总结:SpringBoot中的Cache缓存,1、基本概念,2、整合项目,Cache注解,使用Redis做集中式缓存,

原文链接:https://www.cnblogs.com/JiangLai/p/9999811.html