首先是添加依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>${spring-boot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId><version>${spring-boot.version}</version></dependency>
我这里用的SpringBoot版本是: 2.2.5.RELEASE
jedis与lettuce区别
1、Jedis:
在实现上是直连 Redis server,多线程环境下非线程安全,除非使用连接池,为每个 redis实例增加 物理连接。
2、Lettuce:
是 一种可伸缩,线程安全,完全非阻塞的Redis客户端,多个线程可以共享一个RedisConnection,它利用Netty NIO 框架来高效地管理多个连接,从而提供了异步和同步数据访问方式,用于构建非阻塞的反应性应用程序。
我这里项目的配置文件使用的是 Lettuce
,配置文件内容:
spring:datasource:url:jdbc:mysql://192.168.104.64:3306/spring_boot_plus?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=trueusername:rootpassword:huauN2021#Redis配置redis:database:0host:192.168.104.102password:huauN@2021port:6379timeout:6000#连接超时时长(毫秒)lettuce:pool:max-active:1024#连接池最大连接数(默认为8,-1表示无限制如果pool已经分配了超过max_active个jedis实例,则此时pool为耗尽)max-wait:10000#最大等待连接时间,单位毫秒默认为-1,表示永不超时,超时会抛出JedisConnectionExceptionmax-idle:10min-idle:5
首先是找下redis的配置类,如果没有则新增改配置类:
packagegc.cnnvd.config;importcom.fasterxml.jackson.annotation.JsonAutoDetect;importcom.fasterxml.jackson.annotation.PropertyAccessor;importcom.fasterxml.jackson.databind.ObjectMapper;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;/***<p>*RedisTemplate配置*</p>**@authorlinmengmeng*@date2021-07-21*/@ConfigurationpublicclassRedisTemplateConfig{/***redisTemplate配置*@paramfactory*@return***自定义RedisTemplate的原因:*1、修改泛型方式为<String,Object>,避免繁琐的类型转换*2、将value的序列化方式更改为Jackson2JsonRedisSerializer,因为底层的RedisSerializer序列化value时不会带双引号,而使用Jackson2JsonRedisSerializer序列化String类型时会自动添加双引号。**/@Bean@SuppressWarnings("all")publicRedisTemplate<String,Object>redisTemplate(RedisConnectionFactoryfactory){RedisTemplate<String,Object>redisTemplate=newRedisTemplate<String,Object>();redisTemplate.setConnectionFactory(factory);Jackson2JsonRedisSerializerjackson2JsonRedisSerializer=newJackson2JsonRedisSerializer(Object.class);ObjectMappermapper=newObjectMapper();//指定要序列化的域,ANY是包括public和private的mapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);//指定序列化输入的类型,类必须是非final类型的,否则会报错mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(mapper);StringRedisSerializerstringRedisSerializer=newStringRedisSerializer();//设置key采用String的序列化方式redisTemplate.setKeySerializer(stringRedisSerializer);//设置hash的key采用String的序列化方式redisTemplate.setHashKeySerializer(stringRedisSerializer);//设置value采用jackson2的序列化方式redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//设置hash的value采用jackson2的序列化方式redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);redisTemplate.afterPropertiesSet();returnredisTemplate;}}
如果之前配置过 redisTemplate
,再次新增这个配置文件启动时就会提示异常,提示redisTemplate
bean创建失败,已存在什么的。
接着是 RedisCacheConfig
:
packagegc.cnnvd.config;importorg.springframework.cache.CacheManager;importorg.springframework.cache.annotation.CachingConfigurerSupport;importorg.springframework.cache.annotation.EnableCaching;importorg.springframework.cache.interceptor.KeyGenerator;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.data.redis.cache.RedisCacheConfiguration;importorg.springframework.data.redis.cache.RedisCacheManager;importorg.springframework.data.redis.connection.RedisConnectionFactory;importorg.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;importorg.springframework.data.redis.serializer.RedisSerializationContext;importorg.springframework.data.redis.serializer.RedisSerializer;importorg.springframework.data.redis.serializer.StringRedisSerializer;importjava.time.Duration;importjava.util.Arrays;/***<p>*RedisCache配置*</p>*@authorgeekidea*@date2018-11-08*/@Configuration@EnableCachingpublicclassRedisCacheConfigextendsCachingConfigurerSupport{@Bean@OverridepublicKeyGeneratorkeyGenerator(){return(target,method,params)->{StringBufferredisKey=newStringBuffer();redisKey.append(target.getClass().getName()).append("-");redisKey.append(method.getName());if(params.length>0){redisKey.append("-").append(Arrays.deepToString(params));}returnredisKey.toString();};}/***redis缓存配置*修改序列化方式,解决缓存乱码*@paramfactory*@return*/@BeanpublicCacheManagercacheManager(RedisConnectionFactoryfactory){RedisSerializer<String>redisSerializer=newStringRedisSerializer();Jackson2JsonRedisSerializerjackson2JsonRedisSerializer=newJackson2JsonRedisSerializer(Object.class);//配置序列化RedisCacheConfigurationconfig=RedisCacheConfiguration.defaultCacheConfig();RedisCacheConfigurationredisCacheConfiguration=config//Key序列化方式redisSerializer.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))//value序列化方式jackson2JsonRedisSerializer.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))//设置前缀//.prefixKeysWith("project:")//设置过期时间.entryTtl(Duration.ofSeconds(60*60));RedisCacheManagercacheManager=RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();returncacheManager;}}
我这里直接将注解@EnableScheduling
加在配置文件这里了,如果不加这里可以直接在启动类上要加上注解:@EnableScheduling
随便找了一个 service
方法进行测试:
@Override@Cacheable(value="adminUser",key="#adminUserDetailParam.getId()",unless="#result==null")publicAdminUserDetailVOgetAdminUserDetail(AdminUserDetailParamadminUserDetailParam){AdminUserMergeradminUserMerger=adminUserMapper.selectAdminUserDetail(adminUserDetailParam.getId(),adminUserDetailParam.getVersion());log.info("------------走数据库查询-------------");if(adminUserMerger==null){thrownewBusinessException("用户信息不存在");}AdminUserDetailVOadminUserDetailVO=newAdminUserDetailVO();BeanCopierUtils.copyProperties(adminUserMerger,adminUserDetailVO);returnadminUserDetailVO;}
这里仅在原来基础上加了一行注解@Cacheable(value = "adminUser",key = "#adminUserDetailParam.getId()",unless = "#result==null")
其中value为redis的key的前缀,
importcom.alibaba.fastjson.JSONObject;importgc.cnnvd.system.adminuser.param.AdminUserDetailParam;importgc.cnnvd.system.adminuser.service.AdminUserService;importgc.cnnvd.system.adminuser.vo.AdminUserDetailVO;importgc.cnnvd.test.BaseTest;importorg.junit.Test;importorg.springframework.beans.factory.annotation.Autowired;/***@Autherlinmengmeng*@Date2021-07-2019:15*/publicclassQueryTestextendsBaseTest{@AutowiredprivateAdminUserServiceadminUserService;@TestpublicvoidtestGetAdminDetail(){AdminUserDetailParamadminUserDetailParam=newAdminUserDetailParam();adminUserDetailParam.setId("test001");adminUserDetailParam.setVersion(0);AdminUserDetailVOadminUserDetail=adminUserService.getAdminUserDetail(adminUserDetailParam);System.out.println(JSONObject.toJSONString(adminUserDetail));}}
写了测试用例后,运行发现缓存好使了,第一次会走数据库查询,第二次直接走redis缓存。
缓存内容,使用可视化工具查看如下图:
作者:linmengmeng