redis缓存
概念:Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value非关系型数据库,并提供多种语言的API。咱们平常所说的缓存,就是由它实现的,在于MyBatis的整合中中,用redis查询出来的数据,减轻数据库的压力,从而提高系统的性能。
要使用redis,得先下载,然后解压放到相应的文件夹下,若是在本地,使用命令窗口启动:切换到redis的目录,执行redis-server.exe redis.windows.donf命令,会看到有一个启动成功的标志显示,保持该窗口不被关闭。
项目中,在maven中引入相关配置:
<span style="font-size:18px;"><!-- redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.4.RELEASE</version>
</dependency></span>
新建一个参数配置文件redis.properties:
<span style="font-size:18px;">redis.ip=127.0.0.1
redis.port=6379
redis.pool.maxWait=1000</span>
参考相关资料,新建一个cache类,取名为MybatisRedisCache,实现org.apache.ibatis.cache.Cache接口,具体代码如下:
<span style="font-size:18px;">public class MybatisRedisCache implements Cache {
private static Logger logger = Logger.getLogger(MybatisRedisCache.class);
private Jedis redisClient = createReids();
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private String id;
public MybatisRedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
logger.info(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id);
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public int getSize() {
return Integer.valueOf(redisClient.dbSize().toString());
}
@Override
public void putObject(Object key, Object value) {
logger.info(">>>>>>>>>>>>>>>>>>>>>>>>putObject:" + key + "=" + value+"\n");
redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));
}
@Override
public Object getObject(Object key) {
Object value = SerializeUtil.unserialize(redisClient.get(SerializeUtil.serialize(key.toString())));
logger.info(">>>>>>>>>>>>>>>>>>>>>>>>getObject:" + key + "=" + value);
return value;
}
@Override
public Object removeObject(Object key) {
return redisClient.expire(SerializeUtil.serialize(key.toString()), 0);
}
@Override
public void clear() {
redisClient.flushDB();
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
protected Jedis createReids() {
String host = "localhost";
String port = "6379";
String timeout = "3000";
Properties prop = new Properties();
InputStream in = MybatisRedisCache.class.getClassLoader().getResourceAsStream( "redis.properties" );
try {
prop.load(in);
host = prop.getProperty( "redis.ip" ).trim();
port = prop.getProperty( "redis.port" ).trim();
timeout = prop.getProperty( "redis.pool.maxWait" ).trim();
} catch (IOException e) {
e.printStackTrace();
}
JedisPool pool = new JedisPool(new JedisPoolConfig(),host ,Integer.parseInt(port),Integer.parseInt(timeout));
return pool.getResource();
}
}</span>
实现接口中相应的方法,方法中是调用redis的java客户端去操作缓存,被操作的数据需要被序列化或反序列化,这个可以到网上查找:java序列化。
进入Cache接口,可以看到对于该接口的描述其中有:
* One instance of cache will be created for each namespace.
*
* The cache implementation must have a constructor that receives the cache id as an String parameter.
*
* MyBatis will pass the namespace as id to the constructor.
翻译为:
* 将为每一个命名空间创建一个Cache的实例
* Cache接口的实现类必须有一个具有String类型参数的构造方法,用于接收Cache对象的id,作为其唯一标识
* mybatis将以namespace作为id调用这个构造函数创建对象
所以实现一个构造方法是必须的。
写完缓存实现类后,需要相应的配置,在MyBatis的xml配置文件中写入:
<!-- 这个配置使全局的映射器启用或禁用缓存 -->
<setting name="cacheEnabled" value="true" />
在相应的mapper映射文件中写入:
<!-- 缓存 -->
<cache eviction="LRU" type="com.jk.redis.MybatisRedisCache" />
至此MyBatis+redis配置完成,在对数据库做相应的操作时,可以看到MybatisRedisCache类中相关的putObject、getObject日志输出,在第二次做同样的查询时,只看到getObject,说明是直接从缓存里去取值了。或者开sql日志的可以试试,在第二次相同查询时,sql语句不会输出,也可以说名改数据是从缓存中获取了。
还是附一个序列化的“小栗子”:
public static void main(String [] args){
User user = new User();
user.setUserName("guyueliusu");
user.setUserDesc("to be stronger");
try {
//序列化
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(user);
byte[] b = outputStream.toByteArray();
//反序列化
ByteArrayInputStream inputStream = new ByteArrayInputStream(b);
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
User uu = (User) objectInputStream.readObject();
System.out.println("========"+uu.getUserName());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}