Hi I'm Shendi
SpringBoot integrates Redis, basic use
Article directory
After learning Redis before, you can use SpringBoot to integrate Redis, which is very simple to use
Introduction
Jedis used to operate Redis with Java before, in SpringBoot, after version 2.x, it was replaced with Lettuce
Jedis is not thread-safe, if you want to be safe, you need to use jedis pool connection pool, like BIO
Lettuce is implemented based on Netty and is thread-safe, more like NIO
Spring Data
It is a module of data operation in Spring, including the integration of various databases
For Redis, use Spring Data Redis, which provides RedisTemplate
to operate Redis
In addition to general commands, the corresponding functions of Redis types are as follows
function | describe |
---|---|
opsForValue | Operate the String type |
opsForHash | Operation Hash type |
opsForList | Operate the List type |
opsForSet | Operation Set type |
opsForZSet | Operation ZSet type |
Introduce dependencies
Using Spring Data Redis
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
It should be noted that SpringBoot version 2.5 or below also needs to introduce a connection pool
It is measured that the 2.5.1 version will report an error without introducing the following dependencies, and the 2.6.1 version is no problem
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
configuration
It should be noted that the lettuce used by spring data redis after version 2.x used jedis before, so use it after configuring connection pool 2.xspring.redis.lettuce
application.properties
# 服务器地址
spring.redis.host=localhost
# 端口
spring.redis.port=6379
# 使用哪个数据库,默认有16个数据库,从0开始,0-15
spring.redis.database=0
# 密码
spring.redis.password="admin"
# 连接池配置部分
# 最大连接数,负数代表没有限制
spring.redis.jedis.pool.max-active=30
# 最大阻塞时间,负数代表没有限制,单位毫秒,加上ms更加明确
spring.redis.jedis.pool.max-wait=3000ms
# 最大空闲连接
spring.redis.jedis.pool.max-idle=10
# 最小空闲连接
spring.redis.jedis.pool.min-idle=1
# 连接超时时间,单位毫秒
spring.redis.timeout=6000
use
First you need to get RedisTemplate
the object, you can directly use @Autowirted
the injection
For example simply set a value, use Junit test
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
@SpringBootTest
public class TestRedis {
@Autowired RedisTemplate<String, String> rt;
@Test
public void test() {
rt.opsForValue().set("name", "Shendi");
}
}
Enter redis-cli to see if there is a name value
The method of use is similar to the previous jedis , but there will be problems when setting Chinese in this way, for example
rt.opsForValue().set("name2", "砷碲");
Using redis-cli, the solution is to set the command line encoding to UTF-8, and bring the --raw parameter when starting
# 设置utf-8编码
chcp 65001
redis-cli -p 6379 --raw
custom serialization method
For special requirements, such as directly storing an object (Bean) in Redis, you need to customize the serialization method.
JSON serialization
write a configuration class
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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory rcf) {
RedisTemplate<String, Object> rt = new RedisTemplate<>();
rt.setConnectionFactory(rcf);
Jackson2JsonRedisSerializer<Object> jsonrs = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jsonrs.setObjectMapper(om);
// 键 key,hashKey 用String序列化
rt.setKeySerializer(RedisSerializer.string());
rt.setHashKeySerializer(RedisSerializer.string());
// 值 value,hashValue 用JSON序列化
rt.setValueSerializer(jsonrs);
rt.setHashValueSerializer(jsonrs);
return rt;
}
}
Here I stepped on a pit, the new test project did not introduce web dependencies, so an error was reported when the test case was started
Error creating bean with name ‘redisTemplate’ defined in class path
...wasting a lot of time, searching Baidu to add some common, jedis dependencies... Finally, I added the web dependencies by mistake and I was able to run
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
The test code is as follows. It should be noted that the bean must implement the Serializable interface, and the inner class needs to be statically or practically constructed without parameters to create objects
import java.io.Serializable;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
@SpringBootTest
public class TestRedis {
@Autowired RedisTemplate<String, Object> rt;
static class Info implements Serializable {
String name;
String name2;
String web;
public Info() {
}
public Info(String name, String name2, String web) {
this.name = name;
this.name2 = name2;
this.web = web;
}
}
@Test
public void test() {
rt.opsForValue().set("name2", "砷碲");
rt.opsForValue().set("info", new Info("Shendi", "砷碲", "sdpro.top"));
Object name2 = rt.opsForValue().get("name2");
Info info = (Info) rt.opsForValue().get("info");
System.out.println(name2);
System.out.println(info);
}
}
The code execution output is as follows
simple example
The following shows an example of SpringBoot+Redis user login, to deepen the impression, for reference only
The page will not be done, just make the interface and highlight the use of Redis
Redis is a key-value database. Generally, the prefix + content is used as the key, and a class can be used to save and manage all the keys.
Application
@SpringBootApplication
public class Application {
/** SpringBoot环境 */
private static ConfigurableApplicationContext context;
public static void main(String[] args) {
context = SpringApplication.run(Application.class, args);
}
/** @return SpringBoot运行环境 */
public static ConfigurableApplicationContext getContext() {
return context; }
}
The context is provided here for getBean. It should be noted that the context cannot be obtained by using Junit
Because the content is distinguished by the key prefix, the operation of Redis can be encapsulated, such as the temporary information stored by the user login
/**
* 关于Redis登录信息的操作.<br>
* <br>
* @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
*/
@Component
public class RedisLogin {
/** key 前缀 */
public static final String PREFIX = "login:";
public void set(String key, String value) {
// 存入的数据一小时后过期
RedisUtil.RT.opsForValue().set(PREFIX + key, value, 1, TimeUnit.HOURS);
}
public String get(String key) {
return RedisUtil.RT.opsForValue().get(PREFIX + key);
}
}
Marked @Component
, you can use it on other classes @Autowired
to get
The RedisUtil.RT above is that I used RedisTemplate as a static object. Of course, I can also define the object directly in the class and then inject it
RedisUtil
public class RedisUtil {
/** Redis */
public static final StringRedisTemplate RT;
public static final RedisLogin LOGIN;
static {
RT = Application.getContext().getBean(StringRedisTemplate.class);
LOGIN = Application.getContext().getBean(RedisLogin.class);
}
}
UserControl
@RestController
public class UserControl {
private String account = "admin";
private String pwd = "admin";
@GetMapping("/login")
public String login(String account, String pwd) {
if (this.account.equals(account) && this.pwd.equals(pwd)) {
String token = String.valueOf(System.currentTimeMillis());
// 存入Redis
RedisUtil.LOGIN.set(account, token);
return "登陆成功, token=" + token;
}
return "登陆失败";
}
@GetMapping("/info")
public String info(String account, String token) {
// 有效登录则获取信息
String t = RedisUtil.LOGIN.get(account);
if (t == null || !t.equals(token)) {
return "未登录或登陆失效";
}
return "信息为xxx";
}
}
There are two interfaces, one login and one info
login obtains token information through account password, and info obtains user information through account number and token
After successful login, you can see the data in redis
Using the wrong information will also fail to obtain
The data is stored on Redis, so that even if SpringBoot restarts, the login information will not be lost
Because the expiration time is set, use the ttl command to view the remaining time of the key (seconds)
END