MyBatis(SSM框架)接入redis作为二级缓存(含源码)

1.配置jar包:

 可在(https://mvnrepository.com/)中下载

2.添加redis ip 和port配置

#redis配置 start
# redis地址
redis.ip=127.0.0.1
# redis端口
redis.port=6379
#  最大连接数
jedis.pool.maxActive=3000
#  空闲时最大连接数
jedis.pool.maxIdle=1000
#  最大等待时间
jedis.pool.maxWait=1500
jedis.pool.testOnBorrow=true
jedis.pool.testOnReturn=true
# 开关
redis.switch = true
#  redis的KEY,以这个开头,区分系统
redis.key = SOA
#redis配置 end

3.配置对应工具类

  RedisCache.Java

package com.lll.utils;

import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheException;
import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;

import java.io.Serializable;
import java.util.Properties;
import java.util.concurrent.locks.ReadWriteLock;

public class RedisCache implements Cache {

    private final String redisIp = PropertiesUtils.getProperty("redis.ip");
    private final int redisPort = Integer.valueOf(PropertiesUtils.getProperty("redis.port")).intValue();

    private final String id;

    private Jedis cache = new Jedis(redisIp, redisPort);

    public RedisCache(String id) {
        this.id = id;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    //返回缓存所有键值对的数量
    public int getSize() {
        Long dbSize = cache.dbSize();
        return dbSize.intValue();
    }

    @Override
    //向缓存中存入数据
    public void putObject(Object key, Object value) {
        System.out.println("key:" + key);
        //将对象序列化成字节数组  引入commens-lang3工具包
        byte[] keyBs = SerializeUtils.serialize((Serializable) key);
        byte[] valueBs = SerializeUtils.serialize((Serializable) value);

        cache.set(keyBs, valueBs);
    }

    @Override
    //从缓存中获取数据
    public Object getObject(Object key) {
        byte[] keyBs = SerializeUtils.serialize((Serializable) key);
        byte[] valueBs = cache.get(keyBs);
        if (valueBs != null) { // 第一次到缓存找数据的时候 , 返回的是null
            return SerializeUtils.unserialize(valueBs);
        }
        return null;
    }

    @Override
    //清除缓存
    public Object removeObject(Object key) {
        // 先获取一下删除的对象
        byte[] keyBs = SerializeUtils.serialize((Serializable) key);
        byte[] valueBs = cache.get(keyBs);
        Object obj = SerializeUtils.unserialize(valueBs);
        cache.del(keyBs);// 执行删除操作
        return obj;
    }

    @Override
    //清空缓存
    public void clear() {
        cache.flushDB();
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return null;
    }

    @Override
    public boolean equals(Object o) {
        if (getId() == null) {
            throw new CacheException("Cache instances require an ID.");
        }
        if (this == o) {
            return true;
        }
        if (!(o instanceof Cache)) {
            return false;
        }

        Cache otherCache = (Cache) o;
        return getId().equals(otherCache.getId());
    }

    @Override
    public int hashCode() {
        if (getId() == null) {
            throw new CacheException("Cache instances require an ID.");
        }
        return getId().hashCode();
    }

}

SerializeUtils.java

package com.lll.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializeUtils {

    //private static final Logger logger = Logger.getLogger(SerializeUtils.class);

    private static void close(ObjectOutputStream objectOutputStream, ByteArrayOutputStream byteArrayOutputStream) {
        try {
            if (byteArrayOutputStream != null) {
                byteArrayOutputStream.close();
            }
            if (objectOutputStream != null) {
                objectOutputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            //logger.error("关闭IO资源异常[" + e.getMessage() + "]", e);
        }
    }

    private static void close(ObjectInputStream objectInputStream, ByteArrayInputStream byteArrayInputStream) {
        try {
            if (objectInputStream != null) {
                objectInputStream.close();
            }
            if (byteArrayInputStream != null) {
                byteArrayInputStream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
            //logger.error("关闭IO资源异常[" + e.getMessage() + "]", e);
        }
    }

    public static byte[] serialize(Object object) {
        ObjectOutputStream objectOutputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(object);
            byte[] bytes = byteArrayOutputStream.toByteArray();
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
            //logger.error("序列化对象异常[" + e.getMessage() + "]", e);
        } finally {
            close(objectOutputStream, byteArrayOutputStream);
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public static <T> T unserialize(byte[] bytes) {
        if (bytes == null)
            return null;
        ByteArrayInputStream byteArrayInputStream = null;
        ObjectInputStream objectInputStream = null;
        try {
            byteArrayInputStream = new ByteArrayInputStream(bytes);
            objectInputStream = new ObjectInputStream(byteArrayInputStream);
            return (T) objectInputStream.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            close(objectInputStream, byteArrayInputStream);
        }
        return null;
    }

}

4.在mybatis-config.xml和spring-mybatis.xml开启配置

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

    <!-- 使用mybatis方式全局变量设置在核心配置文件sqlMapConfig.xml的settings中
         spring和mybatis整合的情况下,mybatis下的全局参数<settings>在spring的配置文件中设置,
            在spring的sqlSessionFactory对象中,将配置粘入bean的property中

        settings用于配置全局变量,有顺序要求,要放在environment前面,配置全局参数
        lazyLoadingEnabled 配置懒加载,全局允许或静止懒加载,所有的任务都懒加载
        具体实现懒加载:通过在resultMap中设置fetchType实现懒加载

        <setting name="cacheEnabled" value="true"/> cacheEnabled允许二级缓存
    -->
    <settings>
        <!-- 打开延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 将积极加载改为消极加载即按需要加载 -->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!-- 开启二级缓存(默认也是开启的)-->
        <setting name="cacheEnabled" value="true"/>
    </settings>

</configuration>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">


    <!-- 配置组件扫描器,使用注解方式开发,不用配置dao和service -->
    <!-- 在springmvc.xml文件中也可以配置这个属性 -->
    <context:component-scan base-package="com.lll"/>

    <!-- 数据源 -->
<!--    <bean id="dataSource"-->
<!--          class="org.springframework.jdbc.datasource.DriverManagerDataSource">-->
<!--        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>-->
<!--        <property name="url" value="jdbc:mysql://localhost:3306/test"/>-->
<!--        <property name="username" value="root"/>-->
<!--        <property name="password" value=""/>-->
<!--    </bean>-->

    <!-- 配置session工厂 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--        <property name="dataSource" ref="dataSource"/>-->
        <property name="configLocation" value="classpath:resource/mybatis-config.xml"/>
    </bean>

    <!-- 事务管理器 -->
    <!--     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean> -->

    <!-- 配置AOP通知 -->
    <!--     <tx:advice id="txAdvice" transaction-manager="transactionManager">
             配置事务属性
             <tx:attributes>
                 添加事务管理的方法
                 <tx:method name="save*" propagation="REQUIRED"/>
                 <tx:method name="delete*" propagation="REQUIRED"/>
                 <tx:method name="update*" propagation="REQUIRED"/>
                 <tx:method name="select*" read-only="true"/>
             </tx:attributes>
         </tx:advice> -->

    <!-- 配置AOP,为添加事务管理的操作配置AOP -->
    <!--     <aop:config>
            引入的Spring定义的事务通知,需要使用aop:advisor
            下面难
            <aop:advisor advice-ref="txAdvice"
                pointcut="execution(* com.edu.test.service.*.*(..))"
            />
        </aop:config> -->
</beans>

5.在dao.xml中开启缓存

  <cache type="com.lll.utils.RedisCache" />

6.在sql方法中设置是都使用缓存

7.实际效果:

 

 

8.注意:bean对象必须实现Serializable,否则缓存会报错

9.资源

源码地址:https://github.com/CodingPandaLLL/springlll.git

资源包:https://codeload.github.com/CodingPandaLLL/springlll/zip/refs/tags/1.0.1

软件:Redis(提取码:vkun)Redis Desktop Manager(提取码:2syd)

作者:CodingPanda
座中铭:润物细无声,功到自然成
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
原文地址:https://www.cnblogs.com/LiLiliang/p/14590376.html