zoukankan      html  css  js  c++  java
  • SpringBoot中mybatis整合redis做二级缓存(含源码)

    1.添加依赖

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
                <version>2.1.3.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>2.9.1</version>
            </dependency>

    2.添加redis配置

    spring:
      redis:
        host: 127.0.0.1
        port: 6379
        database: 1
        jedis:
          pool:
            max-idle: 8
            min-idle: 1
            max-active: 8
            max-wait: -1

    3.添加ApplicationContextHolder类(这里不能通过@Autowire的方式引用redisTemplate,因为RedisCache并不是Spring容器里的bean。所以我们需要手动地去调用容器的getBean方法来拿到这个bean,那么这样,我们就需要引入ApplicationContextHolder这个类。)

    package com.llltony.springboot.utils;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ApplicationContextHolder implements ApplicationContextAware {
    
        private static ApplicationContext applicationContext;
    
        /**
         * 实现ApplicationContextAware接口的context注入函数, 将其存入静态变量.
         */
        public void setApplicationContext(ApplicationContext applicationContext) {
            ApplicationContextHolder.applicationContext = applicationContext; // NOSONAR
        }
    
        /**
         * 取得存储在静态变量中的ApplicationContext.
         */
        public static ApplicationContext getApplicationContext() {
            checkApplicationContext();
            return applicationContext;
        }
    
        /**
         * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
         */
        @SuppressWarnings("unchecked")
        public static <T> T getBean(String name) {
            checkApplicationContext();
            return (T) applicationContext.getBean(name);
        }
    
        /**
         * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
         */
        @SuppressWarnings("unchecked")
        public static <T> T getBean(Class<T> clazz) {
            checkApplicationContext();
            return (T) applicationContext.getBeansOfType(clazz);
        }
    
        /**
         * 清除applicationContext静态变量.
         */
        public static void cleanApplicationContext() {
            applicationContext = null;
        }
    
        private static void checkApplicationContext() {
            if (applicationContext == null) {
                throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
            }
        }
    
    
    }

    4.添加序列化工具类

    package com.llltony.springboot.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;
        }
    
    }

    5.添加RedisCache类

    package com.llltony.springboot.utils;
    
    import org.apache.ibatis.cache.Cache;
    import org.springframework.data.redis.core.RedisCallback;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    public class RedisCache implements Cache {
        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        private final String id; // cache instance id
        private RedisTemplate redisTemplate;
        private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间
    
        public RedisCache(String id) {
            if (id == null) {
                throw new IllegalArgumentException("Cache instances require an ID");
            }
            this.id = id;
        }
    
        @Override
        public String getId() {
            return id;
        }
    
        /**
         * Put query result to redis
         *
         * @param key
         * @param value
         */
        @Override
        @SuppressWarnings("unchecked")
        public void putObject(Object key, Object value) {
            RedisTemplate redisTemplate = getRedisTemplate();
            ValueOperations opsForValue = redisTemplate.opsForValue();
            opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
            System.out.println("放入结果到缓存");
        }
    
        /**
         * Get cached query result from redis
         *
         * @param key
         * @return
         */
        @Override
        public Object getObject(Object key) {
            RedisTemplate redisTemplate = getRedisTemplate();
            ValueOperations opsForValue = redisTemplate.opsForValue();
            System.out.println("获取结果从缓存");
            return opsForValue.get(key);
        }
    
        /**
         * Remove cached query result from redis
         *
         * @param key
         * @return
         */
        @Override
        @SuppressWarnings("unchecked")
        public Object removeObject(Object key) {
            RedisTemplate redisTemplate = getRedisTemplate();
            redisTemplate.delete(key);
            System.out.println("从缓存删除了");
            return null;
        }
    
        /**
         * Clears this cache instance
         */
        @Override
        public void clear() {
            RedisTemplate redisTemplate = getRedisTemplate();
            redisTemplate.execute((RedisCallback) connection -> {
                connection.flushDb();
                return null;
            });
            System.out.println("清空缓存");
        }
    
        @Override
        public int getSize() {
            return 0;
        }
    
        @Override
        public ReadWriteLock getReadWriteLock() {
            return readWriteLock;
        }
    
        private RedisTemplate getRedisTemplate() {
            if (redisTemplate == null) {
                redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
            }
            return redisTemplate;
        }
    }

    6.mybatis-config.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>
    
        <settings>
            <setting name="mapUnderscoreToCamelCase" value="true"/>
            <!-- 打开延迟加载 -->
            <setting name="lazyLoadingEnabled" value="true"/>
            <!-- 将积极加载改为消极加载即按需要加载 -->
            <setting name="aggressiveLazyLoading" value="false"/>
            <!-- 开启二级缓存(默认也是开启的)-->
            <setting name="cacheEnabled" value="true"/>
        </settings>
    </configuration>

    7.在mapper中开启缓存

    <cache type="com.llltony.springboot.utils.RedisCache" />

    8.实际效果

     

    7.资源

    源码:https://github.com/CodingPandaLLL/tsl.git

    源码压缩包地址:https://codeload.github.com/CodingPandaLLL/tsl/zip/refs/tags/1.0.1

     注意:bean必须序列化否则存不到redis中报错

    作者:CodingPanda
    座中铭:润物细无声,功到自然成
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    怎么选取训练神经网络时的Batch size?
    一个batch的数据如何做反向传播
    Chinese NER Using Lattice LSTM-阅读总结
    深度学习Inception
    非极大值抑制--NMS
    CUDA简要理解
    Anaconda+tensorflow+pyTorch安装
    多层神经网络python实现
    深入解析Jieba分词源码(包括Trie存储,正向匹配,HMM,viterbi)
    最小堆排序MinHeap
  • 原文地址:https://www.cnblogs.com/LiLiliang/p/14642763.html
Copyright © 2011-2022 走看看