10. 搭配redis做文章緩存
redis是一個使用較多的內存鍵值數據庫,這兒的鍵是字符串類型的標識符,而值可以是字符串、散列、列表、集合和有序集合,也正是因為redis提供了較豐富的值的類型,能夠滿足不同的使用要求,而且redis的讀寫是很高效的,所以現在很多系統都將redis作為緩存系統,在使用的時候先從數據庫中把數據讀取出來,然後寫入redis,再次使用該數據時就可以直接從redis中獲取,當然如果修改數據的話就要把redis中的對應數據清除。本文主要是介紹springboot+mybatis搭配redis來作為文章的緩存,做法如下:
1. 添加依賴:
1 <dependency> 2 <pom.xmlgroupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-data-redis</artifactId> 4 </dependency>
因為要觀察讀取數據時是從哪讀取到的數據,所以也要配置log4j,並使mybatis能夠把sql輸出到控制臺上,所以也要添加log4j的依賴:
<dependency> <groupId>org.springframework.boot</groupIdpom.xml> <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>
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%nlog4j.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=0application.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做文章緩存