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官网中建议的匹配版本, 例如下图