Spring Boot 集成mybatis 用Redis做二级缓存

一:集成druid数据源

一:导包

                
			com.alibaba
			druid
			1.1.10
		

二:配置

用的是druid的连接池,jpa的自动建表,mytabis框架

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springboot
    username: root
    password: root
    
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    
mybatis:
  type-aliases-package: com.tom.bean
  mapper-locations: classpth:mapper/*mapper.xml

druid的额外配置

# 初始化大小,最小,最大
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
# 校验SQL,Oracle配置 spring.datasource.validationQuery=SELECT 1 FROM DUAL,如果不配validationQuery项,则下面三项配置无用
spring.datasource.validationQuery=SELECT 'x'
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
spring.datasource.useGlobalDataSourceStat=true

三:Mapper,Service,Controller

bean,用的自动建表

@Entity
public class teacher implements Serializable{
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int id;
	private String name;
	private int age;
        ...
}

mapper,暂时只写两个方法

@Mapper
public interface teachMapper {
	@Insert("insert into teacher values(null,#{age},#{name})") 
	public void save(teacher t);
	@Select("select * from teacher where id=#{id}")
	public teacher getById(int id);
	
}

service

@Service
public class teachService {
	@Autowired
	private teachMapper tm;

	public teacher getById(int id) {
		return tm.getById(id);
	}
	
	public void save(teacher t) {
		tm.save(t);
	}
}

Controller

@RestController
@RequestMapping("/teacher")
public class teachController {
	@Autowired
	private teachService ts;

	@GetMapping("/{id}")
	public teacher get(@PathVariable("id") int id) {
		return ts.getById(id);
	}
	@PostMapping("/save")
	public String save(teacher t) {
		ts.save(t);
		return "保存成功";
	}
}

四:druid配置

用druid的原因:一个因为听说它性能很强,另一个主要的原因为可以进行实时监控


@WebFilter(filterName="druidWebStatFilter",urlPatterns="/*",
initParams={
    @WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源
})
public class DruidStatFilter extends WebStatFilter {

}
@SuppressWarnings("serial")
@WebServlet(urlPatterns = "/druid/*", 

		initParams = { @WebInitParam(name = "allow", value = "127.0.0.1"), // IP白名单
		@WebInitParam(name = "deny", value = "192.168.0.0"), // IP黑名单 (存在共同时,deny优先于allow)
		@WebInitParam(name = "loginUsername", value = "admin"), // 用户名
		@WebInitParam(name = "loginPassword", value = "admin"), // 密码
		@WebInitParam(name = "resetEnable", value = "false")// 禁用HTML页面上的“Reset All”功能
})
public class DruidStatViewServlet extends StatViewServlet {

}

最后,在启动类上面加上@ServletComponentScan

@SpringBootApplication
//注意要加上@ServletComponentScan注解,否则Servlet无法生效
@ServletComponentScan
public class TomApplication {

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

五,启动项目,登录http://localhost:8080/druid/index.html 查看监控情况

简直优秀。

Spring Boot 集成mybatis 用Redis做二级缓存_第1张图片

二:将Redis作为mysql的二级缓存

配置Redis

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

接下来的步骤:①开启mybatis的二级缓存 ②重写缓存类  ③将mybatis的缓存替换为们重写的

重点:我们重写mybatis的cache类,它只会对配置文件类型的映射文件起作用

主要的作用如下:

1.所有在映射文件里的 select 语句都将被缓存。
2.所有在映射文件里 insert,update 和 delete 语句会清空缓存。
3.缓存使用“最近很少使用”算法来回收
4.缓存不会被设定的时间所清空。

一:开启二级缓存,配置中加一条就好

mybatis:
      configuration:
        cache-enabled: true

二:重写缓存类

这里也有一个问题,由于cache不是容器中的类,我们需要获得applicationContext

@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 getBean(String name) {
        checkApplicationContext();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 从静态变量ApplicationContext中取得Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    public static  T getBean(Class 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");
        }
    }


}

重写缓存类

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

我在映射文件中写了增,删,查3个方法




	
	
	
	
	insert into teacher values(null,#{age},#{name})
	
	
	delete from teacher where id=#{id}
	

OK!!让我看一下效果

结果为:select会添加数据到redis,insert,update,delete会清空缓存

但是这样子好像有点坑了,除select外的操作都要清空缓存,有待研究

 

 

你可能感兴趣的:(Spring,Boot)