• SpringBoot整合Redis - @Cacheable 和 RedisTemplate


    对之前网站做了一些很简单的优化,给用户列表加了一个分页功能。

    分页就更好考虑加载速度,如果换一页就要等几秒,那体验感是非常差的。

    因此想到了加一个redis缓存。

    springboot整合redis有两种方式:

            一、使用注解,@EnableCaching @Cacheable . . . 等

            二、使用RedisTemplate

    两者都能操作缓存,使用RedisTemplate 操作肯定是比使用注解灵活、方便。但是从理论上来讲注解方式速度应该更快,因为使用注解如果在缓存中有就直接从缓存中取,不用进入方法。而RedisTemplate 必须进入方法,而且执行写的逻辑判断。

    下面记录一下我给分页做缓存的思路,肯定有很多不好的地方,希望大家可以给我指出。

    业务场景是后台管理系统,不用过于注重实时数据刷新,就设置一个小时过期。

    我的思路是:

            第一次加载页面,就从数据库把前面四页的数据从数据库查询出来,这样第一次稍微多等一下,后面换页几乎不用等待,这样体验比较好。然后每次换页都换查看有没有在缓存中,没用就加入缓存。

    @RequestMapping("/appUser/{currentPage}")
    public R getTableData1(@PathVariable int currentPage) {
        //第一次请求 前面几页用到的概率更大  把后面三页存入redis 减少后面分页请求的时间  以后每次加载页面都把那页放入redis
        // 设置一个小时过期
        Page appUserPage = new Page(currentPage, 12);
        if (currentPage == 1 && !redisTemplate.hasKey(1)) {
            for (int i = 1; i < 5; i++) {
                Page redisPage = new Page(i, 12);
                redisTemplate.opsForValue().set(i, appUserServiceInterface.page(redisPage), 1, TimeUnit.HOURS);
            }
        } else if (!redisTemplate.hasKey(currentPage)) {
            redisTemplate.opsForValue().set(currentPage, appUserServiceInterface.page(appUserPage), 1, TimeUnit.HOURS);
            return R.success((Page) redisTemplate.opsForValue().get(currentPage));
        } else if (redisTemplate.hasKey(currentPage)) {
            return R.success((Page) redisTemplate.opsForValue().get(currentPage));
        }
        return R.success(appUserServiceInterface.page(appUserPage));
    }

    数据统计那块我又试了试注解。

    先要在启动加上 @EnableCaching注解 

    注解使用就简单,在方法上加上@Cacheable 就行,执行方法前会查询redis缓存是否有对应的key,有就直接取值,没有就执行方法。

    value = "appUserData" 是缓存区的名字 , key是键的名字 。

    以下的键值就是 appUserData : : userArea

    @RequestMapping ("/userArea")
    @Cacheable(value = "appUserData",key ="'userArea'")
    public R area() {
        List userList = appUserServiceInterface.list();
        List areaList = new ArrayList<>();
    
        for (AppUser appUser : userList) {
            areaList.add(appUser.getArea());
        }
        //放入map记录每个月份出现的次数
        Map areaTimes = new HashMap<>();
        for (String s : areaList) {
            if (!areaTimes.containsKey(s)) {
                areaTimes.put(s, 1);
            }else {
                areaTimes.put(s, areaTimes.get(s) + 1);
            }
        }
        //排序
        //自定义比较器
        Comparator> valCmp = new Comparator>() {
            @Override
            public int compare(Map.Entry o1, Map.Entry o2) {
                // TODO Auto-generated method stub
                return o2.getValue() - o1.getValue();  // 降序排序,如果想升序就反过来
            }
        };
        //将map转成List,map的一组key,value对应list一个存储空间
        List> mapList = new ArrayList>(areaTimes.entrySet()); //传入maps实体
        Collections.sort(mapList, valCmp);
    
        //取前8
        int len = mapList.size();
        for (int i = 0; i < len-8; i++) {
            mapList.remove(8);
        }
    
        Map resMap = new HashMap<>();
        for (Map.Entry m : mapList) {
            resMap.put(m.getKey(), m.getValue().toString());
        }
        return R.success(resMap);
    }

    其他注解:

            @CachePut

            @Caching

            @CacheEvict

  • 相关阅读:
    MySQL函数与控制结构
    盘盘在项目中你常用的那些数组API
    IDEA调试并运行Spring源码
    Java之自定义MVC(2)
    【Python零基础入门篇 · 16】:拆包、异常种类、异常处理、抛出异常
    [PAT练级笔记] 13 Basic Level 1015
    数据绑定之数据类型转换
    【错误记录】Android 编译报错 ( The project uses Gradle version which is incompatible with Android Studio )
    网站服务器该怎么选择呢?
    智能仪器仪表行业数字化供应链管理系统:加速企业智慧供应链平台转型
  • 原文地址:https://blog.csdn.net/qq_61672548/article/details/125820961