实验中心网站建设,湖南官网网站推广软件,龙岩建设网站,网站推广全过程SpringBoot操作Redis缓存
Redis有很多使用场景#xff0c;一个使用场景就是缓存数据库的数据。Redis作为一个内存数据库#xff0c;存取数据的速度比传
统的数据库快得多。使用Redis缓存数据库数据#xff0c;可以减轻系统对数据库的访问压力#xff0c;及加快查询效率等…SpringBoot操作Redis缓存
Redis有很多使用场景一个使用场景就是缓存数据库的数据。Redis作为一个内存数据库存取数据的速度比传
统的数据库快得多。使用Redis缓存数据库数据可以减轻系统对数据库的访问压力及加快查询效率等好处。下
面讲解如何使用 SpringBoot Redis来缓存数据库数据(这里数据库使用MySql)。
Spring支持多种缓存技术RedisCacheManager、EhCacheCacheManager、GuavaCacheManager等使用之
前需要配置一个CacheManager的Bean。配置好之后使用三个注解来缓存数据CacheableCachePut 和
CacheEvict。这三个注解可以加Service层或Dao层的类名上或方法上(建议加在Service层的方法上)加上类上
表示所有方法支持该注解的缓存三注解需要指定Key以返回值作为value操作缓存服务。所以如果加在Dao
层当新增1行数据时返回数字1会将1缓存到Redis而不是缓存新增的数据。
1、使用的数据库脚本
create database redis_cache_test;
use redis_cache_test;
CREATE TABLE sys_user (t_id varchar(32) NOT NULL COMMENT ID编号,t_name varchar(300) DEFAULT NULL COMMENT 用户姓名,t_age int(11) DEFAULT NULL COMMENT 用户年龄,PRIMARY KEY (t_id)
) ENGINEInnoDB DEFAULT CHARSETutf8;
INSERT INTO sys_user VALUES (ID0001, zsx1, 27);
INSERT INTO sys_user VALUES (ID0002, zsx2, 27);
INSERT INTO sys_user VALUES (ID0003, zsx3, 27);
INSERT INTO sys_user VALUES (ID0004, zsx4, 27);
INSERT INTO sys_user VALUES (ID0005, zsx5, 18);
INSERT INTO sys_user VALUES (ID0006, zsx6, 12);
INSERT INTO sys_user VALUES (ID0007, zsx7, 8);2、引入pom依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.4.5/versionrelativePath//parentgroupIdcom.example/groupIdartifactIdspring-boot-redis-cache/artifactIdversion0.0.1-SNAPSHOT/versionnamespring-boot-redis-cache/namedescriptionspring-boot-redis-cache/descriptionpropertiesjava.version1.8/java.version/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion2.0.1/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdscoperuntime/scope/dependencydependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-core/artifactIdversion2.9.6/version/dependencydependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-annotations/artifactIdversion2.9.6/version/dependencydependencygroupIdcom.fasterxml.jackson.core/groupIdartifactIdjackson-databind/artifactIdversion2.9.6/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdscopetest/scope/dependency/dependenciesbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build/project3、配置文件
# Redis数据库索引默认为0
spring.redis.database0
# Redis服务器地址
spring.redis.host127.0.0.1
# Redis服务器连接端口
spring.redis.port6379
# Redis服务器连接密码默认为空
spring.redis.password
# 连接池最大连接数使用负值表示没有限制
spring.redis.jedis.pool.max-active10
# 连接池最大阻塞等待时间使用负值表示没有限制
spring.redis.jedis.pool.max-wait-1ms
# 连接池中的最大空闲连接
spring.redis.jedis.pool.max-idle10
# 连接池中的最小空闲连接
spring.redis.jedis.pool.min-idle0
# 连接超时时间毫秒
spring.redis.timeout1000mslogging.level.rootERROR
spring.datasource.driverClassNamecom.mysql.cj.jdbc.Driver
spring.datasource.urljdbc:mysql://127.0.0.1:3306/redis_cache_test?characterEncodingutf8serverTimezoneUTC
spring.datasource.usernameroot
spring.datasource.passwordroot4、实体类User
package com.example.springbootrediscache.redis;/*** 简单的bean对应DB的表*/
public class User {public User() {}public User(String id, String name, int age) {this.id id;this.name name;this.age age;}Overridepublic String toString() {return User [id id , name name , age age ];}private String id;private String name;private int age;public String getId() {return id;}public void setId(String id) {this.id id;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}
}5、UserDao
package com.example.springbootrediscache.redis;import org.apache.ibatis.annotations.*;
import org.springframework.stereotype.Component;import java.util.List;Mapper
Component
public interface UserDao {/*** 插入数据** param bean* return*/Insert(insert into sys_user (t_id, t_name, t_age) values (#{id}, #{name}, ${age}) )int insertUser(User bean);/*** 查询所有数据** return*/ResultMap(redisUserDaoResults)Select(select t_id, t_name, t_age from sys_user )ListUser selectUser();/*** 根据id查询数据** param id* return*/Select(select t_id, t_age, t_name from sys_user where t_id #{id} )Results(id redisUserDaoResults, value {Result(property id, column t_id),Result(property age, column t_age),Result(property name, column t_name),})User selectUserById(Param(id) String id);/*** 根据id修改数据** param user* return*/Update(update sys_user set t_name #{name}, t_age #{age} where t_id #{id} )int updateUser(User user);/*** 根据id删除数据** param id* return*/Delete(delete from sys_user where t_id #{id} )int deleteUserById(Param(id) String id);}6、RedisCacheUserDao
可以在Dao和Service任何一处使用缓存
package com.example.springbootrediscache.redis;import org.apache.ibatis.annotations.*;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;import java.util.List;Component
Mapper
CacheConfig(cacheNames users)
public interface RedisCacheUserDao {// https://blog.csdn.net/f641385712/article/details/95169002Cacheable(key #a0)Select(select t_id, t_age, t_name from sys_user where t_id #{id} )Results(id redisUserDaoResults, value {Result(property id, column t_id),Result(property age, column t_age),Result(property name, column t_name),})User selectUserById(Param(id) String id);Cacheable(key list)ResultMap(redisUserDaoResults)Select(select t_id, t_name, t_age from sys_user )ListUser selectUser();
}7、RedisCacheUserService
package com.example.springbootrediscache.redis;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;import java.util.List;/*** 指定默认缓存区* 缓存区key的前缀与指定的key构成redis的key如 user::10001*/
CacheConfig(cacheNames user)
Service
public class RedisCacheUserService {Autowiredprivate UserDao dao;/*** Cacheable 缓存有数据时从缓存获取没有数据时将返回值保存到缓存中* Cacheable 一般在查询中使用* 1) cacheNames 指定缓存区没有配置使用CacheConfig指定的缓存区* 2) key 指定缓存区的key* 3) 注解的值使用SpEL表达式* eq * lt * le * gt * ge */Cacheable(cacheNames user, key #id)public User selectUserById(String id) {return dao.selectUserById(id);}Cacheable(key list)public ListUser selectUser() {return dao.selectUser();}/*** condition 满足条件缓存数据*/Cacheable(key #id, condition #number ge 20) // 20public User selectUserByIdWithCondition(String id, int number) {return dao.selectUserById(id);}/*** unless 满足条件时否决缓存数据*/Cacheable(key #id, unless #number lt 20) // 20public User selectUserByIdWithUnless(String id, int number) {return dao.selectUserById(id);}/*** CachePut 将返回值保存到缓存中* CachePut 一般在新增和修改中使用*/CachePut(key #user.id)public User insertUser(User user) {dao.insertUser(user);return user;}CachePut(key #user.id, condition #user.age ge 20)public User insertUserWithCondition(User user) {dao.insertUser(user);return user;}CachePut(key #user.id)public User updateUser(User user) {dao.updateUser(user);return user;}/*** 根据key删除缓存区中的数据*/CacheEvict(key #id)public void deleteUserById(String id) {dao.deleteUserById(id);}/*** allEntries true 删除整个缓存区的所有值此时指定的key无效* beforeInvocation true 默认false表示调用方法之后删除缓存数据true时在调用之前删除缓存数据(如方法出现异常)*/CacheEvict(key #id, allEntries true)public void deleteUserByIdAndCleanCache(String id) {dao.deleteUserById(id);}
}8、RedisConfig
RedisCacheManager的配置如下
package com.example.springbootrediscache.redis;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
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.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheManager.RedisCacheManagerBuilder;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;Configuration
EnableCaching
Slf4j
public class RedisConfig {/*** SpringBoot配置redis作为默认缓存工具* SpringBoot 2.0 以上版本的配置*/Beanpublic CacheManager cacheManager(RedisTemplateString, Object template) {RedisCacheConfiguration defaultCacheConfiguration RedisCacheConfiguration.defaultCacheConfig()// 设置key为String.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getStringSerializer()))// 设置value为自动转Json的Object.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(template.getValueSerializer()))// 不缓存null.disableCachingNullValues()// 缓存数据保存1小时.entryTtl(Duration.ofHours(1));RedisCacheManager redisCacheManager RedisCacheManagerBuilder// Redis 连接工厂.fromConnectionFactory(template.getConnectionFactory())// 缓存配置.cacheDefaults(defaultCacheConfiguration)// 配置同步修改或删除 put/evict.transactionAware().build();return redisCacheManager;}/*** redis templateString, Object*/Bean(name template)public RedisTemplateString, Object template(RedisConnectionFactory factory) {log.info(调用自定义的Redis Template!!!);// 创建RedisTemplateString, Object对象RedisTemplateString, Object template new RedisTemplate();// 配置连接工厂template.setConnectionFactory(factory);// 定义Jackson2JsonRedisSerializer序列化对象Jackson2JsonRedisSerializerObject jacksonSeial new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om new ObjectMapper();// 指定要序列化的域field,get和set,以及修饰符范围ANY是都有包括private和publicom.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化输入的类型类必须是非final修饰的final修饰的类比如String,Integer等会报异常om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jacksonSeial.setObjectMapper(om);StringRedisSerializer stringSerial new StringRedisSerializer();// redis key 序列化方式使用stringSerialtemplate.setKeySerializer(stringSerial);// redis value 序列化方式使用jacksontemplate.setValueSerializer(jacksonSeial);// redis hash key 序列化方式使用stringSerialtemplate.setHashKeySerializer(stringSerial);// redis hash value 序列化方式使用jacksontemplate.setHashValueSerializer(jacksonSeial);template.afterPropertiesSet();return template;}/*** 定义数据类型* string hash list set zset*//*** redis string*/Beanpublic ValueOperationsString, Object valueOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForValue();}/*** redis hash*/Beanpublic HashOperationsString, String, Object hashOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForHash();}/*** redis list*/Beanpublic ListOperationsString, Object listOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForList();}/*** redis set*/Beanpublic SetOperationsString, Object setOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForSet();}/*** redis zset*/Beanpublic ZSetOperationsString, Object zSetOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForZSet();}
}9、启动类
package com.example.springbootrediscache;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication
public class SpringBootRedisCacheApplication {public static void main(String[] args) {SpringApplication.run(SpringBootRedisCacheApplication.class, args);}}10、测试
mysql select * from sys_user;
-----------------------
| t_id | t_name | t_age |
-----------------------
| ID0001 | zsx1 | 27 |
| ID0002 | zsx2 | 27 |
| ID0003 | zsx3 | 27 |
| ID0004 | zsx4 | 27 |
| ID0005 | zsx5 | 18 |
| ID0006 | zsx6 | 12 |
| ID0007 | zsx7 | 8 |
-----------------------
7 rows in set10.1 RedisDaoCache
package com.example.springbootrediscache;import com.example.springbootrediscache.redis.RedisCacheUserDao;
import com.example.springbootrediscache.redis.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.junit4.SpringRunner;import java.util.List;SpringBootTest(classes SpringBootRedisCacheApplication.class)
RunWith(SpringRunner.class)
public class RedisDaoCache {Autowiredprivate RedisCacheUserDao dao;Autowiredprivate ValueOperationsString, Object redisString;Testpublic void test001() {System.out.println(redis before use : redisString.get(users::ID0001));System.out.println(dao.selectUserById(ID0001));System.out.println(redis after use : redisString.get(users::ID0001));}Testpublic void test002() {System.out.println(redisString.get(users::list));ListUser list dao.selectUser();System.out.println(list.size());System.out.println(redisString.get(users::list));}
}Test
public void test001() {System.out.println(redis before use : redisString.get(users::ID0001));System.out.println(dao.selectUserById(ID0001));System.out.println(redis after use : redisString.get(users::ID0001));
}redis before use : null
User [idID0001, namezsx1, age27]
redis after use : User [idID0001, namezsx1, age27]Test
public void test002() {System.out.println(redisString.get(users::list));ListUser list dao.selectUser();System.out.println(list.size());System.out.println(redisString.get(users::list));
}null
7
[User [idID0001, namezsx1, age27], User [idID0002, namezsx2, age27], User [idID0003, namezsx3, age27], User [idID0004, namezsx4, age27], User [idID0005, namezsx5, age18], User [idID0006, namezsx6, age12], User [idID0007, namezsx7, age8]]10.2 RedisServiceCache
package com.example.springbootrediscache;import com.example.springbootrediscache.redis.RedisCacheUserService;
import com.example.springbootrediscache.redis.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.junit4.SpringRunner;import java.util.List;SpringBootTest(classes SpringBootRedisCacheApplication.class)
RunWith(SpringRunner.class)
public class RedisServiceCache {Autowiredprivate RedisCacheUserService service;Autowiredprivate ValueOperationsString, Object redisString;/*** 测试 Cacheable 注解缓存bean*/Testpublic void test001() {// redis before use : null// User [idID0001, namezsx, age27]// redis after use : User [idID0001, namezsx, age27]System.out.println(redis before use : redisString.get(user::ID0001));System.out.println(service.selectUserById(ID0001));System.out.println(redis after use : redisString.get(user::ID0001));System.out.println();// redis before use : User [idID0001, namezsx, age27]// User [idID0001, namezsx, age27]// redis after use : User [idID0001, namezsx, age27]System.out.println(redis before use : redisString.get(user::ID0001));System.out.println(service.selectUserById(ID0001));System.out.println(redis after use : redisString.get(user::ID0001));System.out.println();}/*** 测试 Cacheable 注解缓存list* list指定 list字符串作为key*/Testpublic void test002() {// null// 3// [User [idID0001, namezsx1, age27], User [idID0002, namezsx2, age27], User [idID0003, namezsx3, age27]]System.out.println(redisString.get(user::list));// 如果往数据库中插入数据,依然还是会从缓存中拿出,不会拿出最新的数据ListUser list service.selectUser();System.out.println(list.size());System.out.println(redisString.get(user::list));}/*** 测试 Cacheable 注解的 condition : 满足条件时缓存数据*/Testpublic void test003() {// User [idID0002, namezsx2, age27]// redis data[ID0002] : nullUser user1 service.selectUserByIdWithCondition(ID0002, 19);System.out.println(user1);System.out.println(redis data[ID0002] : redisString.get(user::ID0002));// User [idID0003, namezsx3, age27]// redis data[ID0003]: User [idID0003, namezsx3, age27]User user2 service.selectUserByIdWithCondition(ID0003, 20);System.out.println(user2);System.out.println(redis data[ID0003]: redisString.get(user::ID0003));}/*** 测试 Cacheable 注解的 unless : 满足条件时不缓存数据*/Testpublic void test004() {// User [idID0004, namezsx4, age27]// redis data[ID0004] : nullUser user1 service.selectUserByIdWithUnless(ID0004, 19);System.out.println(user1);System.out.println(redis data[ID0004] : redisString.get(user::ID0004));// User [idID0005, namezsx5, age18]// redis data[ID0005]: User [idID0005, namezsx5, age18]User user2 service.selectUserByIdWithUnless(ID0005, 20);System.out.println(user2);System.out.println(redis data[ID0005]: redisString.get(user::ID0005));}/*** 测试 CachePut 注解*/Testpublic void test005() {User user new User(10086, insert_name, 11);service.insertUser(user);// User [id10086, nameinsert_name, age11]System.out.println(redisString.get(user::10086));User user2 new User(10087, insert_name, 22);service.insertUserWithCondition(user2);// User [id10087, nameinsert_name, age22]System.out.println(redisString.get(user::10087));User user3 new User(10086, update_name, 12);service.updateUser(user3);// User [id10086, nameupdate_name, age12]System.out.println(redisString.get(user::10086));}/*** 测试 CacheEvict 注解*/Testpublic void test006() {// [user::ID0003, user::ID0001, user::10086, user::list, user::10087, user::ID0005]System.out.println(redisString.getOperations().keys(user::*));service.deleteUserById(10086);// [user::ID0003, user::ID0001, user::list, user::10087, user::ID0005]System.out.println(redisString.getOperations().keys(user::*));service.deleteUserByIdAndCleanCache(10087);// []System.out.println(redisString.getOperations().keys(user::*));}
}