springboot项目中mybatis使用mybatis-redis开启三级缓存需要创建redis.properties优化方案
- 前言
- 下载mybatis-redis源码分析
- RedisCache 代码
- RedisConfigurationBuilder的parseConfiguration方法
- 优化改造
- 1.创建JedisConfig类
- 2.复制RedisCache代码创建自定义的MyRedisCache
- 3.指定缓存实现类为自己的类
- xml方式
- 注解方式
- 总结
前言
Springboot项目中mybatis使用mybatis-redis开启三级缓存需要创建redis.properties优化方案,如何开启三级缓存详见 十分钟带你了解Mybatis一、二、三级缓存,赶紧用起来!。
本文主要解决在使用mybatis-redis开启三级缓存时候,必须强制创建redis.properties文件,这样导致redis配置在多个地方存在,强迫症患者是无法忍受的,下面开始我们的优化改造。
下载mybatis-redis源码分析
发现mybatis-redis也是实现Cache接口实现三级缓存
RedisCache 代码
public final class RedisCache implements Cache {private final ReadWriteLock readWriteLock = new DummyReadWriteLock();private String id;private static JedisPool pool;public RedisCache(final String id) {if (id == null) {throw new IllegalArgumentException("Cache instances require an ID");}this.id = id;RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();pool = new JedisPool(redisConfig, redisConfig.getHost(), redisConfig.getPort(),redisConfig.getConnectionTimeout(), redisConfig.getSoTimeout(), redisConfig.getPassword(),redisConfig.getDatabase(), redisConfig.getClientName());}。。。。略
}
可以看到底层采用jedis做缓存框架,通过RedisConfigurationBuilder.getInstance().parseConfiguration()去获取redis配置
RedisConfigurationBuilder的parseConfiguration方法
public RedisConfig parseConfiguration(ClassLoader classLoader) {Properties config = new Properties();InputStream input = classLoader.getResourceAsStream(redisPropertiesFilename);if (input != null) {try {config.load(input);} catch (IOException e) {throw new RuntimeException("An error occurred while reading classpath property '"+ redisPropertiesFilename+ "', see nested exceptions", e);} finally {try {input.close();} catch (IOException e) {// close quietly}}}RedisConfig jedisConfig = new RedisConfig();setConfigProperties(config, jedisConfig);return jedisConfig;
}
可以看到这边读取是redisPropertiesFilename文件
上图可以看到默认是redis.properties文件,也可以通过system参数指定,且RedisConfigurationBuilder类是一个final类,基本上没用方法可以处理。因为源码内部只支持properties文件解析,没兼容springboot配置。
优化改造
1.创建JedisConfig类
代码如下:
package com.uhu.redis.cache;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;import java.time.Duration;/*** @author liujunjie* @description* @create 2023-11-29 11:54**/
@Configuration
@Slf4j
public class JedisConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private int port;@Value("${spring.redis.password}")private String password;@Value("${spring.redis.timeout}")private Duration timeout;@Value("${spring.redis.jedis.pool.max-active}")private int maxActive;@Value("${spring.redis.jedis.pool.max-idle}")private int maxIdle;@Value("${spring.redis.jedis.pool.min-idle}")private int minIdle;@Beanpublic JedisPool jedisPool() {JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();jedisPoolConfig.setMaxIdle(maxIdle);jedisPoolConfig.setMinIdle(minIdle);jedisPoolConfig.setMaxTotal(maxActive);// 是否启用pool的jmx管理功能, 默认truejedisPoolConfig.setJmxEnabled(true);JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, Integer.parseInt(String.valueOf(timeout.toMillis())), password);log.info("JedisPool连接成功:" + host + ":" + port);return jedisPool;}
}
2.复制RedisCache代码创建自定义的MyRedisCache
代码如下:
/*** Copyright 2015 the original author or authors.* <p>* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at* <p>* http://www.apache.org/licenses/LICENSE-2.0* <p>* Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.uhu.cache;import cn.hutool.extra.spring.SpringUtil;
import org.apache.ibatis.cache.Cache;
import org.mybatis.caches.redis.RedisCallback;
import org.mybatis.caches.redis.SerializeUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;import java.util.Map;/*** Cache adapter for Redis.** @author Eduardo Macarron*/
public class MyRedisCache implements Cache {private String id;private static JedisPool pool;public MyRedisCache(final String id) {if (id == null) {throw new IllegalArgumentException("Cache instances require an ID");}this.id = id;pool = SpringUtil.getBean(JedisPool.class);}private Object execute(RedisCallback callback) {Jedis jedis = pool.getResource();try {return callback.doWithRedis(jedis);} finally {jedis.close();}}@Overridepublic String getId() {return this.id;}@Overridepublic int getSize() {return (Integer) execute(new RedisCallback() {@Overridepublic Object doWithRedis(Jedis jedis) {Map<byte[], byte[]> result = jedis.hgetAll(id.toString().getBytes());return result.size();}});}@Overridepublic void putObject(final Object key, final Object value) {execute(new RedisCallback() {@Overridepublic Object doWithRedis(Jedis jedis) {jedis.hset(id.toString().getBytes(), key.toString().getBytes(), SerializeUtil.serialize(value));return null;}});}@Overridepublic Object getObject(final Object key) {return execute(new RedisCallback() {@Overridepublic Object doWithRedis(Jedis jedis) {return SerializeUtil.unserialize(jedis.hget(id.toString().getBytes(), key.toString().getBytes()));}});}@Overridepublic Object removeObject(final Object key) {return execute(new RedisCallback() {@Overridepublic Object doWithRedis(Jedis jedis) {return jedis.hdel(id.toString(), key.toString());}});}@Overridepublic void clear() {execute(new RedisCallback() {@Overridepublic Object doWithRedis(Jedis jedis) {jedis.del(id.toString());return null;}});}@Overridepublic String toString() {return "Redis {" + id + "}";}}
3.指定缓存实现类为自己的类
xml方式
<mapper namespace="xxx"><cache type="com.uhu.redis.cache.MyRedisCache"/><!--禁用某个查询使用缓存--><select id="findAll" resultType="xxx" useCache="false"></select>
</mapper>
注解方式
@CacheNamespace(implementation = MyRedisCache.class)
@Mapper
public interface XxxDao {
}
总结
以上就是SpringBoot项目中Mybatis使用mybatis-redis开启三级缓存必须创建redis.properties优化方案,通过简单的源码改造,就可以让许多强迫症患者心情舒畅。