SpringBoot整合Redis
安装Redis
网上安装Redis的教程很多,这里就不在赘述了,可参考:Redis安装
创建一个SpringBoot项目
这里用IDEA编辑器
在pom.xml文件中引入Redis依赖
<!-- spring boot redis Redis弹簧启动 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Redis连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
Spring Boot框架中已经集成了redis,在1.x.x的版本中默认使用jedis客户端,而在2.x.x版本中默认使用的lettuce客户端。
两种客户端的区别如下:
- Jedis和Lettuce都是Redis Client
- Jedis 是直连模式,在多个线程间共享一个 Jedis 实例时是线程不安全的,
- 如果想要在多线程环境下使用 Jedis,需要使用连接池,
- 每个线程都去拿自己的 Jedis 实例,当连接数量增多时,物理连接成本就较高了。
- Lettuce的连接是基于Netty的,连接实例可以在多个线程间共享,
- 所以,一个多线程的应用可以使用同一个连接实例,而不用担心并发线程的数量。
- 当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。
- 通过异步的方式可以让我们更好的利用系统资源,而不用浪费线程等待网络或磁盘I/O。
- Lettuce 是基于 netty 的,netty 是一个多线程、事件驱动的 I/O 框架,
- 所以 Lettuce 可以帮助我们充分利用异步的优势。
我的项目是使用的是Spring Boot 2.3.4.RELEASE,所以采用lettuce来进行配置。
添加配置
1、修改application.properties文件名为application.yml,在其中添加Redis配置信息。
application.yml
spring:
redis:
database: 0 # Redis数据库索引(默认为0)
host: localhost # Redis服务器地址
port: 6379 # Redis服务器连接端口
password: # Redis服务器连接密码(默认为空)
lettuce:
pool:
max-active: 8 # 连接池最大连接数(使用负值表示没有限制) 默认 8
max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
max-idle: 8 # 连接池中的最大空闲连接 默认 8
min-idle: 0 # 连接池中的最小空闲连接 默认 0
2、.添加一个Redis配置类,使用@EnableCaching注解来开启缓存。
RedisConfig.java
package com.example.lzmvlog.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
}
编写业务逻辑
1、编写一个简单的用户实体类,包含用户名和密码。
User.java
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "{username:" + getUsername() + ", password:" +getPassword() + "}";
}
}
2、编写一个业务控制器,分别编写测试字符串和对象的存取接口,另外还通过@Cacheable(value=“user-key”)注解给方法开启缓存,这样就可以缓存方法返回的结果,只有当缓存不存在的时候采用执行方法返回新的用户对象。
RedisControll.java
package com.example.lzmvlog.controller;
import com.example.lzmvlog.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.sql.SQLOutput;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/re")
public class RedisController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate;
@GetMapping("/testString")
public String testString(String name){
stringRedisTemplate.opsForValue().set("l_name", name);
String l_name = stringRedisTemplate.opsForValue().get("l_name");
return "the value of key 'l_name' is :" + l_name;
}
@GetMapping("/testObject")
public String testObject(){
StringBuilder result = new StringBuilder();
User user = new User();
user.setUsername("kebi");
user.setPassword("123456");
ValueOperations<String, User> operations = redisTemplate.opsForValue();
operations.set("sys.user", user);
operations.set("sys.user.timeout", user, 1, TimeUnit.SECONDS); // 设置一秒后过时
result.append("过期前:").append("\n");
result.append("sys.user=" + operations.get("sys.user") ).append("\n");
result.append("sys.user.timeout=" + operations.get("sys.user.timeout"));
try {
Thread.sleep(1000);
}catch (InterruptedException e) {
e.printStackTrace();
}
result.append("\n").append("过期后:").append("\n");
result.append("sys.user=" + operations.get("sys.user")).append("\n");
result.append("sys.user.timeout=" + operations.get("sys.user.timeout"));
return result.toString();
}
@GetMapping("/getUser")
@Cacheable(value = "user-key")
public User getUser(){
User user = new User();
user.setUsername("kebi");
user.setPassword("123456");
System.out.println("缓存不存在,返回一个新对象");
return user;
}
}
测试
1、启动项目,调用testString接口,
URL:http://localhost:8081/re/testString?name=kebi
注:这里我改了服务的端口号,默认是8080
2、调用testObject接口,如果能出现如下图所示结果就说明成功了。
3、调用getUser接口,此时因为是第一次调用此方法,所以没有key值为“user-key”的缓存,所以会执行方法并将返回结果进行缓存。在执行getUser方法的时候控制台输出了我们添加的提示信息如下。
缓存不存在,返回一个新对象
然后再次调用getUser接口,发现getUser没有再次被执行,控制台也没有输出上一步的提示信息,那是因为在方法调用之前,应用从key值为“user-key”的缓存中获取成功,所以并不需要继续执行getUser方法的内容了。
参考资料
相关导航
SpringBoot整合SSM教程
通俗易懂的正则表达式入门及应用
javaScript中操作数组的高阶方法filter、map、reduce及for循环三种遍历形式