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/392945240java
@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); }
至此,如有紕漏,望各位不吝賜教mysql