使用SpringBoot實現(xiàn)Redis多數(shù)據(jù)庫緩存
Redis多數(shù)據(jù)庫存儲實現(xiàn)用戶行為緩存
在我的系統(tǒng)中,為了優(yōu)化用戶行為數(shù)據(jù)的存儲與訪問效率,我引入了Redis緩存,并將數(shù)據(jù)分布在不同的Redis數(shù)據(jù)庫中。通過這種方式,可以減少單一數(shù)據(jù)庫的負載,提高系統(tǒng)的整體性能。
主要實現(xiàn)步驟
Redis配置
- 配置兩個Redis連接工廠,分別用于存儲Token和用戶行為數(shù)據(jù)。
- 創(chuàng)建對應(yīng)的RedisTemplate實例,指定不同的連接工廠及序列化方式。
用戶行為服務(wù)
- 通過
UserBehaviorService
接口及其實現(xiàn)類UserBehaviorServiceImpl
,實現(xiàn)對用戶點贊、收藏、評論、瀏覽行為的記錄。 - 在操作數(shù)據(jù)庫的同時,將用戶行為數(shù)據(jù)存儲到Redis中以提高讀取效率。
- 通過
Token攔截器
- 使用
TokenInterceptor
類在每次請求前驗證Token。 - 驗證通過后,將用戶信息存儲到
ThreadLocal
中,供后續(xù)操作使用。
- 使用
代碼實現(xiàn)
Redis配置類
@Configuration public class RedisConfig { @Value("${spring.data.redis.host}") private String redisHost; @Value("${spring.data.redis.port}") private int redisPort; @Value("${spring.data.redis.password}") private String redisPassword; @Bean(name = "tokenRedisConnectionFactory") public RedisConnectionFactory tokenRedisConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort); config.setPassword(redisPassword); config.setDatabase(0); return new LettuceConnectionFactory(config); } @Bean(name = "userBehaviorRedisConnectionFactory") public RedisConnectionFactory userBehaviorRedisConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(redisHost, redisPort); config.setPassword(redisPassword); config.setDatabase(1); return new LettuceConnectionFactory(config); } @Bean(name = "redisTemplate") public StringRedisTemplate redisTemplate(@Qualifier("tokenRedisConnectionFactory") RedisConnectionFactory redisConnectionFactory) { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new StringRedisSerializer()); return template; } @Bean(name = "userBehaviorRedisTemplate") public RedisTemplate<String, Map<String, Integer>> userBehaviorRedisTemplate(@Qualifier("userBehaviorRedisConnectionFactory") RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Map<String, Integer>> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Map.class)); return template; } }
用戶行為服務(wù)實現(xiàn)類
@Service public class UserBehaviorServiceImpl implements UserBehaviorService { private static final long CACHE_EXPIRATION_DAYS = 1; private static final String CACHE_PREFIX = "articleCounts:"; @Autowired private UserBehaviorMapper userBehaviorMapper; @Autowired @Qualifier("userBehaviorRedisTemplate") private RedisTemplate<String, Map<String, Integer>> userBehaviorRedisTemplate; @Override public void setLikeArticle(Likes likes) { likes.setCreateTime(LocalDateTime.now()); Integer userId = ThreadLocalUtil.getUser("id"); if (userId != null) { likes.setUserId(userId); } userBehaviorMapper.insertLike(likes); } @Override public void setFavoriteArticle(Favorites favorites) { favorites.setCreateTime(LocalDateTime.now()); Integer userId = ThreadLocalUtil.getUser("id"); if (userId != null) { favorites.setUserId(userId); } userBehaviorMapper.insertFavorite(favorites); } @Override public void setCommentArticle(Comments comments) { comments.setCreateTime(LocalDateTime.now()); Integer userId = ThreadLocalUtil.getUser("id"); if (userId != null) { comments.setUserId(userId); } userBehaviorMapper.insertComment(comments); } @Override public void setViewArticle(Views views) { views.setCreateTime(LocalDateTime.now()); Integer userId = ThreadLocalUtil.getUser("id"); if (userId != null) { views.setUserId(userId); } userBehaviorMapper.insertView(views); } @Override public Map<String, Integer> getArticleCounts(Integer articleId) { String key = CACHE_PREFIX + articleId; Map<String, Integer> counts = userBehaviorRedisTemplate.opsForValue().get(key); if (counts == null) { counts = fetchArticleCountsFromDB(articleId); cacheArticleCounts(articleId, counts); } return counts; } private Map<String, Integer> fetchArticleCountsFromDB(Integer articleId) { Map<String, Integer> counts = new HashMap<>(); counts.put("likesCount", userBehaviorMapper.selectLikesCount(articleId)); counts.put("favoritesCount", userBehaviorMapper.selectFavoritesCount(articleId)); counts.put("commentsCount", userBehaviorMapper.selectCommentsCount(articleId)); counts.put("viewsCount", userBehaviorMapper.selectViewsCount(articleId)); return counts; } private void cacheArticleCounts(Integer articleId, Map<String, Integer> counts) { String key = CACHE_PREFIX + articleId; userBehaviorRedisTemplate.opsForValue().set(key, counts, CACHE_EXPIRATION_DAYS, TimeUnit.DAYS); } }
Token攔截器
@Component public class TokenInterceptor implements HandlerInterceptor { @Autowired private StringRedisTemplate redisTemplate; @Override public boolean preHandle(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception { String token = request.getHeader("Authorization"); if (token == null || token.isEmpty()) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); return false; } try { ValueOperations<String, String> operations = redisTemplate.opsForValue(); String redisToken = operations.get(token); if (redisToken == null) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); return false; } Map<String, Object> claims = JwtUtil.parseToken(token); ThreadLocalUtil.setUser(claims); return true; } catch (Exception e) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); return false; } } @Override public void postHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, Exception ex) throws Exception { ThreadLocalUtil.remove(); } }
到此這篇關(guān)于使用SpringBoot實現(xiàn)Redis多數(shù)據(jù)庫緩存的文章就介紹到這了,更多相關(guān)SpringBoot Redis數(shù)據(jù)緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實現(xiàn)解壓zip壓縮包的兩種方法(支持多層級)
壓縮文件在生活中經(jīng)常能用到,在Java中提供了壓縮和解壓縮文件的功能,本文主要介紹了Java實現(xiàn)解壓zip壓縮包的兩種方法(支持多層級),感興趣的可以了解一下2024-03-03SpringBoot實現(xiàn)微服務(wù)通信的多種方式
微服務(wù)通信是指在分布式系統(tǒng)中,各個微服務(wù)之間進行數(shù)據(jù)交互和通信的過程,今天我們將探討在Spring Boot中實現(xiàn)微服務(wù)通信的多種方式,文章通過代碼示例給大家介紹的非常詳細,需要的朋友可以參考下2024-07-07Java利用條件運算符的嵌套來完成學(xué)習(xí)成績的劃分
這篇文章主要介紹了Java利用條件運算符的嵌套來完成學(xué)習(xí)成績的劃分,需要的朋友可以參考下2017-02-02