使用redis开启Mybatis的二级缓存

概述

使用MyBatis自身的设置开启二级缓存,在分布式系统下将不起作用,因此,我们才用中间件开启二级缓存,此文介绍了使用Redis开启二级的解决策略。本文介绍了2种使用redis的开启二级缓存的机制,使用Jedis 和 lettuce。

第一种策略 使用:Jedis

Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接

①引入依赖

 <!--redis的启动器-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
      <version>2.1.5.RELEASE</version>
    </dependency>
 

②配置redis参数

application.yml文件中添加:

#设置redis的参数
spring:
#  redis: #单机模式
#    host: 192.168.*.*
#    port: 6379
	redis: #集群模式
	    cluster:
	      nodes: 192.168.8.18:7004,192.168.8:7001,192.168.8:7002

③获取SprnigBoot工厂后门

定义一个web触发器,作用是获得整个工厂内容,方便非工厂管理的普通类,可以拿到工厂管理的对象(全局容器)
我们这么做,是为了获取 被工厂管理的redisTemplate对象。

package com.baizhi.cache;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

//web触发器,作用是获得整个工厂内容,方便非工厂管理的普通类。可以拿到工厂管理的对象(全局容器)
@Component
public class WebWare implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    //通过属性名获取对象的方法
   public static Object getbyName(String name){
       Object bean = applicationContext.getBean(name);
       return bean;
   }

   //通过属性类获取对象的方法
    public static Object getByClass(Class clazz){
        Object bean = applicationContext.getBean(clazz);
        return bean;
    }
}

④自定义缓存机制

Mybatiscache,给需要集成其它Cache或者自定义Cache提供了接口。

package com.baizhi.cache;

import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.concurrent.locks.ReadWriteLock;
//定义自己的一个缓存策略
public class MyCache implements Cache {

    //获取工厂管理的redisTemplate对象
   private RedisTemplate redisTemplate = (RedisTemplate) WebWare.getbyName("redisTemplate");


    private String id;

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

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

    @Override
    public void putObject(Object o, Object o1) {

        redisTemplate.opsForHash().put(id,o,o1);
    }

    @Override
    public Object getObject(Object o) {

        Object o1 = redisTemplate.opsForHash().get(id, o);
        return o1;

    }

    @Override
    public Object removeObject(Object o) {
        return null;
    }

    //清空缓存
    @Override
    public void clear() {

        redisTemplate.delete(id);
    }

    @Override
    public int getSize() {
        return 0;
    }

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

⑤启用二级缓存

*mapper.xml文件中添加以下内容:

<cache type="com.baizhi.cache.MyCache"></cache>

第二种策略 使用 Lettuce

Lettuce的连接是基于Netty的,连接实例可以在多个线程间并发访问,并且是线程安全的,所以一个连接实例就可以满足多线程环境下的并发访问

①引入依赖

	<!--集成Redis二级缓存-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
	<!--使用连接池技术-->        
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

②配置redis参数

 #连接redis
  redis:
    host: hbase
    port: 6379
    timeout: 5s #超时时间
    lettuce:
      pool:
        max-active: 10 #最大活动数
        max-idle: 8 #最大闲置数
        max-wait: 5ms #最大等待数
        min-idle: 1 #最小闲置数
      shutdown-timeout: 100ms #超时停机时间

③在入口类中注册组件

package com.baizhi;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.web.client.RestTemplate;

import java.net.UnknownHostException;

@SpringBootApplication
@MapperScan("com.baizhi.dao")
public class UsermodelApplication {

    public static void main(String[] args) {
        SpringApplication.run(UsermodelApplication.class, args);
    }

    //注册一个Rest组件 SpringMVC中自带的一个Rest客户端工具,可以无缝和SpringBoot集成
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    //注册一个Redis池技术的组件 Lettuce
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(LettuceConnectionFactory connectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        //设置Key、value的序列化
        redisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());

        return redisTemplate;
    }
    
}

④获取工厂后门

package com.baizhi.cache;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class WebWare implements ApplicationContextAware {
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    //通过属性名获取对象的方法
    public static Object getbyName(String name){
        Object bean = applicationContext.getBean(name);
        return bean;
    }

    //通过属性类获取对象的方法
    public static Object getByClass(Class clazz){
        Object bean = applicationContext.getBean(clazz);
        return bean;
    }
}

⑤自定义缓存机制

package com.baizhi.cache;

import org.apache.ibatis.cache.Cache;
import org.aspectj.weaver.ast.Var;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
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 MyCache implements Cache {

    private Logger logger= LoggerFactory.getLogger(MyCache.class);
    //获取RedisTemple 对象
    //获取工厂管理的redisTemplate对象
    private RedisTemplate redisTemplate = (RedisTemplate) WebWare.getbyName("redisTemplate");
    //创建一个读写锁
    private  ReadWriteLock lock =  new ReentrantReadWriteLock();
    //设置一个超时配置
    private long timeout=300;

    //id 用于存放namespace
    private  String id;

    //提供一个构造
    public MyCache(String id) {
        this.id = id;
    }

    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

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

    @Override // o 某一方法的唯一标识 o1 方法的返回值
    public void putObject(Object o, Object o1) {
       /* redisTemplate.opsForHash().put(id,o,o1);*/
        logger.debug("将查询结果存储到cache.key:"+o+",value:"+o1);
        ValueOperations opsForValue = redisTemplate.opsForValue();
        opsForValue.set(o,o1,timeout, TimeUnit.SECONDS);
    }

    @Override
    public Object getObject(Object o) {
        /*return redisTemplate.opsForHash().get(id,o);*/
        logger.debug("从缓存中读取结果.key:"+o);
        ValueOperations opsForValue = redisTemplate.opsForValue();
        return opsForValue.get(o);
    }

    @Override
    public Object removeObject(Object o) {
        logger.debug("从缓存中清除.key:"+o);
        ValueOperations opsForValue = redisTemplate.opsForValue();
        Object value = opsForValue.get(o);
        redisTemplate.delete(o);
        return value;
    }

    @Override
    public void clear() {
        //清除
      /*  redisTemplate.delete(id);*/
        logger.debug("从缓存中清除缓存区所有数据");
        redisTemplate.execute((RedisConnection connection) ->{
            connection.flushAll();
            return null;
        });
    }

    @Override
    public int getSize() {
        return 0;
    }

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

⑥启用二级缓存

 <!--开启二级缓存-->
    <cache type="com.baizhi.cache.MyCache">
        <!--设置超时时间-->
        <property name="timeout" value="60"/>
    </cache>

☆Memcache 作二级缓存

https://www.cnblogs.com/brian-csyy/p/7611895.html

发布了32 篇原创文章 · 获赞 1 · 访问量 1165

猜你喜欢

转载自blog.csdn.net/ASYMUXUE/article/details/104925925