公司的項目中用到了Redis,最近一直在學習這一塊。從開始學習到現在,總體給我的感覺是Redis上手比較容易,但是精通需要大量的實踐和研究的。好在我們公司對Redis的使用並不是那麼深入,目前只能進行些簡單的操作。總結這幾天的學習結果,記錄下來,希望有助於鞏固和提高。
說明:我的Redis服務是搭建在虛擬機Linux(Read Heat6.2)系統上的,Mysql數據庫安裝在本機,虛擬機的網絡連接模式爲橋接,和本機公用一個網段。網上有很多搭建的例子,這裏就不進行說明了。
首先是SpringBoot中的配置文件(application.yml類型的配置文件,該類型文件對書寫格式有嚴格的要求)
server: port: 8090 spring: datasource: url: jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true username: xxx password: xxx driver-class-name: com.mysql.jdbc.Driver test-on-borrow: false test-while-idel: true time-between-eviction-runs-millis: 3600000 tomcat: max-wait: 10000 max-active: 50 http: encoding: force: true jpa: hibernate: ddl-auto: update max_fetch_depth: 2 naming: physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl properties: hibernate: dialect: org.hibernate.dialect.MySQL5Dialect max_fetch_depth: 2 format_sql: true show-sql: true redis: host: xxx password: port: 6379 pool: # 連接池中的最大空閒連接 max-idle: 8 min-idle: 0 # 連接池最大連接數(使用負值表示沒有限制) max-active: 8 # 連接池最大阻塞等待時間(使用負值表示沒有限制) max-wait: 1 # 連接超時時間(毫秒) timeout: 60000
接下來是對Redis數據操作類的配置,提供了數據的序列化方式。Spring封裝了RedisTimplement對象來對Redis進行操作,該模板默認採用JdkSerializationRedisSerializer
的二進制序列化方式。
import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CachingConfigurerSupport; 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.HashOperations; import org.springframework.data.redis.core.ListOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration //標註一個配置類,交由spring管理 public class Config extends CachingConfigurerSupport{ /* *通過RedisConnectionFactory引入redis在配置文件中的連接配置 * */ @Autowired private RedisConnectionFactory factory; /* * 1.此處爲什麼要序列化 * 原因:普通的連接使用沒有辦法把Java對象直接存入Redis, * 而需要我們自己提供方案-對象序列化,然後存入redis, * 取回序列化內容後,轉換爲java對象 * */ @Bean public RedisTemplate<String,Object> redisTemplate(){ RedisTemplate<String,Object> template = new RedisTemplate<>(); initDomainRedisTemplate(template,factory); return template; } public void initDomainRedisTemplate(RedisTemplate template,RedisConnectionFactory factory){ template.setConnectionFactory(factory); //使用Jackson2JsonRedisSerializer來序列化和反序列化redis的 value 值 Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper mapper = new ObjectMapper(); //ObjectMapper是jackson的主要類,作用序列化 mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); //設置任何字段可見 mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); //反序列化 serializer.setObjectMapper(mapper); template.setValueSerializer(serializer); //設置序列化反序列化redis的value值 template.setKeySerializer(new StringRedisSerializer()); //設置序列化反序列化key值的方式爲String template.afterPropertiesSet(); //初始化操作,在設置完成後進行 } //實例化HashOperations對象,可以使用Hash類型操作 @Bean public HashOperations<String,String,Object> hashOperations(RedisTemplate<String,Object> redisTemplate){ return redisTemplate.opsForHash(); //opsForHash()該方法用於操作Hash } //實例化ListOperations對象,可以使用List類型操作 @Bean public ListOperations<String,Object> listOperations(RedisTemplate<String,Object> redisTemplate){ return redisTemplate.opsForList(); //opsForList()該方法用於操作List } }
然後就是對Redis數據進行操作的工具類了,在此列舉了三種數據類型,String、Hash、List
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.ListOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Component; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @Component public class RedisUtil { /* * 說明:個人總結爲redisTemplate可以處理redis中的所有數據類型。 * 但對於具體數據類型的處理,各種類型的接口處理起來更加方便, * 方法比較多 * */ @Autowired private RedisTemplate<String,Object> redisTemplate; @Autowired private HashOperations<String,String,Object> hashOperations; @Autowired private ListOperations<String,Object> listOperations; /*---------------------------------------------公共區域---------------------------------------------------*/ //判斷key是否存在 public boolean hasKey(String key){ return redisTemplate.hasKey(key); } //根據key刪除key和value public void deleteByKey(String key){ redisTemplate.delete(key); } /* * 設置key的有效期 * @param key,time(有效時間),unit(hours,days,minutes) * */ public void setExpire(String key,long time,TimeUnit unit){ if (time != -1){ redisTemplate.expire(key,time,unit); } } /*---------------------------------------------公共區域---------------------------------------------------*/ /*----------------------------------------------String-------------------------------------------------*/ //根據key獲取value值 public String getValue(String key){ return (String) redisTemplate.opsForValue().get(key); } //插入數據 public void setValue(String key,String value){ redisTemplate.opsForValue().set(key,value); } /*----------------------------------------------String------------------------------------------------*/ /*-----------------------------------------------hash--------------------------------------------------*/ //存入hash類型的值 public void addAllForHash(String key, Map<String,Object> map){ hashOperations.putAll(key,map); } /* * 根據key查詢該key對應map下的所有value * @param key * @return List<AllValue> * */ public List<Object> getAllValueForHash(String key){ return hashOperations.values(key); } //獲取Hash中的單個value public Object getValueForHash(String key, String hashKey){ return hashOperations.get(key,hashKey); } //獲取Hash數量 public Long getCount(String key){ return hashOperations.size(key); } /* * 根據key和hashKey刪除value * @param key,hashKey * @return void * */ public void deleteValueByKeyAndHashKey(String key,String hashKey){ hashOperations.delete(key,hashKey); } /* * 判斷當前key中hashKey是否存在 * @param key,hashKey * @return true / false * */ public boolean hasHashKey(String key,String hashKey){ return hashOperations.hasKey(key,hashKey); } /* * 查詢key下所有Hash值 * @param key * @return Map<key,value> * */ public Object getAllHashByKey(String key){ return hashOperations.entries(key); } /*-----------------------------------------------hash----------------------------------------------------*/ /*-----------------------------------------------list----------------------------------------------------*/ /* * 從list隊列尾部存數據 * @param key,List * @return null * */ public void rightPushAll(String key, List<String> values){ listOperations.rightPushAll(key,values); } /* * 從list隊列尾部存數據 * @param key,value * @return null * */ public void rightPush(String key, String value){ listOperations.rightPush(key,value); } /* *從list隊列中取出全部數據(0,listSize) * @param key * @return List * */ public List<Object> getListAll(String key){ return listOperations.range(key,0,listOperations.size(key)); } /*-----------------------------------------------list---------------------------------------------------*/ }