自定义mybatisplus的redis二级缓存
时间: 2023-05-25 18:05:49 浏览: 220
MybatisPlus已经提供了redis二级缓存的实现,只需要在配置文件中开启对应选项即可。如果需要自定义redis二级缓存的实现,可以通过实现`Cache`接口来实现。
1. 定义缓存类
```java
public class RedisCache implements Cache {
private RedisTemplate<Object, Object> redisTemplate;
private String cacheName;
private final String CACHE_PREFIX = "mybatis_cache:";
public RedisCache(String cacheName) {
this.cacheName = cacheName;
}
@Override
public String getId() {
return CACHE_PREFIX + cacheName;
}
@Override
public void putObject(Object key, Object value) {
redisTemplate.opsForHash().put(getId(), key, value);
}
@Override
public Object getObject(Object key) {
return redisTemplate.opsForHash().get(getId(), key);
}
@Override
public Object removeObject(Object key) {
return redisTemplate.opsForHash().delete(getId(), key);
}
@Override
public void clear() {
redisTemplate.delete(getId());
}
@Override
public int getSize() {
return Math.toIntExact(redisTemplate.opsForHash().size(getId()));
}
@Override
public ReadWriteLock getReadWriteLock() {
return null;
}
public void setRedisTemplate(RedisTemplate<Object, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
}
```
2. 配置RedisTemplate
```java
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setDefaultSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
```
3. 配置RedisCacheManager
```java
@Bean
public RedisCacheManager redisCacheManager(RedisTemplate<Object, Object> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(new RedisCacheWriter() {
@Override
public void put(String name, byte[] key, byte[] value, Duration ttl) {
redisTemplate.opsForHash().put(name, key, value);
}
@Override
public byte[] get(String name, byte[] key) {
return redisTemplate.opsForHash().get(name, key);
}
@Override
public byte[] putIfAbsent(String name, byte[] key, byte[] value, Duration ttl) {
byte[] currentValue = get(name, key);
if (currentValue == null) {
put(name, key, value, ttl);
return null;
} else {
return currentValue;
}
}
@Override
public void remove(String name, byte[] key) {
redisTemplate.opsForHash().delete(name, key);
}
@Override
public void clean(String name, byte[] pattern) {
Set<Object> keys = redisTemplate.opsForHash().keys(name);
if (!CollectionUtils.isEmpty(keys)) {
for (Object key : keys) {
byte[] keyBytes = (byte[]) key;
if (WildcardMatcher.match(new String(pattern), new String(keyBytes))) {
remove(name, keyBytes);
}
}
}
}
@Override
public void clear(String name) {
redisTemplate.delete(name);
}
@Override
public void close() {
// do nothing
}
},redisTemplate);
return cacheManager;
}
```
4. 配置缓存设置
```java
@MapperScan(value = "com.example.mapper", annotationClass = MyBatisPlusRedisCache.class)
@Configuration
public class RedisCacheConfig extends MybatisPlusPropertiesCustomizer {
private final RedisTemplate<Object, Object> redisTemplate;
private final RedisCacheManager redisCacheManager;
public RedisCacheConfig(RedisTemplate<Object, Object> redisTemplate, RedisCacheManager redisCacheManager) {
super();
this.redisTemplate = redisTemplate;
this.redisCacheManager = redisCacheManager;
}
@Override
public void customize(MybatisPlusProperties properties) {
// 开启redis缓存
properties.getGlobalConfig().setCacheEnabled(true);
properties.getGlobalConfig().setDefaultCache(new RedisCache(MpRedisCacheEnum.SECOND_CACHE_MODE.getCacheName()));
// 自定义redis缓存
Map<String, Cache> cacheMap = new HashMap<>();
cacheMap.put(MpRedisCacheEnum.SECOND_CACHE_MODE.getCacheName(), new RedisCache(MpRedisCacheEnum.SECOND_CACHE_MODE.getCacheName()));
redisCacheManager.setCaches(cacheMap);
MybatisConfiguration configuration = properties.getConfiguration();
configuration.addInterceptor(new MybatisPlusRedisCacheInterceptor());
}
}
```
5. 配置自定义拦截器
```java
public class MybatisPlusRedisCacheInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
Object parameter = invocation.getArgs()[1];
CacheKey cacheKey = mappedStatement.getCacheKey(parameter, mappedStatement.getConfiguration(), mappedStatement.getBoundSql(parameter));
BoundSql boundSql = mappedStatement.getBoundSql(parameter);
Cache cache = mappedStatement.getCache();
if (cache instanceof RedisCache) {
RedisCache redisCache = (RedisCache) cache;
redisCache.setRedisTemplate(SpringUtil.getBean(RedisTemplate.class));
}
return invocation.proceed();
}
}
```
6. 定义注解标记需要采用自定义Redis缓存的方法
```java
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyBatisPlusRedisCache {
}
```
7. 在Mapper方法上添加注解
```java
@Mapper
@MyBatisPlusRedisCache
public interface UserMapper extends BaseMapper<User> {
}
```
这样就完成了自定义Redis二级缓存的实现。注意,如果需要使用分布式锁来保证多线程下的缓存穿透问题,需要在putObject方法中添加分布式锁逻辑。
阅读全文