10. 搭配redis做文章缓存

redis是一个使用较多的内存键值数据库,这儿的键是字符串类型的标识符,而值可以是字符串、散列、列表、集合和有序集合,也正是因为redis提供了较丰富的值的类型,能够满足不同的使用要求,而且redis的读写是很高效的,所以现在很多系统都将redis作为缓存系统,在使用的时候先从数据库中把数据读取出来,然后写入redis,再次使用该数据时就可以直接从redis中获取,当然如果修改数据的话就要把redis中的对应数据清除。本文主要是介绍springboot+mybatis搭配redis来作为文章的缓存,做法如下:

1. 添加依赖:

 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</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文件,并添加以下配置

 #logger level
log4j.rootCategory=DEBUG,stdout,DebugAppender,InfoAppender,ErrorAppender
log4j.debug=true
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n
#logger input file
log4j.logger.DebugAppender.access=DEBUG
log4j.appender.DebugAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.DebugAppender.File=../logs/debug
log4j.appender.DebugAppender.File.datePattern='.'yyyy-MM-dd
log4j.appender.DebugAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.DebugAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n #logger input file
log4j.logger.InfoAppender.access=INFO
log4j.appender.InfoAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.InfoAppender.File=../logs/info
log4j.appender.InfoAppender.File.datePattern='.'yyyy-MM-dd
log4j.appender.InfoAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.InfoAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n #error log input file
log4j.logger.ErrorAppender.access=ERROR
log4j.appender.ErrorAppender=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ErrorAppender.File=../logs/error
log4j.appender.ErrorAppender.File.datePattern='.'yyyy-MM-dd
log4j.appender.ErrorAppender.Append = true
log4j.appender.ErrorAppender.threshold = ERROR
log4j.appender.ErrorAppender.layout=org.apache.log4j.PatternLayout
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配置:

 package com.lvniao.blog.config;

 import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer; import java.lang.reflect.Method;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper; @Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport { @Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout; @Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(":" + method.getName());
for (Object obj : params) {
sb.append(":" + obj.toString());
}
return sb.toString();
}
};
} @Bean
public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(10000);
return cacheManager;
} @Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
redisTemplate.setConnectionFactory(factory);
redisTemplate.afterPropertiesSet();
setSerializer(redisTemplate);
return redisTemplate;
} private void setSerializer(RedisTemplate<String, String> template) {
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(jackson2JsonRedisSerializer);
}
}

RedisConfig

5. 这儿只是使用redis来缓存文章数据,所以在ArticleMapper的getArticleById方法上添加缓存配置,代码如下:

 @Cacheable(key ="#p0")
@Select("select id, name, content, summary, createtime createTime, modifytime modifyTime, publiz, first, author, category from articles where id=#{id}")
@Results({
@Result(id=true, column="id", property="id"),
@Result(column="name", property="name"),
@Result(column="content", property="content"),
@Result(column="summary", property="summary"),
@Result(column="createTime", property="createTime"),
@Result(column="modifyTime", property="modifyTime"),
@Result(column="publiz", property="publiz"),
@Result(column="first", property="first"),
@Result(column="author", property="author",
one=@One(select="com.lvniao.blog.mapper.UserMapper.getUserById", fetchType=FetchType.EAGER)),
@Result(column="category", property="category",
one=@One(select="com.lvniao.blog.mapper.CategoryMapper.getCategoryById", fetchType=FetchType.EAGER)),
})

ArticleMapper

public Article getArticleById(@Param("id") String id);
@Cacheable(key ="#p0") 表示先redis中查找键,如果没找到就从数据库中获取数据,然后把数据写入redis中,这样当第二次调用该方法时,就会从redis中获取数据并返回给调用。其中key ="#p0"表示将第一个参数作为键值。
6. 分别执行两次去掉@Cacheable(key ="#p0") 和含有@Cacheable(key ="#p0") 的操作,然后在控制台中比较两次的日志,截图如下:

10. 搭配redis做文章缓存

从图中可以看到执行同样的调用,左边是从redis中国获取数据,而右边是从数据库中获取数据,所以经过如上步骤,就可以在项目中使用redis了。

上一篇:TCP/IP协议基础(转)


下一篇:Android客户端与服务端交互之登陆示例