ホームページ  >  記事  >  データベース  >  SpringBoot が @Cacheable と RedisTemplate を使用して Redis を統合する方法

SpringBoot が @Cacheable と RedisTemplate を使用して Redis を統合する方法

PHPz
PHPz転載
2023-05-29 18:19:411390ブラウズ

以前の Web サイトに非常に簡単な最適化を行い、ユーザー リストにページング機能を追加しました。

ページ分割の際は読み込み速度を考慮することをお勧めします。ページを切り替えるのに数秒待たなければならない場合、エクスペリエンスは非常に悪くなります。

そこで、redis キャッシュを追加することを考えました。

springboot が redis を統合するには 2 つの方法があります:

  • 1. アノテーションを使用します (@EnableCaching @Cacheable . . . など)

  • 2. RedisTemplate を使用する

RedisTemplate を使用してキャッシュを操作すると、アノテーションを使用するよりも柔軟で便利です。アノテーションを使用すると、メソッドを入力せずにキャッシュから直接データをフェッチするため、理論的には高速になるはずです。 RedisTemplateをメソッド内で実行し、ロジックの記述の判定を行う必要があります。

以下は、ページングのキャッシュに関する私のアイデアの記録です。不足点はたくさんあると思います。皆さんに指摘していただければ幸いです。

ビジネス シナリオはバックエンド管理システムです。リアルタイムのデータ更新にあまり注意を払う必要はなく、有効期限を 1 時間に設定するだけです。

私のアイデアは次のとおりです:

初めてページを読み込むときに、データベースから最初の 4 ページのデータをクエリします。このようにして、初回は少し長く待ちます。その後のページ変更はほとんど待つ必要がなく、より良いエクスペリエンスになります。その後、ページを変更するたびにキャッシュにあるかどうかを確認し、役に立たない場合はキャッシュに追加します。

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

データ統計に再度注釈を付けてみました。

まず起動時に @EnableCaching アノテーションを追加します

アノテーションは簡単に使用できます。メソッドに @Cacheable を追加するだけです。メソッドを実行する前に、Redis キャッシュに対応するアノテーションがあるかどうかがクエリされます。キーがある場合は値を直接取得し、そうでない場合はメソッドを実行します。

value = "appUserData" はキャッシュ領域の名前、key はキーの名前です。

次のキー値は appUserData です: userArea

@RequestMapping ("/userArea")
@Cacheable(value = "appUserData",key ="&#39;userArea&#39;")
public R<String> area() {
    List<AppUser> userList = appUserServiceInterface.list();
    List<String> areaList = new ArrayList<>();

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

    //取前8
    int len = mapList.size();
    for (int i = 0; i < len-8; i++) {
        mapList.remove(8);
    }

    Map<String, String> resMap = new HashMap<>();
    for (Map.Entry<String, Integer> m : mapList) {
        resMap.put(m.getKey(), m.getValue().toString());
    }
    return R.success(resMap);
}

その他の注意事項:

  • @CachePut

  • # #@Caching

  • @CacheEvict

以上がSpringBoot が @Cacheable と RedisTemplate を使用して Redis を統合する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。