Home | 簡體中文 | 繁體中文 | 雜文 | 知乎專欄 | Github | OSChina 博客 | 雲社區 | 雲棲社區 | Facebook | Linkedin | 視頻教程 | 打賞(Donations) | About
知乎專欄多維度架構 | 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者”

2.12. Spring boot with Caching

2.12.1. maven

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

2.12.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);
    }

}			
			
			

2.12.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);
	}
				
			

2.12.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 []"			
			
			

2.12.5. @CachePut 用法

@CachePut 每次都會執行方法,都會將結果存入指定key的緩存中,@CachePut 不會判斷是否 key 已經存在,二是始終覆蓋。

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

   return null;

}
			
			

2.12.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
			
			
			

2.12.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";
	}