• SpringBoot+Mybatis+redis实现二级缓存


    对于查询比较多的项目可以考虑配置二级缓存,mybatis本身的二级缓存是缓存到本地,但是对于多个节点的项目来说,可能会出现数据不一致的问题,所以采用redis缓存,这样二级缓存的数据就可以缓存到内存,可实现多个节点项目的数据同步。

    1、配置redis的连接

    #redis
    gmall.redis.host=172.16.1.250
    gmall.redis.port=6379
    gmall.redis.pass=Gworld2017
    gmall.redis.photo.database=6
    
    #最大分配的对象数  
    gmall.redis.maxActive=12000
    
    #最大能够保持idel状态的对象数 
    gmall.redis.maxIdle=600
    
    #当池内没有返回对象时,最大等待时间  
    gmall.redis.maxWait=2000
    
    gmall.redis.timeout=5000
    
    #当调用borrow Object方法时,是否进行有效性检查  
    gmall.redis.testOnBorrow=true
    
    #当调用return Object方法时,是否进行有效性检查  
    gmall.redis.testOnReturn=true
    
    gmall.redis.minIdle=5
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
        xsi:schemaLocation="
                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
                http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"
        default-lazy-init="false">
        <bean id="jedisConnFactory"
            class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
            primary="true">
            <property name="hostName" value="${gmall.redis.host}" />
            <property name="port" value="${gmall.redis.port}" />
            <property name="password" value="${gmall.redis.pass}" />
            <property name="timeout" value="${gmall.redis.timeout}" />
            <property name="database" value="${gmall.redis.photo.database}" />
        </bean>
        <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
            primary="true">
            <property name="connectionFactory" ref="jedisConnFactory" />
            <property name="exposeConnection" value="true" />
            <property name="keySerializer">
                <bean
                    class="org.springframework.data.redis.serializer.StringRedisSerializer" />
            </property>
            <property name="valueSerializer">
                <bean
                    class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
            </property>
            <property name="hashKeySerializer">
                <bean
                    class="org.springframework.data.redis.serializer.StringRedisSerializer" />
            </property>
            <property name="hashValueSerializer">
                <bean
                    class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
            </property>
        </bean>
    </beans>

    2、配置mybatis-cache-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="cacheEnabled" value="true"/>
        </settings>
    </configuration>

    3、编写RedisCache实现Cache类

    package com.gcard.gwmedia.cache;
    
    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.RedisTemplate;
    
    import com.gcard.gwmedia.utils.SpringBeanFactoryUtils;
    
    public class RedisCache implements Cache {
        
        Logger logger = LoggerFactory.getLogger(getClass());
    
        private final String FREFIX = "CACHE_";
        private final String id;
        
        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
        
        @SuppressWarnings("rawtypes")
        private RedisTemplate redisTemplate;
        
        private long cleanInterval;
        
        private long lastClear;
        
        public RedisCache(String id){
            if(id == null){
                throw new IllegalArgumentException("Cache instance require an ID");
            }
            this.id = id;
            this.cleanInterval = 1 * 60 * 60 * 1000;//一个小时
            this.lastClear = System.currentTimeMillis();
        }
    
        @SuppressWarnings({ "unchecked" })
        @Override
        public void clear() {
            lastClear = System.currentTimeMillis();
            String strKey = FREFIX + id.toString();
            getRedisTemplate().delete(strKey);
            logger.debug("Clear all the cached query result from redis");
        }
    
        @Override
        public String getId() {
            return id;
        }
    
        @SuppressWarnings({ "rawtypes", "unchecked" })
        @Override
        public Object getObject(Object key) {
            if(key != null){
                String strKey = FREFIX + id.toString();
                if(clearWhenStale(strKey)){
                    return null;
                }
                RedisTemplate redisTemplate = getRedisTemplate();
                Object obj = redisTemplate.opsForHash().get(strKey, key.toString());
                logger.debug("Get cached query result from redis");
                if(obj != null){
                    return obj;
                }else{
                    return null;
                }
            }else{
                return null;
            }
        }
    
        @SuppressWarnings("rawtypes")
        private RedisTemplate getRedisTemplate() {
            if(redisTemplate == null){
                redisTemplate = (RedisTemplate) SpringBeanFactoryUtils.getBean("redisTemplate");
            }
            return redisTemplate;
        }
        @SuppressWarnings({ "rawtypes", "unchecked" })
        @Override
        public void putObject(Object key, Object value) {
            if (key != null) {
                String strKey = FREFIX + id.toString();
                clearWhenStale(strKey);
                RedisTemplate redisTemplate = getRedisTemplate();
                redisTemplate.opsForHash().put(strKey,key.toString(),value);
                logger.debug("Put query result to redis");
            }
        }
        @Override
        public ReadWriteLock getReadWriteLock() {
            return readWriteLock;
        }
    
        @Override
        public int getSize() {
            return 0;
        }
    
    
        @SuppressWarnings({ "rawtypes", "unchecked" })
        @Override
        public Object removeObject(Object key) {
            if (key != null) {
                String strKey = FREFIX + id.toString();
                RedisTemplate redisTemplate = getRedisTemplate();
                redisTemplate.opsForHash().delete(strKey, key.toString());
                logger.debug("Remove cached query result from redis");
            }
            return null;
        }
        public boolean clearWhenStale(Object key){
            if(System.currentTimeMillis()-lastClear > cleanInterval){
                logger.info("clearWhenStale key={}", key);
                clear();
                return true;
            }
            return false;
            
        }
    }

    4、配置mapper.xml文件

    在mapper.xml文件加入<cache/>

    <cache type="com.gcard.gwmedia.cache.RedisCache"/>

    5、Application启动类添加注解@EnableCaching

    package com.gcard.gwmedia;
    
    import org.springframework.boot.SpringApplication;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    import org.springframework.cache.annotation.EnableCaching;
    import org.springframework.context.annotation.ImportResource;
    import org.springframework.scheduling.annotation.EnableAsync;
    
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
    @ImportResource(locations = {"classpath:/config/applicationContext.xml"})
    @EnableAsync
    @EnableCaching
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
        
    }
  • 相关阅读:
    【Docker】Dockerfile的基本使用
    Linux nsenter 命令简介及 切换宿主机网络为docker容器网络实践
    docker+selenium搭建分布式web自动化测试环境
    docker容器与虚拟机的区别
    docker 网络模式 和 端口映射
    Java基础之数组的定义与使用详解
    Java基础之数据类型、标识符、运算符、程序流程控制结构
    docker常用命令详解
    python查询腾讯云COS存储桶目录及文件大小
    python-自动化监控进程发钉钉报警
  • 原文地址:https://www.cnblogs.com/ouyanxia/p/9361599.html
Copyright © 2020-2023  润新知