Springboot+Redis实现分布式缓存详细教程(附源码下载)

Springboot-cli 开发脚手架系列

Springboot系列:Springboot+Redis优雅的实现分布式缓存(redisTemplate及Annotation)



前言

致力于让开发者快速搭建基础环境并让应用跑起来,并提供使用示例供使用者参考,快速上手。
本博客项目源码地址:

1. 环境

  • 引入依赖pom.xml
     <!--   spring boot data redis 依赖 (需要配合 commons-pool2 对象池依赖使用)     -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--    session存储进redis共享,配合nginx直接实现分布式部署,简单粗暴(可选包)    -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <!-- 对象池依赖 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.10.0</version>
        </dependency>
  • application.yml
spring:
  # redis 配置
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    #连接超时时间
    timeout: 3000
    password: 123456
    #连接池配置
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0
        max-wait: -1

2. 配置redisTemplate

  • 编写RedisConfig.java配置,配置序列化方式
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    /**
     * RedisTemplate 默认使用 jdk 序列化,存在乱码等问题,将 value 的序列化方式换为 Jackson 后,value 中不再出现乱码。
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(RedisSerializer.string());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setEnableTransactionSupport(true);
        return template;
    }
}
  • 封装RedisUtils.java
/**
 * Redis工具类
 */
@Component
@Slf4j
public class RedisUtils {

    @Resource
    private RedisTemplate<String, Object> rt;

    private static RedisTemplate<String, Object> redisTemplate;

    @PostConstruct
    public void init() {
        // bean赋值给静态变量
        redisTemplate = rt;
    }

    /**
     * 存储
     *
     * @param cacheKey     缓存key
     * @param value   值
     * @param timeout 超时时间 秒
     */
    public static void save(String cacheKey, Object value, long timeout) {
        redisTemplate.opsForValue().set(cacheKey, value, timeout, TimeUnit.SECONDS);
    }

    public static void save(String cacheKey, Object value) {
        save(cacheKey, value, -1);
    }

    /**
     * 获取
     *
     * @param cacheKey 缓存key
     * @param c   返回值类型
     * @return c类型的对象
     */
    public static <T> T get(String cacheKey, Class<T> c) {
        Object o = redisTemplate.opsForValue().get(cacheKey);
        return JSON.parseObject(JSON.toJSONString(o), c);
    }

    /**
     * 缓存是否存在
     *
     * @param cacheKey 缓存key
     * @return true 存在
     */
    public static boolean hasKey(String cacheKey) {
        return Boolean.TRUE.equals(redisTemplate.hasKey(cacheKey));
    }

    /**
     * 添加到set集合
     *
     * @param cacheKey 缓存key
     * @param value  值 一个或多个
     */
    public static void addForSet(String cacheKey, Object... value) {
        redisTemplate.opsForSet().add(cacheKey, value);
    }

    /**
     * 获取set集合
     *
     * @param cacheKey 缓存
     * @param c      返回值类型
     * @return c类型的set集合
     */
    public static <T> Set<T> getForSet(String cacheKey, Class<T> c) {
        Set<Object> set = redisTemplate.boundSetOps(cacheKey).members();
        if (Objects.isNull(set)) {
            return null;
        }
        return set.stream().map(o -> JSON.parseObject(JSON.toJSONString(o), c)).collect(Collectors.toSet());
    }

    /**
     * 设置过期时间
     *
     * @param cacheKey    缓存 key
     * @param timeout 过期时间(秒)
     */
    public static void expire(String cacheKey, long timeout) {
        redisTemplate.expire(cacheKey, timeout, TimeUnit.MINUTES);
    }

    /**
     * 删除指定缓存
     *
     * @param cacheKey 缓存key
     */
    public static Boolean delete(String cacheKey) {
        return redisTemplate.delete(cacheKey);
    }

    /**
     * 指定元素删除
     *
     * @param cacheKey  缓存
     * @param objKey 集合元素
     */
    public static void remove(String cacheKey,String objKey) {
        redisTemplate.boundSetOps(cacheKey).remove(objKey);
    }

}

3. 编写实体,并实现序列化接口

  • User.java
@Data
@Accessors(chain = true)
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    /**
     * 用户id
     */
    private Long userId;

    /**
     * 用户名
     */
    private String username;

    /**
     * 性别
     */
    private String sex;

    /**
     * 备注
     */
    private String remark;
}
  • 注意:实体一定要加上序列化
    在这里插入图片描述

4. 测试手动存储

  • 编写测试接口
@RestController
@RequiredArgsConstructor
public class IndexController {
    /**
     * 手动设置缓存
     */
    @GetMapping("/set")
    public String set() {
        RedisUtils.save("key", new User().setUserId(999L).setSex("男").setUsername("王小锤"), 6000);
        return "设置成功 !";
    }

    /**
     * 手动获取缓存
     */
    @GetMapping("/get")
    public User get() {
        return RedisUtils.get("key", User.class);
    }
}
  • 启动项目浏览器输入ip+端口+/set 添加缓存
    在这里插入图片描述

  • ip+端口+/get 获取缓存
    在这里插入图片描述

5. 注解方式实现

  • 在前面配置RedisConfig.java中加入如下配置
   /**
     * 此处重写·springboot注解方式·缓存的Key生成规则
     * key=包+方法名+参数
     */
    @Override
    @Bean
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object obj : params) {
                sb.append(Objects.nonNull(obj) ? obj.toString() : "null");
            }
            System.out.println(sb);
            return sb.toString();
        };
    }

    /**
     * 此处重写·springboot注解方式·缓存的序列化方式及有效时间
     * key=包+方法名+参数
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                // 将::改写为一个:
                .computePrefixWith(cacheName -> cacheName + ":")
                // 设置缓存有效期24小时
                .entryTtl(Duration.ofHours(24))
                // 禁止空值
                .disableCachingNullValues()
                // 设置序列化规则
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        return RedisCacheManager.builder(connectionFactory)
                .cacheDefaults(cacheConfiguration)
                .build();
    }
  • 编写service 接口层
  • IUserService.java
public interface IUserService {
    /**
     * 缓存测试
     *
     * @param id 用户id 随便输入
     * @return 用户数据
     */
    User getUser(Long id);

    /**
     * 删除缓存测试
     *
     * @param id 用户id 随便输入
     */
    void delUser(Long id);
}
  • 编写实现类UserServiceImpl.java,模拟数据库存储
  • 在我们需要用缓存的方法上添加@Cacheable(value = "user-key")
  • 需要刷新缓存的地方添加@CacheEvict(value = "user-key", allEntries = true)
@Service
@Slf4j
public class UserServiceImpl implements IUserService {

    @Override
    @Cacheable(value = "user-key")
    public User getUser(Long id) {
        return this.getUserInfo(id);
    }

    @Override
    @CacheEvict(value = "user-key", allEntries = true)
    public void delUser(Long id) {
        this.delUserInfo(id);
    }

    public void delUserInfo(Long id) {
        log.info("删除{}用户数据执行了!!", id);
    }

    /**
     * 模拟数据库查询
     */
    private User getUserInfo(Long id) {
        log.info("获取用户数据执行了!!");
        return new User().setUserId(id).setUsername("王小锤").setSex("男").setRemark("注解方式aop实现缓存");
    }
}
  • 效果
    观察控制台我们可以发现,当我们查询的id一样时,只有第一次会触发getUserInfo方法,之后就会走缓存进行获取,只有当id不一样时,才会从新去调用getUserInfo方法。
    在这里插入图片描述

6. 源码分享

本项目已收录

  • Springboot-cli开发脚手架,集合各种常用框架使用案例,完善的文档,致力于让开发者快速搭建基础环境并让应用跑起来,并提供丰富的使用示例供使用者参考,快速上手。
  • 项目源码github地址
  • 项目源码国内gitee地址
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
【资源说明】 1、基于SpringBoot+Hadoop+Vue开发的企业级网盘分布式系统源码+项目说明(本科毕设).zip 2、该资源包括项目的全部源码下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 4、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于SpringBoot+Hadoop+Vue开发的企业级网盘分布式系统源码+项目说明(本科毕设).zip # 基于SpringCloud+Hadoop+Vue的企业级网盘系统设计与实现 ## 二、总体设计 #### 2.1 运行环境 ```lua 编程语言:Java、Mybatis、SpringSpringBootSpringCloud、Node、Vue 开发环境:Windows 10 + Mysql 开发工具:WebStorm、IDEA编译器、Git、Maven 应用部署服务器:SpringBoot内置Tomcat插件 Node服务器:Node v10.15.3 数据库:Mysql v5.5.59 缓存服务:Redis v2.8.9 代码仓库管理系统:GitHub 服务器环境:处理器Core i5以上 ``` #### 2.2 基本处理流程 企业网盘系统的使用者分为企业普通员工和企业管理员,所以进行的基本处理流程是不一样的。企业普通员工进入本系统前台主界面后看到的是首页数据大盘,系统右上角有用户的头像和系统公告通知。在首页顶部的位置有个欢迎用户功能,此模块会根据用户登录的时间,人性化的对用户进行打招呼,比如用户深夜的时候登陆系统,该提示语会提醒“已经深夜了,你还在加班吗,请注意休息!”。当用户点击我的网盘模块后,系统首先会请求一次接口,展示自己网盘里面的文件,该用户可以对文件进行相关的操作。在分享模块中,用户可以选择不同的tab栏,分别对已共享、已接收的文件进行查看。当用户进入存储库模块时,单击不同的文档分类以查看已分类的文档,可以对文件进行查询,预览和下载。系统管理员发布通知后,系统前台会在系统右上角进行消息条数的提醒,点击消息红点后,会出现通知下拉列表框,再点击下拉列表里面的查看更多,可以进入更多模块下的系统公告列表页面,在该页面里面,用户可以通过标题关键字,公告发布的时间范围进行搜索,在更多模块下用户可以动态切换系统主题,然后让用户无感知的记录用户行为,当用户退出登录后重新登录,系统的主题还是用户退出登录时所选择的主题。 管理员和超级管理员成功登入系统后台后,默认会调到Index页面去,在该首页,我们可以看到登录用户、服务器运行相关信息。在数据大盘模块,可以看到最近上传文件的数量,以及最近一段时间的上传曲线图。系统超级管理员可以管理系统所有的功能和所有用户,如果需要控制系统用户能访问的菜单,系统管理员只需更改相关角色所拥有的菜单列表。 ![img](https://raw.githubusercontent.com/chenxingxing6/cxx-graduation/master/img/1.png) #### 2.3 模块结构 基于SpringCloud+Hadoop+Vue企业网盘系统主要分为前台和后台两大模块,前台模块分为首页,网盘,分享,资源库,关注用户,系统公告模块,不同的功能模块拥有的功能也是不相同的。此外,所需权限也不同。后台模块分为用户、部门、角色、网盘、日志、系统监控、接口文档、定时任务模块。在网络磁盘管理模块中,管理员可以上传、删除和修改文档,管理员还可以在线查看多媒体资源,如Word文档、视频、音乐、图片。 ![img](https://raw.githubusercontent.com/chenxingxing6/cxx-graduation/master/img/2.png) ![img](https://raw.githubusercontent.com/chenxingxing6/cxx-graduation/master/img/3.png) #### 2.4 内部微服务调用流程图 ![img](https://raw.githubusercontent.com/chenxingxing6/cxx-graduation/master/img/4.png) --- ## 三、系统架构 ![img](https://raw.githubusercontent.com/chenxingxing6/cxx-graduation/master/img/5.png) 数据库:20张表 ```lua 1.sys_config: 系统配置信息表 2.sys
【资源说明】 1、基于springboot+vue前后端分离的小型电商系统源码+项目说明.zip 2、该资源包括项目的全部源码下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 4、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于springboot+vue前后端分离的小型电商系统源码+项目说明.zip # lite_shop微商铺 基于springboot + vue前后端分离的完整小型电商系统 ## 项目介绍 lite_shop是一套小型电商系统,该项目为B2C模式电商系统,包括前台商城系统和后台管理系统,基于springboot + vue打造。后台管理系统包含会员管理、商品管理、订单管理、运营管理、系统管理、统计报表、后台用户管理、权限管理、系统设置等模块。前台管理系统包含首页、商品推荐、商品搜索、专题推荐、用户下单、支付等一套完整电商流程。 ![11644241501_.pic.jpg](https://s2.loli.net/2022/02/07/KQeqcARCNtpTB65.jpg) ![21644241502_.pic.jpg](https://s2.loli.net/2022/02/07/8lxZvDRi2HJW4PC.jpg) ![后台截图1.png](https://i.loli.net/2020/09/20/YPAkIb32zMHXvFr.png) ![后台截图2.png](https://i.loli.net/2020/09/20/IRp7HblznxMUvoB.png) 前台商城系统 敬请期待...... ## 项目架构 ![lite_shop架构.jpg](https://i.loli.net/2020/09/20/73PWtHj2cUqh1XL.png) ## 技术栈 后端技术 | 技术 | 说明 | 版本 | | :--------------------: | :----------------- | :----: | | SpringBoot | web容器+MVC框架 | 2.3.0 | | SpringSecurity | 身份认证与授权 | 5.2.4 | | Mybati-Plus | orm框架 | 3.2.0 | | mybatis-plus-generator | 持久层代码生成器 | 3.2.0 | | Redis | 分布式缓存 | 4.0.10 | | MySQL | 数据库 | 5.7.28 | | jjwt | JWT支持 | 0.9.0 | | 七牛云 | 对象存储 | 7.2.0 | | hutool | 工具包 | 5.3.8 | | elasticsearch | 分布式全文搜索引擎 | 7.6.2 | | RabbitMQ | 消息队列 | 3.9.0 | 前端技术 | 技术 | 说明 | 版本 | | :----------------: | :---------------: | :----: | | Vue | 前端框架 | 2.6.10 | | Vue-router | 前端路由框架 | 3.1.2 | | Vuex | 全局状态管理框架 | 3.1.1 | | Axios | 前端HTTP框架 | 0.19.0 | | Ant Design of Vue | 后台管理UI框架 | 1.6.2 | | Vant | 前台商城VUE组件库 | 2.0 | ## 功能介绍 #### 管理后台: ###### 会员管理: - 会员列表 - 收货地址 - 会员收藏 - 会员足迹 - 意见反馈 ###### 商品管理: -

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈小定

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值