springboot 整合redis

1,準備

①,一個linux虛擬機,安裝好docker,再安裝redis鏡像,而後啓動redis容器java

#下載redis鏡像
docker pull registry.docker-cn.com/library/redis

#-d 後臺運行 -p 暴露端口 --name 起名 最後帶上鏡像名便可
docker run -d -p 6379:6379 --name myredis bfcb1f6df2db

#啓動redis 容器
docker start myredis

②,身爲程序員linux不可不玩,而docker就是一個強有力的工具mysql

③,springboot版本2.0.2.RELEASElinux

④,pom依賴程序員

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
 <dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>1.3.2</version>
</dependency>

<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
</dependency>

2,redis配置

import java.net.UnknownHostException;
import java.time.Duration;

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.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
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;

@EnableCaching
@Configuration
public class CacheConfig {

	@Bean
	public RedisCacheConfiguration redisCacheConfiguration() {
		RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
				Object.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		// 將類型序列化到屬性json字符串中
		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
		jackson2JsonRedisSerializer.setObjectMapper(om);
		configuration = configuration
				.serializeValuesWith(
						RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
				.entryTtl(Duration.ofDays(30));
		return configuration;
	}

	@Bean
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
			throws UnknownHostException {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setConnectionFactory(redisConnectionFactory);
		
		Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
				Object.class);
		ObjectMapper om = new ObjectMapper();
		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
		// 將類型序列化到屬性json字符串中
		jackson2JsonRedisSerializer.setObjectMapper(om);
		
		template.setKeySerializer(jackson2JsonRedisSerializer);
		template.setValueSerializer(jackson2JsonRedisSerializer);
		return template;
	}
}

3,application.properties 配置

spring.redis.host=192.168.43.28
spring.redis.port=6379

①,注意只要配置瞭如上信息,web

springboot的默認緩存就會從SimpleCacheConfiguration 切換成RedisCacheConfiguration
②,原理以下redis

@Configuration
//主要是這裏,當沒有CacheManager 時生效
@ConditionalOnMissingBean(CacheManager.class)
@Conditional(CacheCondition.class)
class SimpleCacheConfiguration {

③,springboot緩存的加載循序以下spring

//CacheAutoConfiguration 的配置以下
static class CacheConfigurationImportSelector implements ImportSelector {

		@Override
		public String[] selectImports(AnnotationMetadata importingClassMetadata) {
			CacheType[] types = CacheType.values();
			String[] imports = new String[types.length];
			for (int i = 0; i < types.length; i++) {
				imports[i] = CacheConfigurations.getConfigurationClass(types[i]);
			}
			return imports;
		}

	}

由於redis在simple的前面,一旦RedisCacheConfiguration 生效就會配置RedisCacheManager,而後simple就不注入ioc容器了sql

4,RedisCacheConfiguration 生效

//使用RedisCacheManager 用於建立cache	
@Bean
	public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory,
			ResourceLoader resourceLoader) {
		RedisCacheManagerBuilder builder = RedisCacheManager
				.builder(redisConnectionFactory)
				.cacheDefaults(determineConfiguration(resourceLoader.getClassLoader()));
		List<String> cacheNames = this.cacheProperties.getCacheNames();
		if (!cacheNames.isEmpty()) {
			builder.initialCacheNames(new LinkedHashSet<>(cacheNames));
		}
		return this.customizerInvoker.customize(builder.build());
	}
//RedisCacheManager 建立cache的方法	
protected RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) {
		return new RedisCache(name, cacheWriter, cacheConfig != null ? cacheConfig : defaultCacheConfig);
	}

5,RedisCache 建立緩存的流程

//①,根據必定的策略生成緩存的key
protected String createCacheKey(Object key) {

		String convertedKey = convertKey(key);

		if (!cacheConfig.usePrefix()) {
			return convertedKey;
		}

		return prefixCacheKey(convertedKey);
	}

//②,先嚐試獲取緩存
	public byte[] get(String name, byte[] key) {

		Assert.notNull(name, "Name must not be null!");
		Assert.notNull(key, "Key must not be null!");

		return execute(name, connection -> connection.get(key));
	}
//③,獲取不到就執行目標方法,並將返回結果放入緩存
public void put(Object key, @Nullable Object value) {

		Object cacheValue = preProcessCacheValue(value);

		if (!isAllowNullValues() && cacheValue == null) {

			throw new IllegalArgumentException(String.format(
					"Cache '%s' does not allow 'null' values. Avoid storing null via '@Cacheable(unless=\"#result == null\")' or configure RedisCache to allow 'null' via RedisCacheConfiguration.",
					name));
		}

		cacheWriter.put(name, createAndConvertCacheKey(key), serializeCacheValue(cacheValue), cacheConfig.getTtl());
	}

6,獲取緩存的過程

//①,根據必定的策略生成緩存的key
protected String createCacheKey(Object key) {

		String convertedKey = convertKey(key);

		if (!cacheConfig.usePrefix()) {
			return convertedKey;
		}

		return prefixCacheKey(convertedKey);
	}
//②,嘗試根據能夠獲取對應的緩存
	@Override
	public byte[] get(String name, byte[] key) {

		Assert.notNull(name, "Name must not be null!");
		Assert.notNull(key, "Key must not be null!");

		return execute(name, connection -> connection.get(key));
	}
//③,獲取成功則不執行目標方法,直接將緩存返回

7,緩存在redis的樣子

①,注意,緩存的數據要帶有緩存的類型,不然redis緩存反序列化成對應pojo會失敗,只要按上面的CacheConfig配置好RedisCacheConfiguration 便可docker

8,controller測試

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class RedisController {

	@Autowired
	private RedisTemplate<Object, Object> redisTemplate;
	
	@RequestMapping("put")
	@ResponseBody
	public String put(String key) {
		ValueOperations<Object, Object> opsForValue = redisTemplate.opsForValue();
		Object val = opsForValue.get(key);
		if(val==null) {
			String value="小純"+key;
			opsForValue.set(key, value);
			return "key:"+key+",val"+value +",加入緩存";
		}		
		return "key:"+key+",val"+val +",已在緩存中存在";
	}
}
相關文章
相關標籤/搜索