SpringBoot连接到Redis:似乎没有缓存数据

8ulbf1ek  于 2023-04-19  发布在  Spring
关注(0)|答案(1)|浏览(158)

我使用SpringBoot连接到Redis。我对SpringBoot有Web依赖,我的意图是将产品信息写入运行时数据结构,即Map。我想测试Spring提供该高速缓存注解以了解用法。
下面是POM.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>io.fireacademy</groupId>
    <artifactId>redisconnectivity</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>redisconnectivity</name>
    <description>Demo project for Spring Boot &amp; Redis connectivity</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <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>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

下面是Spring Application类

package io.fireacademy.redisconnectivity;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class RedisconnectivityApplication {

    public static void main(String[] args) {
        SpringApplication.run(RedisconnectivityApplication.class, args);
    }
}

下面是我的主控制器类

package io.fireacademy.redisconnectivity.controllers;

import io.fireacademy.redisconnectivity.model.Product;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/products")
public class WebAppController {

    private static final Logger logger = LoggerFactory.getLogger(WebAppController.class);

    // This will serve as the database
    private Map<String, Product> m_productDatabase = new HashMap<String, Product>();

    @Cacheable(value="my-product-cache", key="#productId")
    private Product getProductFromCacheOrDB(String productId)
    {
        logger.info("Loading the Product " + productId + " from the cache!.");
        return m_productDatabase.get(productId);
    }

    @CacheEvict(value="my-product-cache", key="#productId")
    private Product deleteFromCache(String productId)
    {
        logger.info("Remove the Product " + productId + " from the cache!.");
        return m_productDatabase.get(productId);
    }

    @GetMapping(path="/")
    public ResponseEntity<List<Product>> getProducts()
    {
        Collection<Product> allProducts = m_productDatabase.values();

        List<Product> allProductsAsList = allProducts.stream().collect(Collectors.toList());

        return new ResponseEntity<List<Product>>(allProductsAsList, HttpStatus.OK);
    }

    @GetMapping(path="/{productId}")
    public ResponseEntity<Product> getProducts(@PathVariable String productId)
    {
        // Either from the Cache or from the DB.
        Product product = getProductFromCacheOrDB(productId);

        return new ResponseEntity<Product>(product, HttpStatus.OK);
    }

    @PostMapping(consumes = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE},
            produces = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<Product> createProduct(@RequestBody Product product)
    {
        m_productDatabase.put(product.getId(), product);

        return new ResponseEntity<Product>(product, HttpStatus.CREATED);
    }

    @PutMapping(path="/{productId}",
                consumes = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE},
                produces = {MediaType.APPLICATION_XML_VALUE,MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<Product> updateProduct(@PathVariable String productId, @RequestBody Product product)
    {
        m_productDatabase.put(productId, product);
        return new ResponseEntity<Product>(product, HttpStatus.OK);
    }

    @DeleteMapping(path="/{productId}")
    public ResponseEntity<Product> deleteProduct(@PathVariable String productId)
    {
        Product deletedProduct = getProductFromCacheOrDB(productId);
        deleteFromCache(productId);

        return new ResponseEntity<Product>(deletedProduct, HttpStatus.OK);
    }
}

这是我的RedisConfig类

package io.fireacademy.redisconnectivity.configurations;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@EnableRedisRepositories
public class RedisConfig {

    @Bean
    public JedisConnectionFactory connectionFactory() {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        configuration.setHostName("localhost");
        configuration.setPort(6379);
        return new JedisConnectionFactory(configuration);
    }

    @Bean
    public RedisTemplate<String, Object> template() {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory());
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new JdkSerializationRedisSerializer());
        template.setValueSerializer(new JdkSerializationRedisSerializer());
        template.setEnableTransactionSupport(true);
        template.afterPropertiesSet();
        return template;
    }
}

我的application.properties看起来如下:

# Redis Config
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379

我将Redis作为一个docker容器运行:

docker run -d -p 6379:6379 --name my-redis redis

当我检查docker容器的日志时,我没有看到任何事情发生。

D:\Development\springboot\learn_redis>docker logs -f c376f1be9be35281b900c2943fbf8ea37e1563157efb57d46ca1c74fc880bc5c
1:C 04 Jun 2022 17:49:51.854 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1:C 04 Jun 2022 17:49:51.854 # Redis version=7.0.0, bits=64, commit=00000000, modified=0, pid=1, just started
1:C 04 Jun 2022 17:49:51.854 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
1:M 04 Jun 2022 17:49:51.854 * monotonic clock: POSIX clock_gettime
1:M 04 Jun 2022 17:49:51.858 * Running mode=standalone, port=6379.
1:M 04 Jun 2022 17:49:51.858 # Server initialized
1:M 04 Jun 2022 17:49:51.858 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
1:M 04 Jun 2022 17:49:51.858 * The AOF directory appendonlydir doesn't exist
1:M 04 Jun 2022 17:49:51.858 * Ready to accept connections

我的理解是该高速缓存注解会将数据存储到Redis的缓存中。例如,getProductFromCacheOrDB,应该将Product对象存储到缓存中,并将输入productId作为键,因为@Cacheable注解和随后使用GET productId获取此特定Product的调用不应该再次调用该方法。但这并没有发生。
请告诉我一些我可能错过的东西...
谢谢你,帕万。
编辑:
1.我在Redis上没有看到任何正在创建的内容。我通过redis-cli在Redis上启用了监控,但什么也没有看到。
1.我尝试删除RedisConfig类,没有看到任何变化。

ffx8fchx

ffx8fchx1#

刚刚在https://github.com/bsbodden/basic-caching-spring-data-redis上创建了一个简单的工作示例
您的需求:

  1. POM依赖性:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

1.在app类或configurer @EnableCaching中:

@SpringBootApplication
@EnableCaching
public class DemoApplication {

1.在app类RedisCacheManager bean中:

@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
  RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() //
      .prefixCacheNameWith(this.getClass().getPackageName() + ".") //
      .entryTtl(Duration.ofHours(1)) //
      .disableCachingNullValues();

  return RedisCacheManager.builder(connectionFactory) //
      .cacheDefaults(config) //
      .build();
}
  1. @Cacheable在您的控制器:
@GetMapping("/{id}")
@Cacheable("some-cache")
public SomeModel get(@PathVariable("id") String id) {
  return repo.findById(id).orElse(SomeModel.of("nope"));
}

相关问题