SpringBoot 05 集成redis实现对象序列化缓存

1.为什么用Spring Data 

        Spring Data 的目标是为数据访问提供一个基于Spring的普遍常用的编程模型,同时仍然保留底层数据存储的特殊特性, 它让使用数据访问技术、关系和非关系数据库和基于云的数据服务变得容易,它包含了很多的子项目例如Spring Data JDBC, Spring Data Redis,Spring Data MongoDB等。

       Spring Data Redis是Spring Data项目的一个子项目, 它提供了从Spring应用程序对Redis的简单配置和轻松访问的方法,将开发人员从基础设置问题中解放出来。它消除了存储交互所需啊哟的冗余任务和样板代码,使得编写使用 Redis键值存储的Spring 应用程序变得非常容易

2.SpringBoot+Redis 示例

1. 创建SpringBoot项目,参考目录结构如下

 

pom中增加spring-data-redis依赖,参考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.6.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.boot</groupId>
    <artifactId>demo-redis</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo-redis</name>
    <description>Demo project for Spring Boot + SpringData Redis</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- redis 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!-- redis 依赖 -->

        <!-- WEB应用 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

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

</project>

参考application.properties文件

server.port=8002


## Redis数据库索引,默认为0
spring.redis.database=0
## Redis数据库地址,默认为localhost
spring.redis.host=127.0.0.1
## Redis数据库端口,默认为6379
spring.redis.port=6379
# Redis服务器连接密码,默认为空
spring.redis.password=
## Redis连接超时时间,单位毫秒
spring.redis.timeout=3000
## Redis链接超时时间
spring.redis.connect-timeout=3000
## Redis连接池中的最小空闲连接数
spring.redis.jedis.pool.min-idle=0
## Redis连接池中的最大空闲连接数
spring.redis.jedis.pool.max-idle=8

注: 启动SpringBoot后自动装配会加载自动配置类RedisAutoConfiguration ,其上使用了注解@EnableConfigurationProperties(RedisProperties.class), 将RedisProperties配置生效

application.properties的配置信息会注入对象org.springframework.boot.autoconfigure.data.redis。RedisProperties 中,因此其他可用属性(spring.redis.**)可以参考RedisProperties 对象上的批注说明

3. 创建测试类UserDTO

package com.boot.redis.domain;

import java.io.Serializable;

public class UserDTO implements Serializable {

    private Long id;
    private String name;
    private String code;

    //省略getter和setter

    @Override
    public String toString() {
        return "UserDTO{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", code='" + code + '\'' +
                '}';
    }
}

通过@Configuration注解创建Bean对象RedisTemplate,

package com.boot.redis.conf;

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.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

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

        JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer();
        template.setValueSerializer(jdkSerializer);
        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }
}

4. 创建测试Controller,并注入RedisTemplate,这个类只是用于测试,实际项目中并不会以此方式处理登录信息

/login 用于模拟登录

  • @RequestParam表示登录请求中如果没有带参数,默认为zhangsan ,即/login和/login?username=zhangsan相同

  • index 每次自增长1,用于模拟不同的ID

  • redisTemplate #execute执行的时候先生成KEY 然后将对象系列化后保存到Redis中

/login 用于模拟获取登录信息

  • @RequestParam表示登录请求中如果没有带参数,默认为1,即/get和/get?uuserid=1相同
  • redisTemplate #execute执行的时候先获取Redis中的值然后再转换成对象返回
package com.boot.redis.controller;


import com.boot.redis.domain.UserDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class LoginController {

    //顺序生成ID,用于测试
    private static Long index = 1L;

    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/login")
    public String login(@RequestParam(value = "username", defaultValue = "zhangsan") String name) {
        UserDTO user = new UserDTO();
        user.setCode(""+1000+index);
        user.setName(name);
        user.setId(index++);

        redisTemplate.execute(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection connection)
                    throws DataAccessException {

                byte[] key = redisTemplate.getStringSerializer().serialize("user.id." + user.getId());

                JdkSerializationRedisSerializer s = (JdkSerializationRedisSerializer) redisTemplate.getValueSerializer();

                connection.set(key, s.serialize(user));
                System.out.println("add");
                return null;
            }
        });

        return String.format("success", name);
    }

    @GetMapping("/get")
    public String get(@RequestParam(value = "userid", defaultValue = "1") String userId) {

        Object object = redisTemplate.execute(new RedisCallback() {

            public Object doInRedis(RedisConnection connection)
                    throws DataAccessException {
                byte[] key = redisTemplate.getStringSerializer().serialize("user.id." + userId);
                if (connection.exists(key)) {
                    JdkSerializationRedisSerializer s = (JdkSerializationRedisSerializer) redisTemplate.getValueSerializer();
                    return s.deserialize(connection.get(key));
                }
                return null;
            }
        });

        if (object == null) {
            return "null";
        } else {
            return ((UserDTO) object).toString();
        }

    }
}

测试:

先启动一个Redis Server ,这部分内容可以参考 Redis 安装_学然后知不足!-CSDN博客 ,这里不再重复说明 

1. 测试请求 :http://127.0.0.1:8002/login?username=zhangsan

 

2. 测试请求:http://127.0.0.1:8002/get?userid=1

3. 通过RedisDesktopManager工具查看Redis中的信息

3.参考源码

https://github.com/PNZBEIJINGL/springboot/tree/master/demo-redis

4.常见问题

ClassNotFoundException: org.apache.commons.pool.impl.GenericObjectPool$Config

Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool.impl.GenericObjectPool$Config
	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

Spring-Data-Redis版本问题,一般是commons-pool2不匹配引起的,可以查看Maven官网中建议的匹配版本, 例如下图

 

              

                   

      

前一篇:SpringBoot 04 集成Flyway实现数据库版本控制

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个基于Spring BootRedis的键值序列化的示例代码: 首先,在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> ``` 然后,在application.properties文件中配置Redis连接信息: ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= spring.redis.database=0 spring.redis.pool.max-active=8 spring.redis.pool.max-wait=-1 spring.redis.pool.max-idle=8 spring.redis.pool.min-idle=0 ``` 接下来,我们可以创建一个RedisConfig类,用于配置RedisTemplate和RedisCacheManager: ```java @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(factory); // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式) Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(mapper); // 设置value的序列化规则和key的序列化规则 template.setValueSerializer(serializer); template.setKeySerializer(new StringRedisSerializer()); template.afterPropertiesSet(); return template; } @Bean public CacheManager cacheManager(RedisConnectionFactory factory) { RedisCacheManager cacheManager = RedisCacheManager.create(factory); cacheManager.setDefaultExpiration(1800); // 设置缓存过期时间(单位:秒) return cacheManager; } } ``` 现在,我们可以在任何需要使用Redis的地方注入RedisTemplate,并使用它来存储和读取数据。例如: ```java @Service public class UserService { @Autowired private RedisTemplate<String, Object> redisTemplate; public User getUserById(Long id) { String key = "user:" + id; User user = (User) redisTemplate.opsForValue().get(key); if (user == null) { // 从数据库中获取用户信息 user = userRepository.findById(id).orElse(null); if (user != null) { redisTemplate.opsForValue().set(key, user); } } return user; } } ``` 在上面的示例中,我们将用户信息存储在Redis中,并设置了一个过期时间。当需要获取用户信息时,首先从缓存中查找,如果缓存中没有,则从数据库中获取,并将结果存储在缓存中,以便下一次使用。这样可以大大提高系统的性能和响应速度。 总结:以上是一个基于Spring BootRedis的键值序列化的示例代码,通过使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值,可以实现最优化最高性能的键值序列化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

=PNZ=BeijingL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值