使用SpringBoot实现Redis多数据库缓存

 更新时间:2024年06月13日 11:29:54   作者:是行东啊  
在我的系统中,为了优化用户行为数据的存储与访问效率,我引入了Redis缓存,并将数据分布在不同的Redis数据库中,通过这种方式,可以减少单一数据库的负载,提高系统的整体性能,所以本文给大家介绍了使用SpringBoot实现Redis多数据库缓存,需要的朋友可以参考下

Redis多数据库存储实现用户行为缓存

在我的系统中,为了优化用户行为数据的存储与访问效率,我引入了Redis缓存,并将数据分布在不同的Redis数据库中。通过这种方式,可以减少单一数据库的负载,提高系统的整体性能。

主要实现步骤

  • Redis配置

    • 配置两个Redis连接工厂,分别用于存储Token和用户行为数据。
    • 创建对应的RedisTemplate实例,指定不同的连接工厂及序列化方式。
  1. 用户行为服务

    • 通过UserBehaviorService接口及其实现类UserBehaviorServiceImpl,实现对用户点赞、收藏、评论、浏览行为的记录。
    • 在操作数据库的同时,将用户行为数据存储到Redis中以提高读取效率。
  2. Token拦截器

    • 使用TokenInterceptor类在每次请求前验证Token。
    • 验证通过后,将用户信息存储到ThreadLocal中,供后续操作使用。

代码实现

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;
    }
}

用户行为服务实现类

@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();
    }
}

到此这篇关于使用SpringBoot实现Redis多数据库缓存的文章就介绍到这了,更多相关SpringBoot Redis数据缓存内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Java中的数值和集合详解

    基于Java中的数值和集合详解

    下面小编就为大家带来一篇基于Java中的数值和集合详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Java 序列化详解及简单实现实例

    Java 序列化详解及简单实现实例

    这篇文章主要介绍了 Java 序列化详解及简单实现实例的相关资料,使用序列化目的:以某种存储形式使自定义对象持久化,将对象从一个地方传递到另一个地方,需要的朋友可以参考下
    2017-03-03
  • 详解Java的Hibernate框架中的缓存与二级缓存

    详解Java的Hibernate框架中的缓存与二级缓存

    这篇文章主要介绍了Java的Hibernate框架中的缓存与二级缓存,Hibernate是Java的SSH三大web开发框架之一,需要的朋友可以参考下
    2015-12-12
  • Java实现PDF文件的分割与加密功能

    Java实现PDF文件的分割与加密功能

    这篇文章主要为大家分享了如何利用Java语言实现PDF文件的分割与加密以及封面图的生成,文中的示例代码简洁易懂,感兴趣的可以了解一下
    2022-04-04
  • Java实现解压zip压缩包的两种方法(支持多层级)

    Java实现解压zip压缩包的两种方法(支持多层级)

    压缩文件在生活中经常能用到,在Java中提供了压缩和解压缩文件的功能,本文主要介绍了Java实现解压zip压缩包的两种方法(支持多层级),感兴趣的可以了解一下
    2024-03-03
  • SpringBoot实现微服务通信的多种方式

    SpringBoot实现微服务通信的多种方式

    微服务通信是指在分布式系统中,各个微服务之间进行数据交互和通信的过程,今天我们将探讨在Spring Boot中实现微服务通信的多种方式,文章通过代码示例给大家介绍的非常详细,需要的朋友可以参考下
    2024-07-07
  • Java开发之ssm三大框架整合

    Java开发之ssm三大框架整合

    SSM框架是spring MVC ,spring和mybatis框架的整合,是标准的MVC模式,将整个系统划分为表现层,controller层,service层,DAO层四层,使用spring MVC负责请求的转发和视图管理,spring实现业务对象管理,mybatis作为数据对象的持久化引擎
    2022-05-05
  • Java利用条件运算符的嵌套来完成学习成绩的划分

    Java利用条件运算符的嵌套来完成学习成绩的划分

    这篇文章主要介绍了Java利用条件运算符的嵌套来完成学习成绩的划分,需要的朋友可以参考下
    2017-02-02
  • SpringBoot配置类编写过程图解

    SpringBoot配置类编写过程图解

    这篇文章主要介绍了SpringBoot配置类编写过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 解决JDBC Connection Reset的问题分析

    解决JDBC Connection Reset的问题分析

    这篇文章主要介绍了解决JDBC Connection Reset的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04

最新评论