Home | 简体中文 | 繁体中文 | 杂文 | 打赏(Donations) | 云栖社区 | OSChina 博客 | Facebook | Linkedin | 知乎专栏 | Github | Search | About

5.21. Spring boot with Caching

5.21.1. maven

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

5.21.2. 启用 Cache

添加 @EnableCaching

			
package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class Application {

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

}			
			
			

5.21.3. 测试 Controller

缓存返回结果

				
	@Cacheable("cacheable")
	@RequestMapping("/test/cacheable")
	@ResponseBody
	public String cacheable() {
		Date date = new Date();
		String message = date.toString();
		return message;
	}
				
			

5秒钟清楚一次缓存

				
	@Scheduled(fixedDelay = 5000)
	@CacheEvict(allEntries = true, value = "cacheable")	
	public void expire() {
		Date date = new Date();
		String message = date.toString();
		System.out.println(message);
	}
				
			

5.21.4. @Cacheable 的用法

			
@Cacheable(value="users", key="#id")
public User find(Integer id) {

   return null;

}			
			
			

引用对象

			
@Cacheable(value="users", key="#user.id")
public User find(User user) {

   returnnull;

}			
			
			

条件判断

			
@Cacheable(value="messagecache", key="#id", condition="id < 10")
public String getMessage(int id){

	return "hello"+id;

}

@Cacheable(value="test",condition="#userName.length()>2")
@Cacheable(value={"users"}, key="#user.id", condition="#user.id%2==0")
			
			

#p0 参数索引,p0表示第一个参数

			
@Cacheable(value="users", key="#p0")
public User find(Integer id) {

   return null;

}

@Cacheable(value="users", key="#p0.id")
public User find(User user) {

   return null;

}
			
			

@Cacheable 如果没有任何参数将会自动生成 key ,前提是必须设置 @CacheConfig(cacheNames = "test")

			
	@GetMapping("/cache/auto")
	@Cacheable()
	public Attribute auto() {
		Attribute attribute = new Attribute();
		attribute.setName("sdfsdf");
		return attribute;
	}			
			
			
			
127.0.0.1:6379> keys *
1) "test::SimpleKey []"			
			
			

5.21.5. @CachePut 用法

@CachePut 每次都会执行方法,都会将结果存入指定key的缓存中,@CachePut 不会判断是否 key 已经存在,二是始终覆盖。

			
@CachePut("users")
public User find(Integer id) {

   return null;

}
			
			

5.21.6. 解决Expire 和 TTL 过期时间

Springboot 1.x

			
	@Bean
	public CacheManager cacheManager(RedisTemplate redisTemplate) {
		RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
		cacheManager.setDefaultExpiration(60);	//缓存默认 60 秒
		Map<String, Long> expiresMap = new HashMap<>();
		expiresMap.put("Product", 5L);  //设置 key = Product 时 5秒缓存。你可以添加很多规则。 
		cacheManager.setExpires(expiresMap);
		return cacheManager;
	}			
			
			

Springboot 2.x

			
package api.config;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
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.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
public class CachingConfigurer {

	public CachingConfigurer() {
		// TODO Auto-generated constructor stub
	}

	@Bean
	public KeyGenerator simpleKeyGenerator() {
		return (o, method, objects) -> {
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.append(o.getClass().getSimpleName());
			stringBuilder.append(".");
			stringBuilder.append(method.getName());
			stringBuilder.append("[");
			for (Object obj : objects) {
				stringBuilder.append(obj.toString());
			}
			stringBuilder.append("]");

			return stringBuilder.toString();
		};
	}

	@Bean
	public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
		return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory), 
		this.redisCacheConfiguration(600), 	// 默认配置
		this.initialCacheConfigurations());	// 指定key过期时间配置
	}
               
	private Map<String, RedisCacheConfiguration> initialCacheConfigurations() {
		Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
		redisCacheConfigurationMap.put("UserInfoList", this.redisCacheConfiguration(3000));
		redisCacheConfigurationMap.put("UserInfoListAnother", this.redisCacheConfiguration(18000));

		return redisCacheConfigurationMap;
	}

	private RedisCacheConfiguration redisCacheConfiguration(Integer seconds) {
		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);

		RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
		redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).entryTtl(Duration.ofSeconds(seconds));

		return redisCacheConfiguration;
	}

}

			
			

			
	@Cacheable(value = "DefaultKey", keyGenerator = "simpleKeyGenerator") // 600秒,使用默认策略
	@Cacheable(value = "UserInfoList", keyGenerator = "simpleKeyGenerator") // 3000秒
    @Cacheable(value = "UserInfoListAnother", keyGenerator = "simpleKeyGenerator") // 18000秒
    
			
			
			
127.0.0.1:6379> keys *
1) "test2::SimpleKey []"

127.0.0.1:6379> ttl "test2::SimpleKey []"
(integer) 584
			
			
			

5.21.7. SpEL表达式

			
	@GetMapping("/cache/expire")
	@Cacheable("test1#${select.cache.timeout:1000}")
	public String expire() {
		return "Test";
	}
	
	@GetMapping("/cache/expire")
	@Cacheable("test1#${select.cache.timeout:1000}#${select.cache.refresh:600}")
	public String expire() {
		return "Test";
	}