本文默认Redis已经安装完成,并且可以使用。这里不做Redis的安装等说明
我这里另外还使用Mybatis,Mysql,druid等依赖。因为我们下一步需要配置Mybatis的二级缓存。
其中的RedisTemplate就是SpringBoot为我们封装好的操作Reids的工具类,我们常用的操作都是通过这个对象来完成的。在这个方法中,对于需要设置参数的存储时间是没有直接的方法的。因此我们需要先设置这个参数,然后设置这个参数的时间,即expire方法,先通过ops.set将数据写入redis,然后通过redis.expire方法设置过期时间。
其中save方法用于将我们传的参数存入redis中,而read方法用于将我们存的值取出来,显示于界面上。
访问我们save和read功能,查看是否成功。如果成功,我们这可以开始我们的redis同mybatis整合操作。
既然要访问数据库,我们当然要写编写数据库相关的代码,由于集成mybatis前面已经讲过,这里我不详细说明,只针对Cache来进行说明
首先建立一个类,实现Cache接口,如下面代码所示:
package com.qlys.bean; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.ibatis.cache.Cache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; public class RedisCache implements Cache { private static final Logger logger = LoggerFactory.getLogger(RedisCache.class); private final ReadWriteLock lock = new ReentrantReadWriteLock(true); private static RedisTemplate<Object, Object> temp; public static void setRedisTemplate(RedisTemplate<Object, Object> temp) { RedisCache.temp = temp; logger.info("设置缓存对象--{}",temp); } private String id; @Override public String getId() { return id; } public RedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } this.id = id; } @Override public void putObject(final Object key,final Object value) { logger.info("写入缓存"); lock.writeLock().lock(); temp.opsForValue().set(key, value); lock.writeLock().unlock(); } @Override public Object getObject(final Object key) { logger.info("读取缓存"); return temp.opsForValue().get(key); } @Override public Object removeObject(final Object key) { logger.info("删除缓存"); Object val = temp.opsForValue().get(key); temp.delete(key); return val; } @Override public void clear() { logger.info("清除缓存"); temp.execute((RedisCallback<Boolean>)(conn)->{ conn.flushDb(); return true; }); } @Override public int getSize() { logger.info("redis大小"); return temp.execute((RedisCallback<Integer>)(conn)->{ return conn.dbSize().intValue(); }); } @Override public ReadWriteLock getReadWriteLock() { return lock; } }修改上面的RedisUtils类,加入如下代码:
@Bean public RedisCache redisCache() { RedisCache.setRedisTemplate(redis); return null; }这个代码是用于将Reids操作类存入到Cache操作类中,由于Cache是通过new创建的,无法通过注入完成。加入完成后,RedisUtils应该是这样的:
package com.qlys.service; import java.util.concurrent.TimeUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import com.qlys.bean.RedisCache; @Component public class RedisUtils { @Autowired private RedisTemplate<Object, Object> redis; @Bean public RedisCache redisCache() { RedisCache.setRedisTemplate(redis); return null; } /* * 读取 */ public Object read(final Object key) { ValueOperations<Object,Object> ops = this.redis.opsForValue(); return ops.get(key); } /* * 写入 */ public boolean set(final Object key,Object val) { ValueOperations<Object,Object> ops = this.redis.opsForValue(); ops.set(key, val); return true; } /* * 设置过期时间 */ public boolean expire(final Object key,Object val,int expireTime) { ValueOperations<Object,Object> ops = this.redis.opsForValue(); ops.set(key, val); this.redis.expire(key, expireTime, TimeUnit.SECONDS); return true; } }最后在我们配置Mybatis语句的mapper.xml文件中加入缓存配置就可以了,代码如下:
<cache eviction="FIFO" flushInterval="1" readOnly="false" type="com.qlys.bean.RedisCache加入完成后,形成的代码如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.qlys.dao.mapper.SystemMapper"> <cache eviction="FIFO" flushInterval="1" readOnly="false" type="com.qlys.bean.RedisCache"></cache> <select id="select" resultType="map"> SELECT * FROM a_table <where> <if test="id!=null"> and a_id=#{id} </if> </where> </select> <insert id="insert" parameterType="map"> INSERT INTO a_table(a_id,a_name,a_part) VALUES(#{id},#{name},#{part}) </insert> <delete id="delete" parameterType="map"> delete from a_table where a_id=#{id} </delete> </mapper>至此一个简单的Redis同mybatis集合方案算是完成了。
由于我们有可能会对SpringBoot提供的RedisTemplate的key解析方案做一些改造,这里贴上一个我写的一个序列化方案,方便知道以后怎么修改RedisTemplate这个对象的相关参数。仅供参考:
package com.qlys.bean; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.CacheManager; 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.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; @Configuration @EnableCaching public class RedisCacheConfig { private static final Logger logger = LoggerFactory.getLogger(RedisCacheConfig.class); @Bean public CacheManager cacheManager(RedisTemplate<Object, Object> redis) { return new RedisCacheManager(redis); } @Bean public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory){ RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object,Object>(); redisTemplate.setConnectionFactory(factory); RedisSerializer<Object> redisSerializer = new ByteRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); return redisTemplate; } private class ByteRedisSerializer implements RedisSerializer<Object>{ @Override public byte[] serialize(Object t) throws SerializationException { try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos)) { // 序列化 oos.writeObject(t); return baos.toByteArray(); } catch (Exception e) { logger.error(e.getMessage(),e); } return null; } @Override public Object deserialize(byte[] bytes) throws SerializationException { if (bytes == null) { return null; } try (InputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais)) { // 反序列化 return ois.readObject(); } catch (Exception e) { logger.error(e.getMessage(),e); } return null; } } }