redis两种默认的Template
之前的一篇博客Springboot项目整合Redis记录了RedisTemplate和StringRedisTemplate的使用效果,由于分别使用了不同的序列化器,所以在Redis中存储的形式也不相同。redisTemplate使用的是默认的序列化器jdk序列化方式,而StringRedisTemplate使用了String序列化方式。这里不再赘述。为了与后面使用自定义RedisTemplate进行存储进行对比,这里先分别使用RedisTemplate和StringRedisTemplate两种模板进行数据存储:
package org.magic.redis;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
@SpringBootTest
class RedisApplicationTests {
@Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void useRedisTemplate() {
redisTemplate.opsForValue().set("User","张三");
}
@Test
void useStringTemplate(){
stringRedisTemplate.opsForValue().set("User","张三");
}
}
RedisTemplate
StringRedisTemplate
如果每次使用Redis进行存储的时候还需要考虑怎么选择序列化方式未免太过麻烦,实际上在项目中我们一般会自定义一个RedisTemplate,这样就不会产生由于序列化方式而引起的不必要的麻烦。
自定义RedisTemplate
package org.magic.redis.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.StringRedisSerializer;
/**
* @Author 无关痛痒
* @create 2020/5/8
* @Description: 方法是自定义redis的配置类,自定义序列化器
*/
@Configuration
public class RedisConfig {
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
//自定义Jackson序列化配置
Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, DefaultTyping.NON_FINAL);
jsonRedisSerializer.setObjectMapper(objectMapper);
//key使用String的序列化方式
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
//hash的key也是用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//value的key使用jackson的序列化方式
template.setValueSerializer(jsonRedisSerializer);
//hash的value也是用jackson的序列化方式
template.setHashValueSerializer(jsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
从序列化器源码中可以看到Redis有很多种序列化方式:(ctrl+n 搜索RedisSerializer
可以查看序列化器源码,ctrl+alt+鼠标左键可查看接口实现类)
然后再注入自定义的RedisTemplate进行存储测试:
package org.magic.redis;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
@SpringBootTest
class RedisApplicationTests {
@Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate;
@Test
void useRedisTemplate() {
redisTemplate.opsForValue().set("Trade","张三");
}
}
看到这里说明我们自定义的RedisTemplate使用成功了。
看看Redis的配置源码:
/*
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.autoconfigure.data.redis;
import java.net.UnknownHostException;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Redis support.
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Christian Dupuis
* @author Christoph Strobl
* @author Phillip Webb
* @author Eddú Meléndez
* @author Stephane Nicoll
* @author Marco Aust
* @author Mark Paluch
* @since 1.0.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
源码中有一个@ConditionalOnMissingBean
注解,该注解作用在@Bean上,Spring容器启动的时候检查容器中是否已经有@ConditionalOnMissingBean
作用的@bean了,如果有则跳过@ConditionalOnMissingBean
作用的bean,如果没有则加载该bean。说白了就是如果有自定义的redisTemplate
或者stringRedisTemplate
就用自定义的,没有自定义的再用这个默认的。