之前在上软件架构与中间件的时候有不少同学在将自己的SpringBoot项目中加入Redis的时候遇到了问题,突然间想起来还是补上记录一下吧,供后来的同学参考

首先在pom.xml中添加如下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

然后在config文件夹下加入对象序列化的类:

package com.hit.software.sale.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
    private long expiration;

    @Bean
    CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        // 配置序列化(解决乱码的问题)
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(expiration))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerialize()))
                .disableCachingNullValues();

        return RedisCacheManager.builder(connectionFactory).cacheDefaults(config).build();
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        template.setValueSerializer(jackson2JsonRedisSerialize());
        template.afterPropertiesSet();
        return template;
    }

    private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerialize() {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        return jackson2JsonRedisSerializer;
    }
}

最后就是基本的业务逻辑啦:

package com.hit.software.sale.service.impl;

import com.hit.software.sale.dao.GoodsDao;
import com.hit.software.sale.domain.GoodsDO;
import com.hit.software.sale.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;


@Service
@CacheConfig(cacheNames = "goodsCache")
public class GoodsServiceImpl implements GoodsService {
    @Autowired
    private GoodsDao goodsDao;

    @Override
    @Cacheable(key = "#id")    //这里的key表示将数据存入redis时的键,# 表示从参数中取值
    public GoodsDO get(Integer id) {
        return goodsDao.get(id);
    }

    @Override
    @Cacheable("goodsList")    //如果不写key,则代表value,表示在value开启一个对象,在此对象下储存
    public List<GoodsDO> list(Map<String, Object> map) {
        return goodsDao.list(map);
    }

    @Override
    @Cacheable("goodsListCount")
    public int count(Map<String, Object> map) {
        return goodsDao.count(map);
    }

    @Override
    @Caching(evict = {@CacheEvict(key = "#goods.id"),    //这里是删除,当更新时删除原数据重新缓存,key与上述一致
            @CacheEvict(value = "goodsList", allEntries = true),
            @CacheEvict(value = "goodsListCount", allEntries = true)})
    public int save(GoodsDO goods) {
        return goodsDao.save(goods);
    }

    @Override
    @Caching(evict = {@CacheEvict(key = "#goods.id"),
            @CacheEvict(value = "goodsList", allEntries = true),
            @CacheEvict(value = "goodsListCount", allEntries = true)})
    public int update(GoodsDO goods) {
        return goodsDao.update(goods);
    }

    @Override
    @Caching(evict = {@CacheEvict(key = "#id"),
            @CacheEvict(value = "goodsList", allEntries = true),
            @CacheEvict(value = "goodsListCount", allEntries = true)})
    public int remove(Integer id) {
        return goodsDao.remove(id);
    }

    @Override
    public int batchRemove(Integer[] ids) {
        return goodsDao.batchRemove(ids);
    }

}
2人点赞