參考博客:http://www.cnblogs.com/ashleyboy/p/9595584.htmlhtml
參考學習網站:how2java.cnjava
SpringBoot中使用Redis的兩種方式:RedisTemplate, 註解redis
這裏使用的是IDEA, 項目爲maven風格的SpringBootspring
一.pom.xml依賴:數據庫
添加Redis依賴和JPA依賴數組
這裏我開始犯了個錯誤,就是沒有依賴jpa包,致使沒法使用RedisTemplate類緩存
<!--Redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- jpa--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
二.application.propertiesspringboot
在application.properties中添加Redis數據庫的配置信息,使得能夠訪問Redis數據庫服務器
################################Redis配置##################################
#Redis數據庫索引
spring.redis.database=0
#Redis服務器地址
spring.redis.host=127.0.0.1
#Redis服務器鏈接端口
spring.redis.port=6379
#Redis服務器鏈接密碼
spring.redis.password=
#鏈接池最大鏈接數
spring.redis.jedis.pool.max-active=20
#鏈接池中的最大空閒鏈接
spring.redis.jedis.pool.min-idle=5
#鏈接超時時間(毫秒)
spring.redis.timeout=2000
_________________________________________________________________________數據結構
經過Redis進行數據緩存的方式有兩種,
一種是使用Redis模板進行數據緩存,
一種是經過註解,讓Spring框架自動進行數據緩存
首先是第一種, 使用RedisTemplate編寫RedisUtil工具,來進行數據緩存操做
三.使用RedisTemplate模板進行數據操做
完成上面的配置以後,其實就能夠直接使用RedisTemplate模板操做數據了
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest @WebAppConfiguration public class SpringbootApplicationTests { @Autowired private StringRedisTemplate stringRedisTemplate; @Test public void contextLoads() { stringRedisTemplate.opsForValue().set("test","123"); String test = stringRedisTemplate.opsForValue().get("test"); System.out.println(test); } }
四.自定義RedisTemplate
若使用默認的RedisTemplate配置,其泛型爲RedisTemplate<Object,Object>, 不方便保存對象
這時就要自定義模板和序列化處理程序,使得Redis可以保存對象
@Bean public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){ RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory);//設置連接工廠 RedisSerializer stringSerializer = new StringRedisSerializer();//初始化string序列化器 redisTemplate.setKeySerializer(stringSerializer);//設置key使用string序列化方式 redisTemplate.setHashKeySerializer(stringSerializer);//設置哈希鍵使用string的序列化方式 //使用Jackson2JsonRedisSerializer來序列化和反序列化redis的value值(默認使用JDK的序列化方式) Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //初始化jackson序列化方式 ObjectMapper om = new ObjectMapper(); // 指定要序列化的域,field,get和set,以及修飾符範圍,ANY是都有包括private和public om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.PUBLIC_ONLY); // 指定序列化輸入的類型,類必須是非final修飾的,final修飾的類,好比String,Integer等會跑出異常 om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//設置 redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); return redisTemplate; }
五.自定義RedisUtil
在完成上面的自定義配置後,就可使用RedisTemplate來寫操做Redis的工具了
此段參考:https://www.jianshu.com/p/b9154316227e
1 package com.springboottest.springboot.util; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.data.redis.core.RedisTemplate; 5 import org.springframework.data.redis.core.StringRedisTemplate; 6 import org.springframework.stereotype.Component; 7 import org.springframework.util.CollectionUtils; 8 9 import java.util.List; 10 import java.util.Map; 11 import java.util.Set; 12 import java.util.concurrent.TimeUnit; 13 14 /** 15 * Redis工具 16 * 17 */ 18 19 @Component 20 public class RedisUtil { 21 @Autowired 22 RedisTemplate<String,Object> redisTemplate; 23 24 @Autowired 25 StringRedisTemplate stringRedisTemplate; 26 27 //=========================common============================= 28 /** 29 * 指定緩存失效時間 30 * @param key 鍵 31 * @param time 時間(秒) 32 * @return 33 */ 34 public boolean expire(String key,long time){ 35 try{ 36 if(time>0) 37 redisTemplate.expire(key,time, TimeUnit.SECONDS); 38 return true; 39 }catch (Exception e){ 40 e.printStackTrace(); 41 return false; 42 } 43 } 44 45 /** 46 * 判斷key是否存在 47 * @param key 鍵 48 * @return true 存在 false 不存在 49 */ 50 public boolean hasKey(String key){ 51 try{ 52 return redisTemplate.hasKey(key); 53 }catch (Exception e){ 54 e.printStackTrace(); 55 return false; 56 } 57 } 58 59 /** 60 * 刪除緩存 61 * @param key 能夠傳一個值或多個 62 */ 63 @SuppressWarnings("unchecked") 64 public void del(String... key){ 65 if(key!=null && key.length>0){ 66 if(key.length==1) //若是參數只有一個 67 redisTemplate.delete(key[0]); //刪除第一個 68 else 69 redisTemplate.delete(CollectionUtils.arrayToList(key)); //不止一個參數,則將其數組轉化成List傳遞進方法 70 } 71 } 72 73 //=========================string============================= 74 /** 75 * 普通緩存獲取 76 * @param key 鍵 77 * @return 值 78 */ 79 public Object get(String key){ 80 return key==null?null:redisTemplate.opsForValue().get(key); 81 } 82 83 /** 84 * 普通緩存放入 85 * @param key 鍵 86 * @param value 值 87 * @return true 成功 false 失敗 88 */ 89 public boolean set(String key,Object value){ 90 try{ 91 redisTemplate.opsForValue().set(key,value); 92 return true; 93 }catch (Exception e){ 94 e.printStackTrace(); 95 return false; 96 } 97 } 98 99 /** 100 * 普通緩存放入並設置時間 101 * @param key 鍵 102 * @param value 值 103 * @param time 時間(秒) time要大於0,若是小於或等於0,則設置無期限 104 * @return boolean 105 */ 106 public boolean set(String key,Object value,long time){ 107 try{ 108 if(time>0) 109 redisTemplate.opsForValue().set(key,value,time,TimeUnit.SECONDS); 110 else 111 set(key,value); 112 return true; 113 }catch (Exception e){ 114 e.printStackTrace(); 115 return false; 116 } 117 } 118 119 /** 120 * 遞增 121 * @param key 鍵 122 * @param delta 要增長多少 123 * @return 124 */ 125 public long incr(String key,long delta){ 126 if(delta<0) 127 throw new RuntimeException("遞增因子必須大於0"); 128 return redisTemplate.opsForValue().increment(key,delta); 129 } 130 131 /** 132 * 遞減 133 * @param key 鍵 134 * @param delta 要減小多少 135 * @return 136 */ 137 public long decr(String key,long delta){ 138 if(delta<0) 139 throw new RuntimeException("遞減因子必須大於0"); 140 return redisTemplate.opsForValue().decrement(key,delta); 141 } 142 143 //=====================================Map============================ 144 /** 145 * HashGet 146 * @param key 鍵 不能爲null 147 * @param item 項 不能爲null 148 * @return 值 149 */ 150 public Object hget(String key,String item){ 151 return redisTemplate.opsForHash().get(key,item); 152 } 153 154 /** 155 * 獲取hashKey對應的全部鍵值 156 * @param key 鍵 157 * @return 對應的多個鍵值 158 */ 159 public Map<Object,Object> hmget(String key){ 160 return redisTemplate.opsForHash().entries(key); 161 } 162 163 /** 164 * HashSet 165 * @param key 鍵 166 * @param map 對應多個鍵值 167 * @return boolean 168 */ 169 public boolean hmset(String key,Map<String,Object> map){ 170 try{ 171 redisTemplate.opsForHash().putAll(key,map); 172 return true; 173 }catch (Exception e){ 174 e.printStackTrace(); 175 return false; 176 } 177 } 178 179 /** 180 * HashSet 並設置時間 181 * @param key 鍵 182 * @param map 多個鍵值對 183 * @param time 時間(秒) 184 * @return boolean 185 */ 186 public boolean hmset(String key,Map<String,Object> map,long time){ 187 try{ 188 redisTemplate.opsForHash().putAll(key,map); 189 if(time>0) 190 expire(key,time); //若是時間大於0,設置這個鍵中的數據保存時長爲time秒 191 return true; 192 }catch (Exception e){ 193 e.printStackTrace(); 194 return false; 195 } 196 } 197 198 /** 199 * 向一張hash表中放入數據,若是不存在將建立 200 * @param key 鍵 201 * @param item 項 202 * @param value 值 203 * @return boolean 204 */ 205 public boolean hset(String key,String item,Object value){ 206 try{ 207 redisTemplate.opsForHash().put(key,item,value); 208 return true; 209 }catch (Exception e){ 210 e.printStackTrace(); 211 return false; 212 } 213 } 214 215 /** 216 * 向一張hash表中放入數據,若是不存在將建立並設置表的時間 217 * @param key 鍵 218 * @param item 項 219 * @param value 值 220 * @param time 時間(秒), 若是已存在的hash表有時間,則會替代原有的時間 221 * @return boolean 222 */ 223 public boolean hset(String key,String item,Object value,long time){ 224 try{ 225 redisTemplate.opsForHash().put(key,item,value); 226 if(time>0) 227 expire(key,time); 228 return true; 229 }catch (Exception e){ 230 e.printStackTrace(); 231 return false; 232 } 233 } 234 235 /** 236 * 刪除hash表中的值 237 * @param key 鍵 不能爲null 238 * @param item 項 能夠是多個,不能爲Null 239 */ 240 public void hdel(String key,Object... item){ 241 redisTemplate.opsForHash().delete(key,item); 242 } 243 244 /** 245 * 判斷hash表中是否有該項的值 246 * @param key 鍵 不能爲null 247 * @param item 項 不能爲Null 248 * @return 249 */ 250 public boolean hHasKey(String key,String item){ 251 return redisTemplate.opsForHash().hasKey(key,item); 252 } 253 254 /** 255 * hash遞增 若是不存在,就建立一個 並把新增後的值返回 256 * @param key 鍵 257 * @param item 項 258 * @param delta 增長多少 259 * @return 260 */ 261 public double hincr(String key,String item,double delta){ 262 if (delta<0) 263 return delta; 264 else 265 return redisTemplate.opsForHash().increment(key,item,delta); 266 } 267 268 /** 269 * hash遞減 270 * @param key 271 * @param item 272 * @param delta 273 */ 274 public double hdecr(String key,String item,double delta){ 275 if (delta<0) 276 return delta; 277 else 278 return redisTemplate.opsForHash().increment(key,item,-delta); 279 } 280 281 //=================================set============================== 282 /** 283 * 根據key獲取set中的值 284 * @param key 285 * @return 286 */ 287 public Set<Object> sget(String key){ 288 try{ 289 return redisTemplate.opsForSet().members(key); 290 }catch (Exception e){ 291 e.printStackTrace(); 292 return null; 293 } 294 } 295 296 /** 297 * 根據value從一個set中查詢,是否存在 298 * @param key 299 * @param value 300 * @return 301 */ 302 public boolean sHasKey(String key,Object value){ 303 try{ 304 return redisTemplate.opsForSet().isMember(key,value); 305 }catch (Exception e){ 306 e.printStackTrace(); 307 return false; 308 } 309 } 310 311 /** 312 * 將數據放入set緩存 313 * @param key 鍵 314 * @param values 值 能夠是多個 315 * @return 成功個數 316 */ 317 public long sSet(String key,Object... values){ 318 try{ 319 return redisTemplate.opsForSet().add(key,values); 320 }catch (Exception e){ 321 e.printStackTrace(); 322 return 0; 323 } 324 } 325 326 /** 327 * 將set數據放入緩存 328 * @param key 鍵 329 * @param time 時間 330 * @param values 值 能夠是多個 331 * @return 332 */ 333 public long sSet(String key,long time,Object... values){ 334 try { 335 Long count = redisTemplate.opsForSet().add(key,values); 336 if(time>0) 337 expire(key,time); 338 return count; 339 }catch (Exception e){ 340 e.printStackTrace(); 341 return 0; 342 } 343 } 344 345 /** 346 * 獲取set緩存的長度 347 * @param key 348 * @return 349 */ 350 public long sGetSetSize(String key){ 351 try{ 352 return redisTemplate.opsForSet().size(key); 353 }catch (Exception e){ 354 e.printStackTrace(); 355 return 0; 356 } 357 } 358 359 /** 360 * 移除值爲value的 361 * @param key 362 * @param values 值 能夠是多個 363 * @return 364 */ 365 public long setRemove(String key,Object... values){ 366 try{ 367 long count = redisTemplate.opsForSet().remove(key,values); 368 return count; 369 }catch (Exception e){ 370 e.printStackTrace(); 371 return 0; 372 } 373 } 374 375 //===============================List=============================== 376 377 /** 378 * 獲取list緩存的內容 379 * @param key 鍵 380 * @param start 開始 381 * @param end 結束 0到-1表明全部值 382 */ 383 public List<Object> lGet(String key,long start,long end){ 384 try{ 385 return redisTemplate.opsForList().range(key,start,end); 386 }catch (Exception E){ 387 E.printStackTrace(); 388 return null; 389 } 390 } 391 392 /** 393 * 獲取list緩存的長度 394 * @param key 395 * @return long 396 */ 397 public long lGetSize(String key){ 398 try{ 399 return redisTemplate.opsForList().size(key); 400 }catch (Exception e){ 401 e.printStackTrace(); 402 return 0; 403 } 404 } 405 406 /** 407 * 經過索引 獲取list的值 408 * @param key 409 * @param index 索引 index>=0時,0表頭,1第二個元素 index<0時 -1表尾 -2倒數第二個 410 */ 411 public Object lGetIndex(String key,long index){ 412 try{ 413 return redisTemplate.opsForList().index(key,index); 414 }catch (Exception e){ 415 e.printStackTrace(); 416 return null; 417 } 418 } 419 420 /** 421 * 將鍵值對放入list緩存 422 * @param key 鍵 423 * @param value 值 424 */ 425 public boolean lSet(String key,Object value){ 426 try{ 427 redisTemplate.opsForList().rightPush(key,value); 428 return true; 429 }catch (Exception e){ 430 e.printStackTrace(); 431 return false; 432 } 433 } 434 435 /** 436 * 將list放入緩存 437 * @param key 438 * @param value 439 */ 440 public boolean lSet(String key,List<Object> value){ 441 try{ 442 redisTemplate.opsForList().rightPushAll(key,value); 443 return true; 444 }catch (Exception e){ 445 e.printStackTrace(); 446 return false; 447 } 448 } 449 450 /** 451 * 將list放入緩存 452 * @param key 鍵 453 * @param value 值 454 * @param time 時間(秒) 455 */ 456 public boolean lSet(String key,List<Object> value,long time){ 457 try{ 458 redisTemplate.opsForList().rightPushAll(key,value); 459 if(time>0) 460 expire(key,time); 461 return true; 462 }catch (Exception e){ 463 e.printStackTrace(); 464 return false; 465 } 466 } 467 468 /** 469 * 根據索引修改list中的某條數據 470 * @param key 鍵 471 * @param index 472 * @param value 473 */ 474 public boolean lUpdateIndex(String key,long index,Object value){ 475 try{ 476 redisTemplate.opsForList().set(key,index,value); 477 return true; 478 }catch (Exception e){ 479 e.printStackTrace(); 480 return false; 481 } 482 } 483 484 /** 485 * 移除N個值爲value 486 * @param key 487 * @param count 488 * @param value 489 * @return 移除的個數 490 */ 491 public long lRemove(String key,long count,Object value){ 492 try{ 493 long remove = redisTemplate.opsForList().remove(key,count,value); 494 return remove; 495 }catch (Exception e){ 496 e.printStackTrace(); 497 return 0; 498 } 499 } 500 }
測試一下其中的一些方法:
@RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest @WebAppConfiguration public class SpringbootApplicationTests { @Autowired private RedisUtil redisUtil; @Test public void contextLoads() { // Category category = new Category(); // category.setId(1); // category.setName("lala"); // redisUtil.lSet("list",category); Category c = (Category)redisUtil.lGetIndex("list",2); System.out.println(c); } }
這裏先是將Category類經過lSet()方法保存到Redis中,其鍵位"list"
而後經過lGetIndex()方法,獲取這個對象,並強轉爲Category,從而得到結果
Category[id=1,name=lala]
固然也能夠經過Redis客戶端,檢查是否有這個數據
127.0.0.1:6379> lrange list 0 3 1) "\"redis\"" 2) "\"redis\"" 3) "[\"com.springboottest.springboot.pojo.Category\",{\"id\":1,\"name\":\"lala\"}]"
參考:http://www.cnblogs.com/ashleyboy/p/9595584.html
StringRedisTemplate是Spring Boot內置的操做Redis的API實現類,另外還有一個API實現類是RedisTemplate。StringRedisTemplate的API假定全部的數據類型化都是字符類型,即key和value都是字符串類型,對於常見額SpringBoot應用系統,使用字符串操做也已經足夠了,並且能方便的經過客戶端管理工具管理。StringRedisTemplate繼承RedisTemplate,與RedisTemplate不一樣的是從新設置了序列化策略,使用StringRedisSerialier類來序列化key-value,包括List、Hash、Set等數據結構。
_________________________________________________________________________________________
除了使用Redis模板進行緩存外,還能夠經過指定Spring Cache緩存支持,經過註解進行緩存
六.自定義CacheManager
經過配置Spring的CacheManager爲Redis,來指定Redis作緩存
構造RedisCacheManager的方法有兩種
一種是靜態方法create得到 Spring默認配置的CacheManager
@Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisCacheManager cacheManager = RedisCacheManager.create(factory); return cacheManager; }
另外一種是經過RedisCacheManager構建器→builder(factory)方法,進行自定義配置後得到
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configmap)
.build();
此處給出完整代碼:
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory){
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
//生成一個默認配置,經過config對象便可對緩存進行自定義配置
config = config.entryTtl(Duration.ofMinutes(1)) //經過Duration,設置緩存的過時時間爲1分鐘
.disableCachingNullValues()//不緩存空值
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))//設置key序列化器
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()));//設置value序列化器
RedisCacheManager cacheManager = RedisCacheManager.builder(factory) //使用自定義的緩存配置初始化cacheManager
.cacheDefaults(config)
.build();
//RedisCacheManager redisCacheManager = RedisCacheManager.create(factory);
return cacheManager;
}
private RedisSerializer<String> keySerializer(){ return new StringRedisSerializer(); } private RedisSerializer<Object> valueSerializer(){ return new Jackson2JsonRedisSerializer(Object.class); }
七.在SpringBoot的主程序中加入@EnableCaching開啓緩存
@SpringBootApplication @EnableCaching public class SpringbootApplication { public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); } }
如下爲操做示例:
八.準備一個實體類,Mapper和Service
1.實體類
package com.springboottest.springboot.pojo; public class Person { private long id; private String name; private long age; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getAge() { return age; } public void setAge(long age) { this.age = age; } @Override public String toString(){ return "Person[id="+id+",name="+name+",age="+age+"]"; } }
2.Mapper
@Mapper @Component("personmapper") public interface PersonMapper { @Insert("insert into person_ (name,age) values(#{name},#{age})") public int add(Person person); @Select("select * from person_ where id = #{id}") public Person get(long id); }
3.Service
@Service @CacheConfig(cacheNames = "person") public class PersonService { @Autowired private PersonMapper personMapper; @Cacheable(cacheNames = "person1" ,key="#root.methodName+'['+#id+']'") public Person getPersonById(long id){ Person person = personMapper.get(id); return person; } }
九.準備 person_表
create table blood_( id BIGINT(11) PRIMARY key auto_increment, name VARCHAR(30) not null, age BIGINT(11) not null )ENGINE=INNODB
本人數據庫學得很差....這裏就隨便寫的數據建的
十.調用service中的getPersonById
經過調用service中的getPersonById, 從數據庫中得到Person的數據, 而後Spring框架會自動緩存數據到Redis中
這裏我用RedisClient界面查看的數據
能夠看到緩存後,保存到了Redis中的person1下
key爲person1::getPersonBtId[1]
value爲保存在數據庫中的數值