java使用redis,Callable 封装工具方法

使用Redis缓存数据时,频繁的get、set方法繁琐且难维护。本文给出一个通用工具方法及简单说明,思路包括用Callable类抽象查询逻辑、封装不同方法处理不同数据类型、将类交由Spring管理,还贴出调用方代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简单调用Redis缓存的工具方法

前言:

使用redis缓存数据时,频繁的get,set方法,十分的繁琐与难以维护,今天刚好遇上这个场景写了一个通用的工具方法,将代码贴出,有需要可以取走。附上简单的说明,如有不清楚可以评论咨询,如有不足或者更好的想法也可以一起讨论。

简单暴力,毕竟是工具类直接贴代码。

备注:因为不是去说redis接入的,redis接入部分的代码我就不贴了。

1、工具类的代码:
今天刚写的,提供个简单思路,有需要的可以自己拓展一下。
思路如下:
1.1、主要是使用的 Callable类,将所有真正查询的逻辑视作一个简单的函数,一个单位,抽象出来交由 Callable去调用。抽象与实现分离的思维。
1.2、Redis存的都是字符串,但有时是数组有时是对象,使用JSON工具时仍需要注意此项,因此封装了两个方法,区别开。
1.3、将类交由Spring管理,首先是单例,其次也可以方便使用其他的一些操作。

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class RedisUtil {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * redis缓存的封装 返回是数组类型
     *
     * @param callable   具体逻辑
     * @param redisKey
     * @param clazz      返回值的类型
     * @param expireTime 过期时间(单位毫秒)
     * @return java.util.List<R>
     * @date 16:07 2023/3/14
     **/
    public <R> List<R> cacheCallableArray(Callable<List<R>> callable, String redisKey, Class<R> clazz, Long expireTime) throws Exception {
        log.info("method:cacheCallableArray,redisKey:{},expireTime:{}", redisKey, expireTime);
        // 取缓存
        Object redisValue = redisTemplate.opsForValue().get(redisKey);
        if (ObjectUtil.isNotEmpty(redisValue)) {
            return JSONArray.parseArray(String.valueOf(redisValue), clazz);
        }
        // 存到缓存
        String jsonString = JSONArray.toJSONString(callable.call());
        redisTemplate.opsForValue().set(redisKey, jsonString, expireTime, TimeUnit.MILLISECONDS);
        return callable.call();
    }

    /**
     * redis缓存的封装 返回是对象类型
     *
     * @param callable 具体逻辑
     * @param redisKey
     * @param clazz 返回值的类型
     * @param expireTime 过期时间(单位毫秒)
     * @return R
     * @date 16:11 2023/3/14
     **/
    public <R> R cacheCallableObj(Callable<R> callable, String redisKey, Class<R> clazz, Long expireTime) throws Exception {
        log.info("method:cacheCallableArray,redisKey:{},expireTime:{}", redisKey, expireTime);
        // 取缓存
        Object redisValue = redisTemplate.opsForValue().get(redisKey);
        if (ObjectUtil.isNotEmpty(redisValue)) {
            return JSONObject.parseObject(String.valueOf(redisValue), clazz);
        }
        // 存到缓存
        String jsonString = JSONObject.toJSONString(callable.call());
        redisTemplate.opsForValue().set(redisKey, jsonString, expireTime, TimeUnit.MILLISECONDS);
        return callable.call();
    }
}

2、贴一下调用方的代码,主要是提供键与过期时间。部分无关的逻辑简写了。

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
	
@Slf4j
@Service	
public class A{
	@Autowired
    private RedisUtil redisUtil;
	/**
     * XXX 缓存前缀
     */
    private final String XXX_CACHE = "XXX_CACHE :";
     /**
     * XXX查询 缓存
     * @date 16:18 2023/3/14
     * @param id
     **/
    @SneakyThrows
    public CascaderEntity getTreeModelsCascaderCache(Long id) {
        String cacheKey = this.CATALOG__PC_getTreeModelsCascader_CACHE + String.valueOf(id);
        Long expireTime = streamingCommonUtil.randomLong();
        return redisUtil.cacheCallableObj(()->this.getTreeModelsCascader(id),cacheKey,CascaderEntity.class,expireTime);
    }

    /**
     * 原查询方法
     * 树结构的一种递归逻辑,有兴趣的同志可以瞅瞅
     * @param id
     * @return com.central.common.vo.base.CascaderEntity 仿照前端elementUi的Cascader级联下拉框的数据模型
     * @date 10:52 2023/3/14
     **/
    public CascaderEntity getTreeModelsCascader(Long id) {
        // 查询所有树,并数据处理
        List<CatalogContent> catalogContents = this.list();
        Assert.isArrayEmpty(catalogContents, CommonEnum.ExceptionDesc.数据异常);
        // 根据父id分组
        Map<Long, List<CatalogContent>> map = catalogContents.stream().collect(Collectors.groupingBy(CatalogContent::getParentId));
        CatalogContent topCatalogContent = map.get(-1L).get(0);
        return this.cascaderHandle(topCatalogContent, map);
    }

	/**
     * 递归树结构处理
     * 业务限制,顶级树节点只有一层。有需要可以换成List<Node>实现,逻辑差不多
     * @param catalogContent 当前节点对象
     * @param map 整个树的数据,根据parentId分组
     * @return com.central.common.vo.base.CascaderEntity
     * @date 10:52 2023/3/14
     **/
    private CascaderEntity cascaderHandle(CatalogContent catalogContent, Map<Long, List<CatalogContent>> map) {
        CascaderEntity cascaderEntity = new CascaderEntity();
        cascaderEntity.setValue(String.valueOf(catalogContent.getId())).setLabel(catalogContent.getName());
        // 获取子节点
        List<CatalogContent> childNodes = map.get(catalogContent.getId());
        if (CollectionUtil.isEmpty(childNodes)) {
            return cascaderEntity;
        }
        // 按指定sort排序
        Collections.sort(childNodes, (x1, x2) -> streamingCommonUtil.sortAsc(x1.getSort(), x2.getSort()));
        List<CascaderEntity> newChildNodes = new ArrayList<>();
        // 递归
        childNodes.stream().forEach(item -> {
            CascaderEntity newChildNode = this.cascaderHandle(item, map);
            newChildNodes.add(newChildNode);
        });
        cascaderEntity.setChildren(newChildNodes);
        return cascaderEntity;
    }
}
package com.central.common.vo.base;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.List;

/**
 *  Cascader 级联选择器的模型
 * @author chenkaimin
 * @Date 2022/11/2 14:38
 */ 
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class CascaderEntity implements Serializable {
    private static final long serialVersionUID = -2016602847223469602L;
    
    /**
     * 值,相当于id
     */
    private String value;

    /**
     * 展示,相当于name
     */
    private String label;

    /**
     * 子级
     */
    private List<CascaderEntity> children;

    public CascaderEntity(String value, String label) {
        this.value = value;
        this.label = label;
    }

    public CascaderEntity(Long value, String label) {
        this.value = String.valueOf(value);
        this.label = label;
    }
}

留言:老婆做了一个小红书账号,全是瓷砖方面的干货,大佬们如果有需求或者有兴趣可以移步了解一下,嘻嘻~

小红书地址,GO GO GO!!!
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值