项目启动时自动加载redis缓存

 1.配置文件MyCacheConfig

@Configuration
@EnableCaching //开启spring缓存
public class MyCacheConfig extends CachingConfigurerSupport {

    /**
     * @Description: 使用@Cacheable注解的时候会将返回的对象缓存起来,默认缓存的值是二进制的,
     * 为此我们自定义序列化配置,改成JSON格式的
     */
    @Bean
    public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(1))// 设置缓存有效期一小时
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
        return new RedisCacheManager(redisCacheWriter, redisCacheConfiguration);
    }

    /**
     *自己的RedisTemplate
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate();
        template.setConnectionFactory(factory);
        //序列化配置
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);过时
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance ,
                ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        //String的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }


    @Override
    public KeyGenerator keyGenerator() {
        return  new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... objects) {
                //1.缓冲
                StringBuilder sb = new StringBuilder();
                //2.类名
                sb.append(target.getClass().getSimpleName());
                //3.方法名
                sb.append(method.getName());
                //4.参数值
                for (Object obj : objects) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };

    }
}

其中解决了@Cacheable注解的时候会将返回的对象缓存起来,默认缓存的值是二进制的问题

2.最主要的实现ApplicationRunner ,项目启动的时候回自动加载

import java.lang.annotation.*;

@Component
//@Slf4j
public class CacheLoader implements ApplicationRunner {
    private Logger logger = LoggerFactory.getLogger(CacheLoader.class);

    @Autowired
    private DictService dictService;

    public CacheLoader() {
        logger.info("创建缓存加载器ApplicationRunner:CacheLoader");
    }

    @Override
    public void run(ApplicationArguments args){
        logger.info("CacheLoader.run()");
        logger.info("预加载字典数据到缓存");
        dictService.loadDictToCache();
    }
}

3.使用正常逻辑三步走,清缓存,查询数据库,放入到到缓存中

    @Override
    public void loadDictToCache() {
        // 删除所有的dict的reids的key
        Set<String> keys = iDictRedisRepository.getAllKeys();
        //根据key删除所有的dict的redis
        iDictRedisRepository.deleteAll(keys);

        // 查询出dict表中的所有行数据
        List<Dict> list = this.list();

        //将dict放入到redis中 ,有两大类:dict 和 pdict
        iDictRedisRepository.putAllList(list);

        System.out.println("loadDictToCache finish ...");
    }

3.具体实现

package com.mehow.n302.userservice.repository.impl;

import com.mehow.n302.redisService.repository.IDictRedisRepository;
import com.mehow.n302.redisService.service.DictService;
import com.mehow.n302.redisServiceapis.entity.Dict;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;


@Repository
public class IDictRedisRepositoryImpl implements IDictRedisRepository {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public Set<String> getAllKeys() {
        //获取所有 dict:code 和 pdict:c.k.pk: 的keys
        Set<String> deleteKeys = redisTemplate.keys(DICT_LIST_KEY+"*");
        return deleteKeys;
    }

    @Override
    public Long deleteAll(Collection<String> keys) {
        return redisTemplate.delete(keys);
    }


    @Override
    public void putAllList(List<Dict> dicts) {
        //value值内容 去除p_id=0的数据
        List<Dict> listByCodes = dicts.stream().filter(d->!"0".equals(d.getParentId())).collect(Collectors.toList());
        //根据sort排序存放到redis中

        listByCodes.sort(Comparator.comparing(Dict::getCode).thenComparing(Dict::getSort));

      
        List<Dict> dictInput = new ArrayList<>();
        String searchCode = "";
        for (int i=0;i<listByCodes.size();i++) {
            if(i!=0 && !searchCode.equals(listByCodes.get(i).getCode())){
                //不为第一个值(因为肯定不等),且code不相等 则searchCode代表dictInput里面已经放了所有的searchCode,
                redisTemplate.opsForValue().set( DICT_LIST_KEY + searchCode, dictInput);

                searchCode = listByCodes.get(i).getCode();
                dictInput.clear();
            }
            dictInput.add(listByCodes.get(i));
            searchCode = listByCodes.get(i).getCode();

            if(i==listByCodes.size()-1){
                redisTemplate.opsForValue().set( DICT_LIST_KEY + searchCode, dictInput);
            }
    }
}

注:具体实现可根据自己系统的业务逻辑

猜你喜欢

转载自blog.csdn.net/qq_40453972/article/details/129822560