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源码解析与使用实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【请收藏】自动化构建部署之Travis
- 下一篇: 计算机应用基础word试题,计算机应用基