Redis-SpringBoot整合(注解和模板)
Posted wqq-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis-SpringBoot整合(注解和模板)相关的知识,希望对你有一定的参考价值。
SpringBoot中使用Redis的两种方式:RedisTemplate, 注解
这里使用的是IDEA, 项目为maven风格的SpringBoot
一.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.properties
在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为保存在数据库中的数值
以上是关于Redis-SpringBoot整合(注解和模板)的主要内容,如果未能解决你的问题,请参考以下文章