1. 程式人生 > >10. 搭配redis做文章緩存

10. 搭配redis做文章緩存

for 字符串類型 ext org mapper ping java 取出 evel

redis是一個使用較多的內存鍵值數據庫,這兒的鍵是字符串類型的標識符,而值可以是字符串、散列、列表、集合和有序集合,也正是因為redis提供了較豐富的值的類型,能夠滿足不同的使用要求,而且redis的讀寫是很高效的,所以現在很多系統都將redis作為緩存系統,在使用的時候先從數據庫中把數據讀取出來,然後寫入redis,再次使用該數據時就可以直接從redis中獲取,當然如果修改數據的話就要把redis中的對應數據清除。本文主要是介紹springboot+mybatis搭配redis來作為文章的緩存,做法如下:

1. 添加依賴:

技術分享圖片
1 <dependency>
2     <
groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-data-redis</artifactId> 4 </dependency>
pom.xml

因為要觀察讀取數據時是從哪讀取到的數據,所以也要配置log4j,並使mybatis能夠把sql輸出到控制臺上,所以也要添加log4j的依賴:

技術分享圖片
<dependency>  
    <groupId>org.springframework.boot</groupId
> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </
exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j</artifactId> <version>1.3.8.RELEASE</version> </dependency>
pom.xml

2. 在src/main/resources目錄下增加log4j.properties文件,並添加以下配置

技術分享圖片
 1 #logger level  
 2 log4j.rootCategory=DEBUG,stdout,DebugAppender,InfoAppender,ErrorAppender  
 3 log4j.debug=true  
 4 log4j.appender.stdout=org.apache.log4j.ConsoleAppender    
 5 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout       
 6 log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
 7 #logger input file  
 8 log4j.logger.DebugAppender.access=DEBUG  
 9 log4j.appender.DebugAppender=org.apache.log4j.DailyRollingFileAppender       
10 log4j.appender.DebugAppender.File=../logs/debug  
11 log4j.appender.DebugAppender.File.datePattern=‘.‘yyyy-MM-dd
12 log4j.appender.DebugAppender.layout=org.apache.log4j.PatternLayout       
13 log4j.appender.DebugAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
14   
15 #logger input file  
16 log4j.logger.InfoAppender.access=INFO  
17 log4j.appender.InfoAppender=org.apache.log4j.DailyRollingFileAppender       
18 log4j.appender.InfoAppender.File=../logs/info  
19 log4j.appender.InfoAppender.File.datePattern=‘.‘yyyy-MM-dd
20 log4j.appender.InfoAppender.layout=org.apache.log4j.PatternLayout       
21 log4j.appender.InfoAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n   
22   
23 #error log input file  
24 log4j.logger.ErrorAppender.access=ERROR  
25 log4j.appender.ErrorAppender=org.apache.log4j.DailyRollingFileAppender  
26 log4j.appender.ErrorAppender.File=../logs/error 
27 log4j.appender.ErrorAppender.File.datePattern=‘.‘yyyy-MM-dd
28 log4j.appender.ErrorAppender.Append = true  
29 log4j.appender.ErrorAppender.threshold = ERROR  
30 log4j.appender.ErrorAppender.layout=org.apache.log4j.PatternLayout   
31 log4j.appender.ErrorAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
log4j.properties

同時在application.properties文件中增加:logging.level.*=DEBUG
3. 在application.properties中添加redis配置

技術分享圖片
spring.redis.database=0
spring.redis.host=192.168.1.103
spring.redis.port=6379
spring.redis.password=
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=0
application.properties

4. 添加RedisConfig,以開啟redis配置:

技術分享圖片
 1 package com.lvniao.blog.config;
 2 
 3 import org.springframework.cache.interceptor.KeyGenerator;
 4 import org.springframework.beans.factory.annotation.Value;
 5 import org.springframework.cache.CacheManager;
 6 import org.springframework.cache.annotation.CachingConfigurerSupport;
 7 import org.springframework.cache.annotation.EnableCaching;
 8 import org.springframework.context.annotation.Bean;
 9 import org.springframework.context.annotation.Configuration;
10 import org.springframework.data.redis.cache.RedisCacheManager;
11 import org.springframework.data.redis.connection.RedisConnectionFactory;
12 import org.springframework.data.redis.core.RedisTemplate;
13 import org.springframework.data.redis.core.StringRedisTemplate;
14 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
15 import org.springframework.data.redis.serializer.StringRedisSerializer;
16 
17 import java.lang.reflect.Method;
18 import com.fasterxml.jackson.annotation.JsonAutoDetect;
19 import com.fasterxml.jackson.annotation.PropertyAccessor;
20 import com.fasterxml.jackson.databind.ObjectMapper;
21 
22 @Configuration
23 @EnableCaching
24 public class RedisConfig  extends CachingConfigurerSupport {
25 
26     @Value("${spring.redis.host}")
27     private String host;
28     @Value("${spring.redis.port}")
29     private int port;
30     @Value("${spring.redis.timeout}")
31     private int timeout;
32     
33     @Bean
34     public KeyGenerator keyGenerator() {
35         return new KeyGenerator() {
36             @Override
37             public Object generate(Object target, Method method, Object... params) {
38                 StringBuilder sb = new StringBuilder();
39                 sb.append(target.getClass().getName());
40                 sb.append(":" + method.getName());
41                 for (Object obj : params) {
42                     sb.append(":" + obj.toString());
43                 }
44                 return sb.toString();
45             }
46         };
47     }
48     
49     @Bean 
50     public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
51         RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
52         cacheManager.setDefaultExpiration(10000);
53         return cacheManager;
54     }
55     
56     @Bean
57     public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
58         RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
59         redisTemplate.setConnectionFactory(factory);
60         redisTemplate.afterPropertiesSet();
61         setSerializer(redisTemplate);
62         return redisTemplate;
63     }
64 
65     private void setSerializer(RedisTemplate<String, String> template) {
66         Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
67         ObjectMapper om = new ObjectMapper();
68         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
69         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
70         jackson2JsonRedisSerializer.setObjectMapper(om);
71         template.setKeySerializer(new StringRedisSerializer());
72         template.setValueSerializer(jackson2JsonRedisSerializer);
73     }
74 }
RedisConfig

5. 這兒只是使用redis來緩存文章數據,所以在ArticleMapper的getArticleById方法上添加緩存配置,代碼如下:

技術分享圖片
 1 @Cacheable(key ="#p0") 
 2 @Select("select id, name, content, summary, createtime createTime, modifytime modifyTime, publiz, first, author, category from articles where id=#{id}")
 3 @Results({
 4     @Result(id=true, column="id", property="id"),
 5     @Result(column="name", property="name"),
 6     @Result(column="content", property="content"),
 7     @Result(column="summary", property="summary"),
 8     @Result(column="createTime", property="createTime"),
 9     @Result(column="modifyTime", property="modifyTime"),
10     @Result(column="publiz", property="publiz"),
11     @Result(column="first", property="first"),
12     @Result(column="author", property="author", 
13         one=@One(select="com.lvniao.blog.mapper.UserMapper.getUserById", fetchType=FetchType.EAGER)),
14     @Result(column="category", property="category", 
15         one=@One(select="com.lvniao.blog.mapper.CategoryMapper.getCategoryById", fetchType=FetchType.EAGER)),
16 })
ArticleMapper

public Article getArticleById(@Param("id") String id);
@Cacheable(key ="#p0") 表示先redis中查找鍵,如果沒找到就從數據庫中獲取數據,然後把數據寫入redis中,這樣當第二次調用該方法時,就會從redis中獲取數據並返回給調用。其中key ="#p0"表示將第一個參數作為鍵值。
6. 分別執行兩次去掉@Cacheable(key ="#p0") 和含有@Cacheable(key ="#p0") 的操作,然後在控制臺中比較兩次的日誌,截圖如下:

技術分享圖片

從圖中可以看到執行同樣的調用,左邊是從redis中國獲取數據,而右邊是從數據庫中獲取數據,所以經過如上步驟,就可以在項目中使用redis了。

10. 搭配redis做文章緩存