日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

redistemplate使用_spring-boot-starter-data-redis源码解析与使用实战

發布時間:2025/3/15 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redistemplate使用_spring-boot-starter-data-redis源码解析与使用实战 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們以spring-boot-starter-data-redis-2.1.7為例,starter本身沒有包含任何代碼,只是引入了spring-data-redis的依賴,因此肯定是在spring-boot-autoconfigure中加了自動配置:

我們就看下這幾個配置類:

其中RedisAutoConfiguration里面就配置了我們常用的RedisTemplate,RedisRepositoriesAutoConfiguration這里面是實現了spring-data規范的一些配置,RedisReactiveAutoConfiguration是當需要用Reactive方式編程的時候用的,本文忽略。

RedisAutoConfiguration

@Configuration @ConditionalOnClass(RedisOperations.class) @EnableConfigurationProperties(RedisProperties.class) //內置了對lettuce和jedis的支持 //但是默認只添加了lettuce的依賴,因此默認是使用的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;} }

這里面內置了對lettuce和jedis的支持,因為默認是引入的lettuce的jar,因此默認會使用lettuce去訪問redis,同時這里面創建了一個RedisTemplate和一個StringRedisTemplate,一般我們經常會直接注入StringRedisTemplate來訪問redis。

首先看下StringRedisTemplate:

public StringRedisTemplate() {setKeySerializer(RedisSerializer.string());setValueSerializer(RedisSerializer.string());setHashKeySerializer(RedisSerializer.string());setHashValueSerializer(RedisSerializer.string()); }

從名字也可以看出來,它在序列化key、value、hash key和hash value的時候都是轉化成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)); }

一眼就能明白,沒什么好說的。但是很顯然,它只能處理String類型,如果是對象得需要自己手動轉化成String才可以,一般我們會把對象轉化成json字符串存儲到redis里面。

我們回頭再來看下RedisTemplate,RedisTemplate#afterPropertiesSet:

@Overridepublic void afterPropertiesSet() {boolean defaultUsed = false;//判斷是否幽默ren的序列化器if (defaultSerializer == null) {//默認是采用jdk自帶的序列化,//也就是說必須得實現Serializable接口才行defaultSerializer = new JdkSerializationRedisSerializer(classLoader != null ? classLoader : this.getClass().getClassLoader());}//默認j就是啟用的if (enableDefaultSerializer) {//key、value、hash key、hash value都使用默認的那個序列化器 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;}}。。。}

從名字也可以看出來,RedisTemplate默認是采用JDK自帶的序列化方式來做序列化器,看一下:

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來讀寫對象,因此對象必須得實現Serializable接口才可以,最終是以二進制的格式存儲到redis里面,比如:

很顯然,這種序列化方式的可讀性太不友好了。

RedisRepositoriesAutoConfiguration

它實現了spring-data規范,其實就是把redis以數據庫dao的形式來訪問,這個東西相對就比較復雜了,但是在實際中使用的并不是很多,我們只說一下如何使用。

首先定義一個dao,需要繼承CrudRepository:

@Repository public interface UserDao extends CrudRepository<UserEntity,Long> { }

定義一個數據庫實體:

@RedisHash("user") public class UserEntity {@Idprivate Long id;private String username;private String password; }

@RedisHash("user")會把user對象存儲到一個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();} }

總結一下

- 1.spring-boot-starter-data-redis默認是使用lettuce去訪問redis

- 2.內置了StringRedisTemplate和RedisTemplate,應用可以直接使用。當存取對象的時候,StringRedisTemplate需要手動把對象轉化成String,RedisTemplate雖然可以直接存取對象,但是需要對象實現Serializable接口,同時在redis庫中的可讀性比較差。

- 3.由于存在以上的缺點,因此可以把這兩個template的優點給融合到一起,既可以直接存取對象,還可以方便人類閱讀,當然也可以存取List和基本類型,更重要的是還可以支持給key統一添加前綴,趕快來使用吧:github地址:https://github.com/xjs1919/redis-client。

歡迎掃碼查看更多文章:

總結

以上是生活随笔為你收集整理的redistemplate使用_spring-boot-starter-data-redis源码解析与使用实战的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。