Springboot开启方法的缓存

为啥要启用缓存
  1. 提高性能,针对同一个方法,当再次请求时传递的参数没发生变化时,直接返回上次查询的结果,不再执行方法中的业务逻辑
开启缓存
  1. 在启动类添加@EnableCaching 注解
  2. 在方法上使用 @Cacheable(value = “user”,key = “#p0”)注解,key和value可以自定义。
解释
@Cacheable(value = "user",key = "#p0")

value表示此缓存内容的缓存位置,不同方法的value应该使用不一样的值防止被覆盖。
key中的#p0表示方法的第一个参数值,当再次请求此方法,传递的值如果没发生变化,则直接从缓存中取,不再执行方法中的代码。

实验

做一个实验,把两个不同的方法key和vaue设置成一样,并且分别请求这两个方法,请求的时候参数值也给他传一样的,只有请求路径不一样,请求如下:

@RestController
@RequestMapping("/testBoot")
public class UserController {
    
    

    @Autowired
    private UserService userService;

    @RequestMapping("getUser/{id}")
    @Cacheable(value = "user",key = "#p0")
    public User GetUser(@PathVariable int id){
    
    
        System.out.println("test.....");
        return userService.Sel(id);
    }

    @RequestMapping("getUsers/{id}")
    @Cacheable(value = "user",key = "#p0")
    public List<User> getUsers(@PathVariable int id){
    
    
        System.out.println("getuesrs.....");
        return userService.getUsers();
    }
}
实验一,验证缓存成功

第一次请求http://localhost:8080/testBoot/getUsers/3,可以看到结果如下:
在这里插入图片描述
此时我们把数据库中张三的money随便改成其他数字,再次请求http://localhost:8080/testBoot/getUsers/3会发现查出来的结果没变,说明我们设置的缓存生效了。

实验二,验证缓存名字冲突

接着上边,这次请求http://localhost:8080/testBoot/getUser/3,请求路径变了,参数依然是3,结果如下:
在这里插入图片描述
原因:因为这请求执行的方法缓存的地址名也叫user,并且传递的参数也是3,所以程序认为此次请求应该直接从缓存获取结果,不用再执行代码。于是乎它就从程序获取到上次缓存的List 并且想把它反序列化成User,结果就报错java.lang.ClassCastException

整合redis

加入redis后,会自动把缓存放到redis中管理

  1. 添加依赖
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
  1. 配置redis
spring:
    redis:
        database: 9
        host: 192.168.2.250
        password: sonoscape
        port: 6379
        ssl: false
        timeout: 5000 # Connection timeout.

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.*;
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.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import javax.annotation.Resource;

import static org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig;

@Configuration
public class CacheConfig extends CachingConfigurerSupport {
    
    

    @Resource
    private RedisConnectionFactory factory;

    /**
     * 自定义生成redis-key
     *
     * @return
     */
    @Override
    @Bean
    public KeyGenerator keyGenerator() {
    
    
        return (o, method, objects) -> {
    
    
            StringBuilder sb = new StringBuilder();
            sb.append(o.getClass().getName()).append(".");
            sb.append(method.getName()).append(".");
            for (Object obj : objects) {
    
    
                sb.append(obj.toString());
            }
            System.out.println("keyGenerator=" + sb.toString());
            return sb.toString();
        };
    }

    @Bean
    public RedisTemplate<Object, Object> redisTemplate() {
    
    
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);

        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();

        redisTemplate.setKeySerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);

        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
        return redisTemplate;
    }

    @Bean
    @Override
    public CacheResolver cacheResolver() {
    
    
        return new SimpleCacheResolver(cacheManager());
    }

    @Bean
    @Override
    public CacheErrorHandler errorHandler() {
    
    
        // 用于捕获从Cache中进行CRUD时的异常的回调处理器。
        return new SimpleCacheErrorHandler();
    }

    @Bean
    @Override
    public CacheManager cacheManager() {
    
    
        RedisCacheConfiguration cacheConfiguration =
                defaultCacheConfig()
                        .disableCachingNullValues()
                        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        return RedisCacheManager.builder(factory).cacheDefaults(cacheConfiguration).build();

    }
}

猜你喜欢

转载自blog.csdn.net/chen462488588/article/details/114405077