spring + redis 实现数据的缓存

简介:

1、实现目标

通过redis缓存数据。(目的不是加快查询的速度,而是减少数据库的负担)

2、所需jar包

注意:jdies和commons-pool两个jar的版本是有对应关系的,注意引入jar包是要配对使用,否则将会报错。因为commons-pooljar的目录根据版本的变化,目录结构会变。前面的版本是org.apache.pool,而后面的版本是org.apache.pool2…

style=”background-color: #0098dd; color: white; font-size: 17px; font-weight: bold;”3、redis简介

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)

4、编码实现

1)、配置的文件(properties)

将那些经常要变化的参数配置成独立的propertis,方便以后的修改

redis.properties

1
2
3
4
5
6
7
8
9
redis.hostName= 127.0 . 0.1
redis.port= 6379
redis.timeout= 15000
redis.usePool= true
  
redis.maxIdle= 6
redis.minEvictableIdleTimeMillis= 300000
redis.numTestsPerEvictionRun= 3
redis.timeBetweenEvictionRunsMillis= 60000

2)、spring-redis.xml

redis的相关参数配置设置。参数的值来自上面的properties文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<beans xmlns= "http://www.springframework.org/schema/beans"  
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"  default -autowire= "byName" >  
     <bean id= "jedisPoolConfig"  class = "redis.clients.jedis.JedisPoolConfig" >  
         <!-- <property name= "maxIdle"  value= "6" ></property>  
         <property name= "minEvictableIdleTimeMillis"  value= "300000" ></property>  
         <property name= "numTestsPerEvictionRun"  value= "3" ></property>  
         <property name= "timeBetweenEvictionRunsMillis"  value= "60000" ></property>   -->
  
         <property name= "maxIdle"  value= "${redis.maxIdle}" ></property>  
         <property name= "minEvictableIdleTimeMillis"  value= "${redis.minEvictableIdleTimeMillis}" ></property>  
         <property name= "numTestsPerEvictionRun"  value= "${redis.numTestsPerEvictionRun}" ></property>  
         <property name= "timeBetweenEvictionRunsMillis"  value= "${redis.timeBetweenEvictionRunsMillis}" ></property>
     </bean>  
     <bean id= "jedisConnectionFactory"  class = "org.springframework.data.redis.connection.jedis.JedisConnectionFactory"  destroy-method= "destroy" >  
         <property name= "poolConfig"  ref= "jedisPoolConfig" ></property>  
         <property name= "hostName"  value= "${redis.hostName}" ></property>  
         <property name= "port"  value= "${redis.port}" ></property>  
         <property name= "timeout"  value= "${redis.timeout}" ></property>  
         <property name= "usePool"  value= "${redis.usePool}" ></property>  
     </bean>  
     <bean id= "jedisTemplate"  class = "org.springframework.data.redis.core.RedisTemplate" >  
         <property name= "connectionFactory"  ref= "jedisConnectionFactory" ></property>  
         <property name= "keySerializer" >  
             <bean  class = "org.springframework.data.redis.serializer.StringRedisSerializer" />  
         </property>  
         <property name= "valueSerializer" >  
             <bean  class = "org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />  
         </property>  
     </bean>  
</beans>

3)、applicationContext.xml

spring的总配置文件,在里面假如一下的代码

1
2
3
4
5
6
7
8
9
10
11
12
<bean  class = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
         <property name= "systemPropertiesModeName"  value= "SYSTEM_PROPERTIES_MODE_OVERRIDE"  />
         <property name= "ignoreResourceNotFound"  value= "true"  />
         <property name= "locations" >
             <list>
  
                 <value>classpath*:/META-INF/config/redis.properties</value>
             </list>
         </property>
     </bean>
  
< import  resource= "spring-redis.xml"  />

5)、redis缓存工具类

ValueOperations  ——基本数据类型和实体类的缓存
ListOperations     ——list的缓存
SetOperations    ——set的缓存

HashOperations  Map的缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import  java.io.Serializable;
import  java.util.ArrayList;
import  java.util.HashMap;
import  java.util.HashSet;
import  java.util.Iterator;
import  java.util.List;
import  java.util.Map;
import  java.util.Set;
  
import  org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.beans.factory.annotation.Qualifier;
import  org.springframework.context.support.ClassPathXmlApplicationContext;
import  org.springframework.data.redis.core.BoundSetOperations;
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.core.SetOperations;
import  org.springframework.data.redis.core.ValueOperations;
import  org.springframework.stereotype.Service;
  
@Service
public  class  RedisCacheUtil<T>
{
  
     @Autowired  @Qualifier ( "jedisTemplate" )
     public  RedisTemplate redisTemplate;
  
     /**
      * 缓存基本的对象,Integer、String、实体类等
      * @param key    缓存的键值
      * @param value    缓存的值
      * @return        缓存的对象
      */
     public  <T> ValueOperations<String,T> setCacheObject(String key,T value)
     {
  
         ValueOperations<String,T> operation = redisTemplate.opsForValue(); 
         operation.set(key,value);
         return  operation;
     }
  
     /**
      * 获得缓存的基本对象。
      * @param key        缓存键值
      * @param operation
      * @return            缓存键值对应的数据
      */
     public  <T> T getCacheObject(String key /*,ValueOperations<String,T> operation*/)
     {
         ValueOperations<String,T> operation = redisTemplate.opsForValue(); 
         return operation.get(key);
     }
  
     /**
      * 缓存List数据
      * @param key        缓存的键值
      * @param dataList    待缓存的List数据
      * @return            缓存的对象
      */
     public <T> ListOperations<String, T> setCacheList(String key,List<T> dataList)
     {
         ListOperations listOperation = redisTemplate.opsForList();
         if(null != dataList)
         {
             int size = dataList.size();
             for(int i = 0; i < size ; i ++)
             {
  
                 listOperation.rightPush(key,dataList.get(i));
             }
         }
  
         return listOperation;
     }
  
     /**
      * 获得缓存的list对象
      * @param key    缓存的键值
      * @return        缓存键值对应的数据
      */
     public <T> List<T> getCacheList(String key)
     {
         List<T> dataList = new ArrayList<T>();
         ListOperations<String,T> listOperation = redisTemplate.opsForList();
         Long size = listOperation.size(key);
  
         for(int i = 0 ; i < size ; i ++)
         {
             dataList.add((T) listOperation.leftPop(key));
         }
  
         return dataList;
     }
  
     /**
      * 缓存Set
      * @param key        缓存键值
      * @param dataSet    缓存的数据
      * @return            缓存数据的对象
      */
     public <T> BoundSetOperations<String,T> setCacheSet(String key,Set<T> dataSet)
     {
         BoundSetOperations<String,T> setOperation = redisTemplate.boundSetOps(key);    
         /*T[] t = (T[]) dataSet.toArray();
              setOperation.add(t);*/
  
         Iterator<T> it = dataSet.iterator();
         while(it.hasNext())
         {
             setOperation.add(it.next());
         }
  
         return setOperation;
     }
  
     /**
      * 获得缓存的set
      * @param key
      * @param operation
      * @return
      */
     public Set<T> getCacheSet(String key/*,BoundSetOperations<String,T> operation*/)
     {
         Set<T> dataSet = new HashSet<T>();
         BoundSetOperations<String,T> operation = redisTemplate.boundSetOps(key);    
  
         Long size = operation.size();
         for(int i = 0 ; i < size ; i++)
         {
             dataSet.add(operation.pop());
         }
         return dataSet;
     }
  
     /**
      * 缓存Map
      * @param key
      * @param dataMap
      * @return
      */
     public <T> HashOperations<String,String,T> setCacheMap(String key,Map<String,T> dataMap)
     {
  
         HashOperations hashOperations = redisTemplate.opsForHash();
         if(null != dataMap)
         {
  
             for (Map.Entry<String, T> entry : dataMap.entrySet()) {  
  
                 /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());  */
                 hashOperations.put(key,entry.getKey(),entry.getValue());
            
  
         }
  
         return hashOperations;
     }
  
     /**
      * 获得缓存的Map
      * @param key
      * @param hashOperation
      * @return
      */
     public <T> Map<String,T> getCacheMap(String key/*,HashOperations<String,String,T> hashOperation*/)
     {
         Map<String, T> map = redisTemplate.opsForHash().entries(key);
         /*Map<String, T> map = hashOperation.entries(key);*/
         return map;
     }
  
     /**
      * 缓存Map
      * @param key
      * @param dataMap
      * @return
      */
     public <T> HashOperations<String,Integer,T> setCacheIntegerMap(String key,Map<Integer,T> dataMap)
     {
         HashOperations hashOperations = redisTemplate.opsForHash();
         if(null != dataMap)
         {
  
             for (Map.Entry<Integer, T> entry : dataMap.entrySet()) {  
  
                 /*System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());  */
                 hashOperations.put(key,entry.getKey(),entry.getValue());
            
  
         }
  
         return hashOperations;
     }
  
     /**
      * 获得缓存的Map
      * @param key
      * @param hashOperation
      * @return
      */
     public <T> Map<Integer,T> getCacheIntegerMap(String key/*,HashOperations<String,String,T> hashOperation*/)
     {
         Map<Integer, T> map = redisTemplate.opsForHash().entries(key);
         /*Map<String, T> map = hashOperation.entries(key);*/
         return  map;
     }
}

6)、测试

这里测试我是在项目启动的时候到数据库中查找出国家和城市的数据,进行缓存,之后将数据去出

6.1  项目启动时缓存数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import  java.util.HashMap;
import  java.util.List;
import  java.util.Map;
  
import  org.apache.log4j.Logger;
import  org.springframework.beans.factory.annotation.Autowired;
import  org.springframework.context.ApplicationListener;
import  org.springframework.context.event.ContextRefreshedEvent;
import  org.springframework.stereotype.Service;
  
import  com.test.model.City;
import  com.test.model.Country;
import  com.zcr.test.User;
  
/*
  * 监听器,用于项目启动的时候初始化信息
  */
@Service
public  class  StartAddCacheListener  implements  ApplicationListener<ContextRefreshedEvent>
{
     //日志
     private  final  Logger log= Logger.getLogger(StartAddCacheListener. class );
  
     @Autowired
     private  RedisCacheUtil<Object> redisCache;
  
     @Autowired
     private  BrandStoreService brandStoreService;
  
     @Override
     public  void  onApplicationEvent(ContextRefreshedEvent  event) 
     {
         //spring 启动的时候缓存城市和国家等信息
         if (event.getApplicationContext().getDisplayName().equals( "Root WebApplicationContext" ))
         {
             System.out.println( "\n\n\n_________\n\n缓存数据 \n\n ________\n\n\n\n" );
             List<City> cityList = brandStoreService.selectAllCityMessage();
             List<Country> countryList = brandStoreService.selectAllCountryMessage();
  
             Map<Integer,City> cityMap =  new  HashMap<Integer,City>();
  
             Map<Integer,Country> countryMap =  new  HashMap<Integer, Country>();
  
             int  cityListSize = cityList.size();
             int  countryListSize = countryList.size();
  
             for ( int  i =  0  ; i < cityListSize ; i ++ )
             {
                 cityMap.put(cityList.get(i).getCity_id(), cityList.get(i));
             }
  
             for ( int  i =  0  ; i < countryListSize ; i ++ )
             {
                 countryMap.put(countryList.get(i).getCountry_id(), countryList.get(i));
             }
  
             redisCache.setCacheIntegerMap( "cityMap" , cityMap);
             redisCache.setCacheIntegerMap( "countryMap" , countryMap);
         }
     }
  
}

获取缓存数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Autowired
     private  RedisCacheUtil<User> redisCache;
  
     @RequestMapping ( "testGetCache" )
     public  void  testGetCache()
     {
         /*Map<String,Country> countryMap = redisCacheUtil1.getCacheMap("country");
         Map<String,City> cityMap = redisCacheUtil.getCacheMap("city");*/
         Map<Integer,Country> countryMap = redisCacheUtil1.getCacheIntegerMap( "countryMap" );
         Map<Integer,City> cityMap = redisCacheUtil.getCacheIntegerMap( "cityMap" );
  
         for ( int  key : countryMap.keySet())
         {
             System.out.println( "key = "  + key +  ",value="  + countryMap.get(key));
         }
  
         System.out.println( "------------city" );
         for ( int  key : cityMap.keySet())
         {
             System.out.println( "key = "  + key +  ",value="  + cityMap.get(key));
         }
     }

























本文转自yunlielai51CTO博客,原文链接:http://blog.51cto.com/4925054/1910479 ,如需转载请自行联系原作者
相关文章
|
3月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
4676 74
|
3月前
|
缓存 负载均衡 监控
135_负载均衡:Redis缓存 - 提高缓存命中率的配置与最佳实践
在现代大型语言模型(LLM)部署架构中,缓存系统扮演着至关重要的角色。随着LLM应用规模的不断扩大和用户需求的持续增长,如何构建高效、可靠的缓存架构成为系统性能优化的核心挑战。Redis作为业界领先的内存数据库,因其高性能、丰富的数据结构和灵活的配置选项,已成为LLM部署中首选的缓存解决方案。
|
3月前
|
NoSQL Java 数据库连接
《深入理解Spring》Spring Data——数据访问的统一抽象与极致简化
Spring Data通过Repository抽象和方法名派生查询,简化数据访问层开发,告别冗余CRUD代码。支持JPA、MongoDB、Redis等多种存储,统一编程模型,提升开发效率与架构灵活性,是Java开发者必备利器。(238字)
|
4月前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
235 1
Redis专题-实战篇二-商户查询缓存
|
3月前
|
缓存 运维 监控
Redis 7.0 高性能缓存架构设计与优化
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Redis 7.0高性能缓存架构,探索函数化编程、多层缓存、集群优化与分片消息系统,用代码在二进制星河中谱写极客诗篇。
|
4月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
320 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
4月前
|
缓存 NoSQL 关系型数据库
Redis缓存和分布式锁
Redis 是一种高性能的键值存储系统,广泛用于缓存、消息队列和内存数据库。其典型应用包括缓解关系型数据库压力,通过缓存热点数据提高查询效率,支持高并发访问。此外,Redis 还可用于实现分布式锁,解决分布式系统中的资源竞争问题。文章还探讨了缓存的更新策略、缓存穿透与雪崩的解决方案,以及 Redlock 算法等关键技术。
|
6月前
|
NoSQL Java Redis
Redis基本数据类型及Spring Data Redis应用
Redis 是开源高性能键值对数据库,支持 String、Hash、List、Set、Sorted Set 等数据结构,适用于缓存、消息队列、排行榜等场景。具备高性能、原子操作及丰富功能,是分布式系统核心组件。
619 2
|
存储 NoSQL Redis
redis存储原理和数据模型
redis存储原理和数据模型
175 1
|
存储 NoSQL Redis
Redis存储原理与数据模型
Redis存储原理与数据模型