同时使用缓存和数据库
运用框架的模式
启动类
要添加@EnableCaching注释
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
要配置config类
package com.xsz.config;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
// 自定义缓存key生成策略
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, java.lang.reflect.Method method, Object... params) {
StringBuffer sb = new StringBuffer();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
// 缓存管理器
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时
return RedisCacheManager
.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))
.cacheDefaults(redisCacheConfiguration).build();
}
@Bean
@SuppressWarnings({"rawtypes", "unchecked"})
public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory connectionFactory){
RedisTemplate<Object,Object> redisTemplate=new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
//使用Jackson2JsonRedisSerializer替换默认的序列化规则
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer=new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper=new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
//设置value的序列化规则
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
//设置key的序列化规则
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
// private void setSerializer(StringRedisTemplate template) {
// @SuppressWarnings({ "rawtypes", "unchecked" })
// Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
// ObjectMapper om = new ObjectMapper();
// om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// jackson2JsonRedisSerializer.setObjectMapper(om);
// template.setValueSerializer(jackson2JsonRedisSerializer);
// }
}
配置service层
package com.xsz.service;
/**
* @Description: java类作用描述
* @Author: Bsea
* @CreateDate: 2019/9/15$ 20:28$
*/
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisTemplateService {
@Autowired
StringRedisTemplate stringRedisTemplate;
public <T> boolean set(String key ,T value){
try {
//任意类型转换成String
String val = beanToString(value);
if(val==null||val.length()<=0){
return false;
}
stringRedisTemplate.opsForValue().set(key,val);
return true;
}catch (Exception e){
return false;
}
}
public <T> T get(String key,Class<T> clazz){
try {
String value = stringRedisTemplate.opsForValue().get(key);
return stringToBean(value,clazz);
}catch (Exception e){
return null ;
}
}
@SuppressWarnings("unchecked")
private <T> T stringToBean(String value, Class<T> clazz) {
if(value==null||value.length()<=0||clazz==null){
return null;
}
if(clazz ==int.class ||clazz==Integer.class){
return (T)Integer.valueOf(value);
}
else if(clazz==long.class||clazz==Long.class){
return (T)Long.valueOf(value);
}
else if(clazz==String.class){
return (T)value;
}else {
return JSON.toJavaObject(JSON.parseObject(value),clazz);
}
}
/**
*
* @return String
*/
private <T> String beanToString(T value) {
if(value==null){
return null;
}
Class <?> clazz = value.getClass();
if(clazz==int.class||clazz==Integer.class){
return ""+value;
}
else if(clazz==long.class||clazz==Long.class){
return ""+value;
}
else if(clazz==String.class){
return (String)value;
}else {
return JSON.toJSONString(value);
}
}
}
实体对象中的修改
修改后:
public class Blog implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
}
修改前:
public class Blog{
}
这里要让他实现Serializable接口,具体为什么这样做也没搞明白。
Service层中也要添加注解
修改数据要使用@CachePut(key="#p0.id")
删除用@CacheEvict(key="#p0")
查询使用@Cacheable(key="#p0")
同一层service中如果只需要一个缓存的话
@CacheEvict(cacheNames=“TagCache”,allEntries=true)
@CacheEvict(cacheNames=“TagCache”,allEntries=true)
@Cacheable(cacheNames=“TagCache”)