pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>bsea</groupId>
<artifactId>springboot2</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>springbootJPARedis</artifactId>
<!-- Add typical dependencies for a web application -->
<dependencies>
<!-- 添加redis的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--目的:《可选》引入springboot 热启动,每次修改以后,会自动把改动加载,不需要重启服务了 和@Cacheable 有冲突
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- <version>8.0.15</version> -->
</dependency>
<!-- 添加JPA的支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
</dependencies>
</project>
启动类
package com.xsz;
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);
}
}
配置文件
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;
import javax.annotation.Resource;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.xsz.entity.Blog;
import com.xsz.repository.BlogRepository;
import com.xsz.repository.UserRepository;
@CacheConfig(cacheNames = "blogService")
@Service
public class BlogService {
@Resource
BlogRepository blogRepository;
@Cacheable(key = "#p0")
public Blog selectByPrimaryKey(String id) {
return blogRepository.findById(id).get();
}
@CachePut(key = "#p0.id")
public Blog updateBy(Blog blog) {
return blogRepository.save(blog);
}
}
/**
*
* 1 基于注解的支持
* Spring为我们提供了几个注解来支持Spring Cache。其核心主要是@Cacheable和@CacheEvict。
* 使用@Cacheable标记的方法在执行后Spring Cache将缓存其返回结果,而使用@CacheEvict标记的方法会在方法执行前或者执行后移除Spring Cache中的某些元素。
* 下面我们将来详细介绍一下Spring基于注解对Cache的支持所提供的几个注解。
*
* 1.1 @Cacheable
* @Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,
* 当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被调用后将其返回值缓存起来,
* 以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。Spring在缓存方法的返回值时是以键值对进行缓存的,
* 值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略,这个稍后会进行说明。
* 需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。@Cacheable可以指定三个属性,value、key和condition。
*
* 1.1.1 value属性指定Cache名称
* value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。
*
* @Cacheable("cache1")//Cache是发生在cache1上的
*
* public User find(Integer id) {
*
* returnnull;
*
* }
*
*
*
* @Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的
*
* public User find(Integer id) {
*
* returnnull;
*
* }
*
*
*
* 1.1.2 使用key属性自定义key
* key属性是用来指定Spring缓存方法的返回结果时对应的key的。
* 该属性支持SpringEL表达式。当我们没有指定该属性时,
* Spring将使用默认策略生成key。
* 我们这里先来看看自定义策略,
* 至于默认策略会在后文单独介绍。
*
* 自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。
* 这里的EL表达式可以使用方法参数及它们对应的属性。
* 使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。
* 下面是几个使用参数作为key的示例。
*
* @Cacheable(value="users", key="#id")
*
* public User find(Integer id) {
*
* returnnull;
*
* }
*
*
*
* @Cacheable(value="users", key="#p0")
*
* public User find(Integer id) {
*
* returnnull;
*
* }
*
*
*
* @Cacheable(value="users", key="#user.id")
*
* public User find(User user) {
*
* returnnull;
*
* }
* 1.2 @CachePut
* 在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
*
* @CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟@Cacheable是一样的。
*
* @CachePut("users")//每次都会执行方法,并将结果存入指定的缓存中
*
* public User find(Integer id) {
*
* returnnull;
*
* }
*
*
*
* 1.3 @CacheEvict
* @CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。下面我们来介绍一下新出现的两个属性allEntries和beforeInvocation。
*
* 1.3.1 allEntries属性
* allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。
*
* @CacheEvict(value="users", allEntries=true)
*
* public void delete(Integer id) {
*
* System.out.println("delete user by id: " + id);
*
* }
*
*
*
*
*/