RedisTemplate和StringRedisTemplate在项目中应用

一,应用场景:项目启动时,需要进行初始化,初始化内容为redis缓存,目的是数据提前加载到缓存,而不是在项目中查询用到了,再去查询数据库,初始化缓存

初始化实现逻辑:清空缓存,查询数据库,初始化redis及本地缓存。

二,实现

项目中redis存储的数据类型有两种,一种是String,一种是对象类型数据

String类型数据,使用StringRedisTemplate类

对象类型数据,用RedisTemplate

为啥这样参考:

https://blog.csdn.net/notsaltedfish/article/details/75948281

我参考完之后,也没太十分明白,String类型用StringRedisTemplate就行了,原因是直接保存,直接取出来没问题,不会为null啥的

重点说一下:保存对象类型用RedisTemplate

在项目中,需要把对象先序列化为字节数据,保存起来,取的时候,取得是字节数据,再反序列化为可见的对象,(我就想为什么还要进行序列及反序列操作,不能拿过来直接用吗,可以,见下文)实现如下

存:

保存数据:
ValueOperations<String,byte[]> operations = redisTemplate.opsForValue();
operations.set(CacheKeyEnum.DOCUMENT.getKey()+apiDocument.getMethod(), ProtoStuffUtils.serialize(apiDocument));

取:

  BoundValueOperations<String, byte[]> operationsGet = redisTemplate.boundValueOps(CacheKeyEnum.DOCUMENT.getKey() + apiDocument.getMethod());
        if (operationsGet.get() != null) {
            byte[] bytes = operationsGet.get();
            apiDocument = ProtoStuffUtils.deSerialize(bytes, ApiDocument.class);
        }

序列化:

/**
 * 序列化,保存对象到redis
 * @author lr
 * @date 2019-07-30 11:40
 */
public class ProtoStuffUtils {

    /**
     * 序列化
     * @param message
     * @return
     */
    public static <T> byte[] serialize(T message) {
        Class<T> cls = (Class<T>) message.getClass();
        LinkedBuffer linkedBuffer = LinkedBuffer.allocate();
        Schema<T> schema =  RuntimeSchema.getSchema(cls);
        byte[] bytes = ProtostuffIOUtil.toByteArray(message,schema, linkedBuffer);
        return bytes;
    }

    /**
     * 反序列化
     * @param bytes
     * @return
     */
    public static <T> T deSerialize(byte[] bytes,Class<T> cls) {
        T message = null;
        try {
            message = cls.newInstance();
            ProtostuffIOUtil.mergeFrom(bytes,message, RuntimeSchema.getSchema(cls));
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return message;
    }
}

三,优化

上文提到为什么还要进行序列及反序列操作,不能拿过来直接用吗,项目中这样做是因为对象本身没有实现序列化接口,我尝试了一下,对象实现序列化接口,就可以不用序列化操作,实现如下

基类添加序列化
public class ApiDocument extends BaseEntity
public class BaseEntity implements Serializable {
存:
ValueOperations<String, ApiDocument> operations = redisTemplate.opsForValue();
ApiDocument apiDocument = apiDocuments.get(0);
operations.set(CacheKeyEnum.DOCUMENT.getKey() + apiDocument.getMethod(), apiDocument);
取:
BoundValueOperations<String, ApiDocument> operationsObj = redisTemplate.boundValueOps(CacheKeyEnum.DOCUMENT.getKey() + apiDocument.getMethod());
ApiDocument apiDocument1 = operationsObj.get();

四,项目初始化代码


/**
 * 初始化缓存(本地和Redis)
 * @author lr
 * @date 2019-07-26 16:05
 */
public class InitLocalRedisCache implements InitializingBean {


    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ApiProjectMapper apiProjectMapper;

    @Autowired
    private ApiDocumentMapper apiDocumentMapper;

    @Autowired
    private AppMapper appMapper;

    public InitLocalRedisCache(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 设置redis key的序列化方式为字符串
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        redisTemplate.setKeySerializer(new StringRedisSerializer(StandardCharsets.UTF_8));
    }

    /**
     * 初始化redis缓存。加载时先清空缓存
     */
    public void init(){
        ValueOperations<String,byte[]> operations = redisTemplate.opsForValue();
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();

        //1、清空缓存
        clearLocalRedisCache();

        //2、缓存项目服务地址
        List<ApiProject> apiProjects = apiProjectMapper.selectList(null);
        apiProjects.stream().forEach(apiProject -> {
            valueOperations.set(CacheKeyEnum.PROJECT.getKey()+apiProject.getProjectCode(), apiProject.getProductUrl());
            LocalCache.OPEN_PROJECT_URL_CACHE.put(apiProject.getProjectCode(),apiProject.getProductUrl());
        });

        //3、缓存接口信息(已发布)
        List<ApiDocument> apiDocuments = apiDocumentMapper.selectList(new QueryWrapper<ApiDocument>()
                .eq(GatewayConstant.STATUS, GatewayConstant.METHOD_PUBLISHED));

        apiDocuments.stream().forEach(apiDocument -> {
            operations.set(CacheKeyEnum.DOCUMENT.getKey()+apiDocument.getMethod(), ProtoStuffUtils.serialize(apiDocument));
            LocalCache.OPEN_DOCUMENT_CACHE.put(apiDocument.getMethod(),apiDocument);
        });

        //4、缓存应用秘钥
        List<OpenApp> openApps = appMapper.selectList(new QueryWrapper<OpenApp>().eq(GatewayConstant.STATUS, GatewayConstant.ENABLE));
        openApps.stream().forEach(openApp -> {
            valueOperations.set(CacheKeyEnum.APP.getKey()+openApp.getAppId(), openApp.getAppSecret());
            LocalCache.OPEN_APP_SECRET_CACHE.put(openApp.getAppId(),openApp.getAppSecret());
        });
    }

    /**
     * 清空缓存
     */
    private void clearLocalRedisCache() {
        //应用秘钥缓存
        Set appRedis = redisTemplate.keys(CacheKeyEnum.APP.getKey() + "*");
        redisTemplate.delete(appRedis);

        //项目服务地址缓存
        Set projectUrls = redisTemplate.keys(CacheKeyEnum.PROJECT.getKey() + "*");
        redisTemplate.delete(projectUrls);

        //接口详情缓存
        Set documents = redisTemplate.keys(CacheKeyEnum.DOCUMENT.getKey() + "*");
        redisTemplate.delete(documents);
    }
}

 

在Spring Boot,通过使用RedisTemplate实现与指定库的交互是一种常见的方法。Spring Boot是一个开源的框架,用于简化Spring应用的创建和部署。它提供了一个方便的方式来集成各种不同的数据库和缓存系统,包括Redis。 以下是在Spring Boot使用RedisTemplate实现使用指定库的一般步骤: 1. 添加依赖: 在你的Spring Boot项目的`pom.xml`文件,添加Redis相关的依赖。具体的库取决于你使用的Redis客户端和版本。例如,如果你使用的是 Jedis 客户端,那么可能需要添加如下的依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis连接: 在`application.properties`或`application.yml`文件,配置Redis的连接信息,包括主机名、端口、密码等。例如: ```properties spring.redis.host=localhost spring.redis.port=6379 spring.redis.password=your_password ``` 3. 使用RedisTemplate: 在配置好Redis连接后,你就可以在你的服务类使用RedisTemplate来与Redis数据库进行交互了。例如,你可以使用`opsForValue()`方法来执行基本的Redis操作,如设置和获取值。以下是一个简单的示例: ```java @Service public class RedisService { @Autowired private StringRedisTemplate stringRedisTemplate; public void setValue(String key, String value) { stringRedisTemplate.opsForValue().set(key, value); } public String getValue(String key) { return stringRedisTemplate.opsForValue().get(key); } } ``` 在这个示例,我们使用了`StringRedisTemplate`,它是Spring Data Redis提供的一个模板类,用于与String类型的Redis数据库进行交互。你也可以使用其他类型的RedisTemplate,如`HashRedisTemplate`和`ListRedisTemplate`,根据你使用的Redis库和数据类型进行选择。 请注意,上述步骤的代码仅作为示例,你需要根据你的实际需求进行适当的修改和扩展。另外,确保你已经正确地引入了所有必要的依赖,并且配置文件Redis连接信息是正确的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值