spring mvc 小记(八):MyBatis整合redis缓存

使用spring mvc已有2年之久,却还是停留在使用阶段,感觉这么下去不是办法,所以还是想往深处一探究竟。

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();
        }
    }





猜你喜欢

转载自blog.csdn.net/u012602046/article/details/52843348