2018-12-31 · Develop

Spring Boot 缓存

应用系统需要通过 Cache 来缓存不经常改变的数据以提高系统性能和增加系统吞吐量,避免直接访问数据库等低速的存储系统。缓存的数据通常存放在访问速度更快的内存中或者是低延迟存取的存储器、服务器上。应用系统缓存通常有如下用处:

Spring Cache 对 Cache 进行了抽象,提供了 @Cacheable @CachePut @CacheEvict 等注解基于内存进行缓存管理。

Spring Boot 本身提供了基于 ConcurrentHashMap 进行单体应用的缓存实现,集成只需要添加如下的依赖

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

然后再配置文件中添加缓存管理器的配置信息

spring.cache.type=simple

同时需要使用注解 @EnableCaching 打开缓存功能。

@SpringBootApplication
@EnableCaching
public class LoApplication {

    public static void main(String[] args) {
        SpringApplication.run(LoApplication.class, args);
    }
}

添加 Service 方法

public interface UserService {

    User selectById(Long id);

    User save(User user);

    User updateNameById(Long id, String name);

    void deleteById(Long id);
}

以及实现类

@Service
@CacheConfig(cacheNames = {"user"})
public class UserServiceImpl implements UserService {

    @Cacheable
    @Override
    public User selectById(Long id) {
        return User.builder()
                .id(id)
                .name("TEST." + id)
                .departmentId(1L)
                .createTime(new Date())
                .build();
    }

    @CachePut(key = "#user.id")
    @Override
    public User save(User user) {
        return user;
    }

    @CachePut(key = "#id")
    @Override
    public User updateNameById(Long id, String name) {
        User user = selectById(id);
        user.setName(name);
        return user;
    }

    @CacheEvict
    @Override
    public void deleteById(Long id) {
        return;
    }
}
@Caching(evict = {
        @CacheEvict(key = "#user.id"),
        @CacheEvict(key = "#ext.id")
})
public void updateUser(User user, UserExt ext){

}

simple 类型的缓存与 Spring boot 应用在同一个 Java 虚拟机内,适合单体应用的系统。对于分布式系统,通常将缓存存放于单独的服务器上,只用最多的就是 redis 了。结合之前的文章 Spring Boot 对 Redis 的集成的文章 我们就只需将 type 改为 redis 。

spring.cache.type=redis

然后使用图形工具连接会看见 Value 值出现乱码,需要自定义下 Redis 的序列化策略

    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        return RedisCacheManager.builder(factory)
                .cacheDefaults(
                        RedisCacheConfiguration.defaultCacheConfig()
                                .disableCachingNullValues()
                                .entryTtl(Duration.ofMinutes(10))
                                .serializeKeysWith(
                                        RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string())
                                )
                                .serializeValuesWith(
                                        RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json())
                                )
                )
                .build();
    }

这样就会看到如下序列化后的 Value 值

{
  "@class": "com.zuojl.lo.modules.cache.entity.User",
  "id": 1.0,
  "name": "TEST.1",
  "departmentId": 1.0,
  "createTime": [
    "java.util.Date",
    1.54564594608E12
  ]
}