redistemplate使用_spring-boot-starter-data-redis源码解析与使用实战
我們以spring-boot-starter-data-redis-2.1.7為例,starter本身沒有包含任何代碼,只是引入了spring-data-redis的依賴,因此肯定是在spring-boot-autoconfigure中加了自動(dòng)配置:
我們就看下這幾個(gè)配置類:
其中RedisAutoConfiguration里面就配置了我們常用的RedisTemplate,RedisRepositoriesAutoConfiguration這里面是實(shí)現(xiàn)了spring-data規(guī)范的一些配置,RedisReactiveAutoConfiguration是當(dāng)需要用Reactive方式編程的時(shí)候用的,本文忽略。
RedisAutoConfiguration
@Configuration @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) //內(nèi)置了對(duì)lettuce和jedis的支持 //但是默認(rèn)只添加了lettuce的依賴,因此默認(rèn)是使用的lettuce @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;} }這里面內(nèi)置了對(duì)lettuce和jedis的支持,因?yàn)槟J(rèn)是引入的lettuce的jar,因此默認(rèn)會(huì)使用lettuce去訪問redis,同時(shí)這里面創(chuàng)建了一個(gè)RedisTemplate和一個(gè)StringRedisTemplate,一般我們經(jīng)常會(huì)直接注入StringRedisTemplate來(lái)訪問redis。
首先看下StringRedisTemplate:
public StringRedisTemplate() {setKeySerializer(RedisSerializer.string());setValueSerializer(RedisSerializer.string());setHashKeySerializer(RedisSerializer.string());setHashValueSerializer(RedisSerializer.string()); }從名字也可以看出來(lái),它在序列化key、value、hash key和hash value的時(shí)候都是轉(zhuǎn)化成String存入redis的,RedisSerializer#string:
static RedisSerializer<String> string() {return StringRedisSerializer.UTF_8; } public static final StringRedisSerializer UTF_8 = new StringRedisSerializer(StandardCharsets.UTF_8);看下具體的序列化和反序列化的方法:
@Override public String deserialize(@Nullable byte[] bytes) {return (bytes == null ? null : new String(bytes, charset)); } @Override public byte[] serialize(@Nullable String string) {return (string == null ? null : string.getBytes(charset)); }一眼就能明白,沒什么好說(shuō)的。但是很顯然,它只能處理String類型,如果是對(duì)象得需要自己手動(dòng)轉(zhuǎn)化成String才可以,一般我們會(huì)把對(duì)象轉(zhuǎn)化成json字符串存儲(chǔ)到redis里面。
我們回頭再來(lái)看下RedisTemplate,RedisTemplate#afterPropertiesSet:
@Overridepublic void afterPropertiesSet() {boolean defaultUsed = false;//判斷是否幽默ren的序列化器if (defaultSerializer == null) {//默認(rèn)是采用jdk自帶的序列化,//也就是說(shuō)必須得實(shí)現(xiàn)Serializable接口才行defaultSerializer = new JdkSerializationRedisSerializer(classLoader != null ? classLoader : this.getClass().getClassLoader());}//默認(rèn)j就是啟用的if (enableDefaultSerializer) {//key、value、hash key、hash value都使用默認(rèn)的那個(gè)序列化器 if (keySerializer == null) {keySerializer = defaultSerializer;defaultUsed = true;}if (valueSerializer == null) {valueSerializer = defaultSerializer;defaultUsed = true;}if (hashKeySerializer == null) {hashKeySerializer = defaultSerializer;defaultUsed = true;}if (hashValueSerializer == null) {hashValueSerializer = defaultSerializer;defaultUsed = true;}}。。。}從名字也可以看出來(lái),RedisTemplate默認(rèn)是采用JDK自帶的序列化方式來(lái)做序列化器,看一下:
public JdkSerializationRedisSerializer(@Nullable ClassLoader classLoader) {this(new SerializingConverter(), new DeserializingConverter(classLoader));}public SerializingConverter() {this.serializer = new DefaultSerializer();} public class DefaultSerializer implements Serializer<Object> {@Overridepublic void serialize(Object object, OutputStream outputStream) throws IOException {if (!(object instanceof Serializable)) {throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +"but received an object of type [" + object.getClass().getName() + "]");}ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);objectOutputStream.writeObject(object);objectOutputStream.flush();} }很清楚了,最終是使用ObjectOutputStream和ObjectInputStream來(lái)讀寫對(duì)象,因此對(duì)象必須得實(shí)現(xiàn)Serializable接口才可以,最終是以二進(jìn)制的格式存儲(chǔ)到redis里面,比如:
很顯然,這種序列化方式的可讀性太不友好了。
RedisRepositoriesAutoConfiguration
它實(shí)現(xiàn)了spring-data規(guī)范,其實(shí)就是把redis以數(shù)據(jù)庫(kù)dao的形式來(lái)訪問,這個(gè)東西相對(duì)就比較復(fù)雜了,但是在實(shí)際中使用的并不是很多,我們只說(shuō)一下如何使用。
首先定義一個(gè)dao,需要繼承CrudRepository:
@Repository public interface UserDao extends CrudRepository<UserEntity,Long> { }定義一個(gè)數(shù)據(jù)庫(kù)實(shí)體:
@RedisHash("user") public class UserEntity {@Idprivate Long id;private String username;private String password; }@RedisHash("user")會(huì)把user對(duì)象存儲(chǔ)到一個(gè)key是user:id的hash中,比如:
定義service和controller:
@Service public class UserService {@Autowiredprivate UserDao userDao;public UserEntity save(UserEntity userEntity){userDao.save(userEntity);return userEntity;}public UserEntity findById(Long id){Optional<UserEntity> optional = userDao.findById(id);return optional.isPresent()?optional.get():null;} } @RestController public class UserController {@Autowiredprivate UserService userService;private static AtomicLong id = new AtomicLong(0);@GetMapping("/add_user")public String addUser(String username, String password){long idLong = id.incrementAndGet();userService.save(new UserEntity(idLong, username, password));UserEntity entity = userService.findById(idLong);return entity.toString();} }總結(jié)一下
- 1.spring-boot-starter-data-redis默認(rèn)是使用lettuce去訪問redis
- 2.內(nèi)置了StringRedisTemplate和RedisTemplate,應(yīng)用可以直接使用。當(dāng)存取對(duì)象的時(shí)候,StringRedisTemplate需要手動(dòng)把對(duì)象轉(zhuǎn)化成String,RedisTemplate雖然可以直接存取對(duì)象,但是需要對(duì)象實(shí)現(xiàn)Serializable接口,同時(shí)在redis庫(kù)中的可讀性比較差。
- 3.由于存在以上的缺點(diǎn),因此可以把這兩個(gè)template的優(yōu)點(diǎn)給融合到一起,既可以直接存取對(duì)象,還可以方便人類閱讀,當(dāng)然也可以存取List和基本類型,更重要的是還可以支持給key統(tǒng)一添加前綴,趕快來(lái)使用吧:github地址:https://github.com/xjs1919/redis-client。
歡迎掃碼查看更多文章:
總結(jié)
以上是生活随笔為你收集整理的redistemplate使用_spring-boot-starter-data-redis源码解析与使用实战的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【请收藏】自动化构建部署之Travis
- 下一篇: 计算机应用基础word试题,计算机应用基