package org.redislearn.configuration;
import java.lang.reflect.Method;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
@EnableCaching
@Configuration
public class RedisConfiguration extends CachingConfigurerSupport{
/*
* key的生成策略(根据目标对象,本例是service实现类,以及其中的方法,参数拼接成一个key)
* 可以根据业务需求更改策略
*/
@Override
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
/*
* 参数1:要操作的目标对象
* 参数2:要操作的方法
* 参数3:执行方法时的参数
*/
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sBuilder = new StringBuilder();
sBuilder.append(target.getClass().getName());
sBuilder.append(".");
sBuilder.append(method.getName()); //生成key
for(Object object:params){
sBuilder.append(".");
sBuilder.append(object.toString());
}
return sBuilder.toString();
}
};
}
/**
* redisTemplate相关配置 RedisTemplate操作Redis
* @param factory
* @return
*/
@Bean
@SuppressWarnings("all")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
//设置工厂
template.setConnectionFactory(factory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
//(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
//创建对象映射
ObjectMapper mapper = new ObjectMapper();
//指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
mapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
//指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer
//等会抛出异常
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
//
jackson2JsonRedisSerializer.setObjectMapper(mapper);
//字符串序列化器
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
//hash的key也采用String的方式
template.setHashKeySerializer(stringRedisSerializer);
//value采用jackson的方式
template.setValueSerializer(jackson2JsonRedisSerializer);
//hash的value也采用Jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
server:
port: 8080
mybatis:
config-location: classpath:mybatis-config.xml
type-aliases-package: org.xxxx.entity
mapper-locations:
- classpath:mapper/*.xml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
username: root
password: 123456
redis:
host: 127.0.0.1
port: 6379
jedis:
pool:
max-active: 10
max-idle: 5
min-idle: 2
max-wait: -1
//在需要使用的地方利用spring注入RedisTemplate对象
@Autowired
private RedisTemplate<String,Object> redisTemplate;
ps:存入redis的实体类数据需要实现序列化接口,不然会报
org.springframework.data.redis.serializer.SerializationException: Cannot deserialize;
至于原理,可以看看我看过的这篇文章了解一下
Redis为什么需要序列化https://www.zhihu.com/question/277363840/answer/392945240
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product implements Serializable {//redis need to serialize
private int pid;
private String pname;
private double price;
private int store;
private List<String> images;
private String detail;
}
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductMapper productMapper;
@Cacheable("findAll")
@Override
public List<Product> all() {
return productMapper.all();
}
@Cacheable("findById")
@Override
public Product findProductByPid(int pid) {
return productMapper.findProductByPid(pid);
}
//把跟这个id有关的数据都要删除,这里是"findAll"和"findById"
@CacheEvict(value = {"findAll","findById"},allEntries = true)
@Override
public int deleteProductByPid(int pid) {
return productMapper.deleteProductByPid(pid);
}
}
public class RedisUtil {
public static String generate(String namespace,Object target, String method, Object... params) {
StringBuilder sBuilder = new StringBuilder();
sBuilder.append(namespace);
sBuilder.append("::"); //自动生成的key会有双冒号
sBuilder.append(target.getClass().getName());
sBuilder.append(".");
sBuilder.append(method); //生成key
for(Object object:params){
sBuilder.append(".");
sBuilder.append(object.toString());
}
return sBuilder.toString();
}
}
//定义一个需要的命名空间
private static final String NAMESPACE = "findProductByPid";
//删除指定的key
@CacheEvict(value = "findAll",allEntries = true)
@Override
public int deleteProductByPid(int pid){
//前缀 this method 参数
String key = RedisUtil.generate(NAMESPACE,this,"findProductByPid",pid);
System.out.println(key);
//操作删除指令
redisTemplate.delete(key);
return productMapper.deleteProductByPid(pid);
}
初学redis,若有纰漏,望各位不吝赐教
原文:https://www.cnblogs.com/0nePlece/p/13228041.html