由於資料字典的變化不是很頻繁,而且系統對資料字典的存取較頻繁,所以我們有必要把資料字典的資料存入緩存,減少資料庫壓力和提高存取速度。這裡,我們使用Redis作為系統的分散式快取中間件。
在Spring Boot專案中,預設整合Spring Data Redis,Spring Data Redis針對Redis提供了非常方便的操作模版RedisTemplate,並且可以進行連接池自動管理。
service-base模組中加入redis依賴,Spring Boot 2.0以上預設透過commons-pool2連線池連接Redis
<!-- spring boot redis缓存引入 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- 缓存连接池--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- redis 存储 json序列化 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency>
service-core的application.yml 中新增以下設定
cd /usr/local/redis-5.0.7#spring:
##啟動服務
redis:
。 # lettuce:
pool:
max-active: 20 #最大連結數,負值表示沒有限制,預設8
max-wait: -1 等待限制#p max-wait: -1 等待值預設-1
max-idle: 8 #最大閒置連接,預設為8
min-idle: 0 #最小閒置連接,預設0
Red#S##Red#Red#S##Red#S#Red#S#Red#如果服務服務服務#3、啟動服務服務。
遠端連接Linux伺服器,這裡本機使用centos虛擬機器上的redis
發現RedisTemplate默認使用了JDK的序列化方式儲存了key和value,可讀性差1、存值測試
test中建立測試類別RedisTemplateTests@SpringBootTest @RunWith(SpringRunner.class) public class RedisTemplateTests { @Resource private RedisTemplate redisTemplate; @Resource private DictMapper dictMapper; @Test public void saveDict(){ Dict dict = dictMapper.selectById(1); //向数据库中存储string类型的键值对, 过期时间5分钟 redisTemplate.opsForValue().set("dict", dict, 5, TimeUnit.MINUTES); } }
#2、Redis設定檔
service-base中加入RedisConfig,我們可以在這個設定檔中配置Redis序列化方案
@Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); //首先解决key的序列化方式 StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(stringRedisSerializer); //解决value的序列化方式 Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); //序列化时将类的数据类型存入json,以便反序列化的时候转换成正确的类型 ObjectMapper objectMapper = new ObjectMapper(); //objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); // 解决jackson2无法反序列化LocalDateTime的问题 objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.registerModule(new JavaTimeModule()); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); return redisTemplate; } }
再次測試,key使用了字串存儲,value使用了json存儲
##3、取值測試@Test public void getDict(){ Dict dict = (Dict)redisTemplate.opsForValue().get("dict"); System.out.println(dict); }四、將資料字典存入redisDictServiceImpl
注意:當redis伺服器宕機時,我們不要拋出異常,要正常的執行後面的流程,使業務可以正常的運行
@Resource private RedisTemplate redisTemplate; @Override public List<Dict> listByParentId(Long parentId) { //先查询redis中是否存在数据列表 List<Dict> dictList = null; try { dictList = (List<Dict>)redisTemplate.opsForValue().get("srb:core:dictList:" + parentId); if(dictList != null){ log.info("从redis中取值"); return dictList; } } catch (Exception e) { log.error("redis服务器异常:" + ExceptionUtils.getStackTrace(e));//此处不抛出异常,继续执行后面的代码 } log.info("从数据库中取值"); dictList = baseMapper.selectList(new QueryWrapper<Dict>().eq("parent_id", parentId)); dictList.forEach(dict -> { //如果有子节点,则是非叶子节点 boolean hasChildren = this.hasChildren(dict.getId()); dict.setHasChildren(hasChildren); }); //将数据存入redis try { redisTemplate.opsForValue().set("srb:core:dictList:" + parentId, dictList, 5, TimeUnit.MINUTES); log.info("数据存入redis"); } catch (Exception e) { log.error("redis服务器异常:" + ExceptionUtils.getStackTrace(e));//此处不抛出异常,继续执行后面的代码 } return dictList; }
(2)配置redis連接資訊;
(3)測試連接,取值測試,存值測試;
(4)依照自己的需求配置序列化器,否則預設使用jdk的序列化器。
redis業務總結:
(1)首先查詢redis中有無對應的快取信息,有的話取出直接返回,沒有執行(2),如果redis因為某種原因連接不上例如宕機,此時列印錯誤日誌,繼續查詢資料庫;
(2)沒有的話查詢資料庫,將資料存放進redis並回傳資料。
以上是Redis快取實例程式碼分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!