整合SpringBoot+Mysql+Redis實現緩存機制的一個Demo

  公司的項目中用到了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(); //ObjectMapperjackson的主要類,作用序列化
         mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); //設置任何字段可見
         mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); //反序列化
         serializer.setObjectMapper(mapper);

        template.setValueSerializer(serializer); //設置序列化反序列化redisvalue
         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刪除keyvalue
    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);
    }

    /*
    * 根據keyhashKey刪除value
    * @param key,hashKey
    * @return void
    * */
    public void deleteValueByKeyAndHashKey(String key,String hashKey){
        hashOperations.delete(key,hashKey);
    }

    /*
    * 判斷當前keyhashKey是否存在
    * @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---------------------------------------------------*/

}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章