RedisTemplate在项目中的应用
RedisTemplate在項(xiàng)目中的應(yīng)用
如下主要通去年無聊做的 "涂涂影院后臺(tái)管理系統(tǒng)" 一個(gè) demo,看 RedisTemplate 的使用。
主要用到地方:視頻首頁輪播圖的獲取,以及搜索檢索界面,如下圖所示:
由于是非maven非springboot項(xiàng)目,故配置有所繁瑣,但正所謂有繁才有簡,在下面會(huì)帶大家看一下springboot中配置redis是怎樣簡單。
好了,先回到 "涂涂影院" 來吧。
本項(xiàng)目環(huán)境
√開發(fā)工具:Eclipse
√JDK:1.8
√Redis;
eclipse中截圖相信非springboot項(xiàng)目里的配置大家都應(yīng)該很熟悉吧,主要就是配置繁瑣的 xml,搭建一個(gè) ssm 項(xiàng)目可參考之前的例子:SSM(Spring+SpringMVC+Mybatis)框架環(huán)境搭建
1、spring-redis.xml
<beans?xmlns="http://www.springframework.org/schema/beans"
???????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
???????xmlns:context="http://www.springframework.org/schema/context"
???????xsi:schemaLocation="http://www.springframework.org/schema/beans
????????http://www.springframework.org/schema/beans/spring-beans.xsd?
????????http://www.springframework.org/schema/context?
????????http://www.springframework.org/schema/context/spring-context.xsd">
????<!--?緩存的層級(jí)-->
?????<context:component-scan?base-package="com.jeenotes.common.cache"?/>
?????<!--?配置?讀取properties文件?jeenotes.properties?-->
????<context:property-placeholder?location="classpath:resources/jeenotes.properties"??ignore-unresolvable="true"/>
????<!--?Redis?配置?-->
????<bean?id="jedisPoolConfig"?class="redis.clients.jedis.JedisPoolConfig">
????????<!--?控制一個(gè)pool可分配多少個(gè)jedis實(shí)例?-->
????????<property?name="maxTotal"?value="${redis.pool.maxTotal}"?/><!--??-->
????????<!--?連接池中最多可空閑maxIdle個(gè)連接?,這里取值為20,表示即使沒有數(shù)據(jù)庫連接時(shí)依然可以保持20空閑的連接,
???????????????而不被清除,隨時(shí)處于待命狀態(tài)。?-->
????????<property?name="maxIdle"?value="${redis.pool.maxIdle}"?/><!--??-->
????????<!--?最大等待時(shí)間:當(dāng)沒有可用連接時(shí),連接池等待連接被歸還的最大時(shí)間(以毫秒計(jì)數(shù)),超過時(shí)間則拋出異常?-->
????????<property?name="maxWaitMillis"?value="${redis.pool.maxWaitMillis}"?/><!--??-->
????????<!--?在獲取連接的時(shí)候檢查有效性?-->
????????<property?name="testOnBorrow"?value="${redis.pool.testOnBorrow}"?/><!--??-->
????</bean>
????<!--?redis單節(jié)點(diǎn)數(shù)據(jù)庫連接配置?-->
????<!--?Spring-redis連接池管理工廠?-->??
????<bean?id="jedisConnectionFactory"?class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
????????<property?name="hostName"?value="${redis.ip}"?/><!--??-->
????????<property?name="port"?value="${redis.port}"?/><!--??-->
????????<property?name="password"?value="${redis.pass}"?/><!--??-->
????????<property?name="poolConfig"?ref="jedisPoolConfig"?/>
????</bean>?
????<!--?redisTemplate配置,redisTemplate是對(duì)Jedis的對(duì)redis操作的擴(kuò)展,有更多的操作,
???????????封裝使操作更便捷?-->
????<!--?SDR默認(rèn)采用的序列化策略有兩種,一種是String的序列化策略,一種是JDK的序列化策略。
????????StringRedisTemplate默認(rèn)采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。
????????RedisTemplate默認(rèn)采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。
????????????????????就是因?yàn)樾蛄谢呗缘牟煌?#xff0c;即使是同一個(gè)key用不同的Template去序列化,結(jié)果是不同的。
????????????????????所以根據(jù)key去刪除數(shù)據(jù)的時(shí)候就出現(xiàn)了刪除失敗的問題。?
?????-->
????<!--?redis?序列化策略?,通常情況下key值采用String序列化策略,?-->
????<!--?如果不指定序列化策略,StringRedisTemplate的key和value都將采用String序列化策略;?-->
????<!--?但是RedisTemplate的key和value都將采用JDK序列化?這樣就會(huì)出現(xiàn)采用不同template保存的數(shù)據(jù)不能用同一個(gè)template刪除的問題?-->
????<bean?id="redisTemplate"?class="org.springframework.data.redis.core.StringRedisTemplate">
????????<property?name="connectionFactory"?ref="jedisConnectionFactory"?/>
????????<!--?我們通常所用的序列化操作:
????????????????JDK的序列化——類上implements?Serializable接口
????????????????XML和Json
????????????????protocol?buffer(簡稱protobuf)Google的、?本項(xiàng)目采用中-->
????????<!--?<property?name="keySerializer"?ref="stringRedisSerializer"?/>
????????<property?name="hashKeySerializer"?ref="stringRedisSerializer"?/>
????????<property?name="valueSerializer"?ref="stringRedisSerializer"/>?-->
????</bean>
</beans>
注釋比較詳細(xì),簡要概述,jedisPoolConfig 用來配置 redis 連接池的一些配置,JedisConnectionFactory 則作為連接池的工廠類;還記得上文中提到的 redis 序列化問題嗎?上邊配置中(StringRedisTemplate)正是用到了 String 序列化策略。
2、RedisCache.java
/**?*?redis緩存
?*?
?*?@author?niceyoo
?*
?*/
public?class?RedisCache?{
????public?final?static?String?CAHCENAME="cache";//緩存名
????public?final?static?int?CAHCETIME=300;//默認(rèn)緩存時(shí)間???以秒計(jì)算的
????
????private?RedisTemplate<String,?String>?redisTemplate;
????public?<T>?boolean?putCache(String?key,?T?obj)?{
????????final?byte[]?bkey?=?key.getBytes();
????????final?byte[]?bvalue?=?ProtoStuffSerializerUtil.serialize(obj);
????????boolean?result?=?redisTemplate.execute(new?RedisCallback<Boolean>()?{
????????????
????????????public?Boolean?doInRedis(RedisConnection?connection)?throws?DataAccessException?{
????????????????return?connection.setNX(bkey,?bvalue);
????????????}
????????});
????????return?result;
????}
????public?<T>?void?putCacheWithExpireTime(String?key,?T?obj,?final?long?expireTime)?{
????????final?byte[]?bkey?=?key.getBytes();
????????final?byte[]?bvalue?=?ProtoStuffSerializerUtil.serialize(obj);
????????redisTemplate.execute(new?RedisCallback<Boolean>()?{
????????????
????????????public?Boolean?doInRedis(RedisConnection?connection)?throws?DataAccessException?{
????????????????connection.setEx(bkey,?expireTime,?bvalue);
????????????????return?true;
????????????}
????????});
????}
????public?<T>?boolean?putListCache(String?key,?List<T>?objList)?{
????????final?byte[]?bkey?=?key.getBytes();
????????final?byte[]?bvalue?=?ProtoStuffSerializerUtil.serializeList(objList);
????????boolean?result?=?redisTemplate.execute(new?RedisCallback<Boolean>()?{
????????????
????????????public?Boolean?doInRedis(RedisConnection?connection)?throws?DataAccessException?{
????????????????return?connection.setNX(bkey,?bvalue);
????????????}
????????});
????????return?result;
????}
????public?<T>?boolean?putListCacheWithExpireTime(String?key,?List<T>?objList,?final?long?expireTime)?{
????????final?byte[]?bkey?=?key.getBytes();
????????final?byte[]?bvalue?=?ProtoStuffSerializerUtil.serializeList(objList);
????????boolean?result?=?redisTemplate.execute(new?RedisCallback<Boolean>()?{
????????????
????????????public?Boolean?doInRedis(RedisConnection?connection)?throws?DataAccessException?{
????????????????connection.setEx(bkey,?expireTime,?bvalue);
????????????????return?true;
????????????}
????????});
????????return?result;
????}
????public?<T>?T?getCache(final?String?key,?Class<T>?targetClass)?{
????????byte[]?result?=?redisTemplate.execute(new?RedisCallback<byte[]>()?{
????????????
????????????public?byte[]?doInRedis(RedisConnection?connection)?throws?DataAccessException?{
????????????????return?connection.get(key.getBytes());
????????????}
????????});
????????if?(result?==?null)?{
????????????return?null;
????????}
????????return?ProtoStuffSerializerUtil.deserialize(result,?targetClass);
????}
????public?<T>?List<T>?getListCache(final?String?key,?Class<T>?targetClass)?{
????????byte[]?result?=?redisTemplate.execute(new?RedisCallback<byte[]>()?{
????????????
????????????public?byte[]?doInRedis(RedisConnection?connection)?throws?DataAccessException?{
????????????????return?connection.get(key.getBytes());
????????????}
????????});
????????if?(result?==?null)?{
????????????return?null;
????????}
????????return?ProtoStuffSerializerUtil.deserializeList(result,?targetClass);
????}
????/**
?????*?精確刪除key
?????*?
?????*?@param?key
?????*/
????public?void?deleteCache(String?key)?{
????????redisTemplate.delete(key);
????}
????/**
?????*?模糊刪除key
?????*?
?????*?@param?pattern
?????*/
????public?void?deleteCacheWithPattern(String?pattern)?{
????????Set<String>?keys?=?redisTemplate.keys(pattern);
????????redisTemplate.delete(keys);
????}
????/**
?????*?清空所有緩存
?????*/
????public?void?clearCache()?{
????????deleteCacheWithPattern(RedisCache.CAHCENAME+"|*");
????}
}
RedisCache.java 實(shí)現(xiàn)了對(duì)對(duì)數(shù)據(jù)增刪改查的幾種方法,如何使用呢?
我們以首頁的輪播圖為例:
在需要使用的類中注入該組件:
看一下如下方法:
public?ResultMobileBannerBean?huandeng(Model?model)?{
????String?cache_key?=?RedisCache.CAHCENAME?+?"|getPcHomeHuanDengList";
????ResultMobileBannerBean?result_cache?=?cache.getCache(cache_key,?ResultMobileBannerBean.class);
????if(result_cache?!=?null){
????????return?result_cache;
????}
????ResultMobileBannerBean?bannerBean?=?new?ResultMobileBannerBean();
????bannerBean.setCode("000000");
????List<HomeBanner>?homeBannerList?=?homeManagerService.findMobileHomeBannerList();
????bannerBean.setBannerList(homeBannerList);
????cache.putCacheWithExpireTime(cache_key,?bannerBean,?RedisCache.CAHCETIME);
????return?bannerBean;
}
主要是 ResultMobileBannerBean result_cache = cache.getCache(cache_key, ResultMobileBannerBean.class); 在去數(shù)據(jù)庫請(qǐng)求數(shù)據(jù)之前,先去 redis 中讀取緩存信息,如果返回的數(shù)據(jù)非空的話,則返回該數(shù)據(jù),否則去數(shù)據(jù)庫查詢數(shù)據(jù),查詢后在存放在 redis 中。
項(xiàng)目源碼:https://gitee.com/niceyoo/jeenotes-ssm.git
springboot 中是如何引用 redis 的呢?
1、maven依賴
<!--?Redis--><dependency>
????<groupId>org.springframework.boot</groupId>
????<artifactId>spring-boot-starter-redis</artifactId>
????<version>1.4.7.RELEASE</version>
</dependency>
<!--?Gson?可暫時(shí)忽略-->
<dependency>
????<groupId>com.google.code.gson</groupId>
????<artifactId>gson</artifactId>
????<version>2.8.5</version>
</dependency>
2、yml配置信息
spring:??#?Redis
??redis:
????host:?127.0.0.1
????password:
????#?數(shù)據(jù)庫索引?默認(rèn)0
????database:?0
????port:?6379
????#?超時(shí)時(shí)間?Duration類型?3秒
????timeout:?3S
3、項(xiàng)目中引用
private?StringRedisTemplate?redisTemplate;
(value?=?"/getByParentId/{parentId}",?method?=?RequestMethod.GET)
(value?=?"通過parentId獲取")
public?Result<List<Department>>?getByParentId(?String?parentId,
??????????????????????????????????????????????("是否開始數(shù)據(jù)權(quán)限過濾")?(required?=?false,?defaultValue?=?"true")?Boolean?openDataFilter){
????List<Department>?list?=?new?ArrayList<>();
????User?u?=?securityUtil.getCurrUser();
????String?key?=?"department::"+parentId+":"+u.getId()+"_"+openDataFilter;
????String?v?=?redisTemplate.opsForValue().get(key);
????if(StrUtil.isNotBlank(v)){
????????list?=?new?Gson().fromJson(v,?new?TypeToken<List<Department>>(){}.getType());
????????return?new?ResultUtil<List<Department>>().setData(list);
????}
????list?=?departmentService.findByParentIdOrderBySortOrder(parentId,?openDataFilter);
????list?=?setInfo(list);
????redisTemplate.opsForValue().set(key,
????????????new?GsonBuilder().registerTypeAdapterFactory(HibernateProxyTypeAdapter.FACTORY).create().toJson(list));
????return?new?ResultUtil<List<Department>>().setData(list);
}
RedisTemplate 定義了 5 種數(shù)據(jù)結(jié)構(gòu)操作:
最優(yōu)補(bǔ)充
從上文可看出 RedisTemplate 在 springboot 中應(yīng)用尤為簡單,所以趕快切到 springboot 中吧~
如果文章有錯(cuò)的地方歡迎指正,大家互相留言交流。習(xí)慣在微信看技術(shù)文章,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號(hào):niceyoo
posted @ 2019-05-07 23:47 niceyoo 閱讀(...) 評(píng)論(...) 編輯 收藏總結(jié)
以上是生活随笔為你收集整理的RedisTemplate在项目中的应用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hadoop HBase概念学习系列之H
- 下一篇: MySQL+Amoeba实现数据库主从复