准备工作
1、导入依赖
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<version>5.3.6.RELEASE</version>
</dependency>
2、创建一个Redis连接对象工具类
对连接对象进行封装,
public class RedisUtils {
/**
* redis的连接对象
*/
private static StatefulRedisConnection connection;
/**
* 初始化连接对象
*/
static {
//初始化连接的uri
RedisURI redisURI = RedisURI.Builder
.redis("lettuce")
.withHost("127.0.0.1")
.withPort(6379)
.withPassword("123456")
.withDatabase(0)
.withTimeout(Duration.ofSeconds(2))
.build();
//初始化连接对象
//connection = RedisClient.create(redisURI).connect();
//初始化连接对象并设置自定义序列化器
connection = RedisClient.create(redisURI)
.connect(new ObjectRedisSerializer());
}
/**
* 从连接对象中获取一个命令来操作redis
* @return
*/
public static RedisCommands getCommands() {
//获取一个同步命令
return connection.sync();
}
}
3、创建自定义序列化器
public class ObjectRedisSerializer implements RedisCodec<String, Object> {
/**
* 这个方法将key从redis取出来的时候转换为字符串类型
* 将key的字节缓冲(ByteBuffer)转换为String类型
* @param byteBuffer
* @return
*/
@Override
public String decodeKey(ByteBuffer byteBuffer) {
//在系统中先分配内存
ByteBuffer buffer = ByteBuffer.allocate(byteBuffer.capacity());
buffer.put(byteBuffer);
//将字节数组以UTF-8的编码转换成String并返回
return new String(buffer.array(), StandardCharsets.UTF_8);
}
/**
* 从redis中取出的字节数组转换成任意的Object对象
* @param byteBuffer
* @return
*/
@Override
public Object decodeValue(ByteBuffer byteBuffer) {
//先分配系统内存空间
ByteBuffer buffer = ByteBuffer.allocate(byteBuffer.capacity());
buffer.put(byteBuffer);
//构建字节数组的输入流,这样就可以在jvm的内存中将这个字节数组
//反序列为任意的Object对象
try(ByteArrayInputStream bais =
new ByteArrayInputStream(buffer.array());
//再通过对象输入流将其转换为Object即可
ObjectInputStream ois = new ObjectInputStream(bais)) {
return ois.readObject();
}catch (IOException | ClassNotFoundException e) {
throw new RuntimeException("无法反序列化value", e);
}
}
/**
* 将字符串的key序列化成字节数组保存到redis
* @param key
* @return
*/
@Override
public ByteBuffer encodeKey(String key) {
return ByteBuffer.wrap(key.getBytes(StandardCharsets.UTF_8));
}
/**
* 将Object序列化成字节数组保存到redis中
* @param value
* @return
*/
@Override
public ByteBuffer encodeValue(Object value) {
try(ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos)) {
//将对象写入流中变成字节数组
oos.writeObject(value);
//从流中获取这个字节数组
byte[] bytes = baos.toByteArray();
//将字节数组包装成ByteBuffer对象并返回
return ByteBuffer.wrap(bytes);
}catch(IOException e) {
throw new RuntimeException("无法序列化value", e);
}
}
}
注意:这个类主要是对java中的实体类进行序列化操作,将实体类转换成json类型存储,需要实现RedisCodec<String, Object> 接口,或者不定义自定义序列化器,可以直接通过ObjectMapper对象进行序列化
4、测试
@Slf4j
public class RedisTest {
@Test
public void testLettuce() {
//获取RedisCommands命令对象
RedisCommands commands = RedisUtils.getCommands();
commands.set("user:1001", "wangl");
String val = (String) commands.get("user:1001");
log.info("=====> " + val);
Map<String, Object> map = new HashMap<>();
map.put("user:1002", "user2");
map.put("user:1003", "user3");
commands.mset(map);
List<KeyValue> list = commands.mget("user:1001",
"user:1002","user:1003");
list.forEach(keyValue -> log.info("===>" + keyValue.getValue()));
}
@Test
public void testHash() {
RedisCommands commands = RedisUtils.getCommands();
commands.hset("user", "name", "user1");
commands.hset("user", "age", "21");
commands.hset("user", "sex", "男");
log.info("==>" + commands.hget("user", "name"));
log.info("==>" + commands.hget("user", "age"));
log.info("==>" + commands.hget("user", "sex"));
}
@Test
public void testDel() {
RedisCommands commands = RedisUtils.getCommands();
//删除键
commands.del("user:1001", "user:1002", "user:1003", "user");
}
@Test
public void testExpire() throws InterruptedException {
RedisCommands commands = RedisUtils.getCommands();
//过期时间单位是秒
commands.setex("user:1001", 2, "user1");
Thread.sleep(3000);
log.info("===>" + commands.get("user:1001"));
commands.set("user:1002", "user2");
//给已存在的key设置过期时间
commands.expire("user:1002", 2);
}
@Test
public void testSerialize() throws JsonProcessingException {
Product p = new Product();
p.setProductName("iPhone");
p.setFirm("Apple Inc");
p.setPlace("China");
//将实体序列化成JSON字符串
String productJson = new ObjectMapper().writeValueAsString(p);
RedisCommands commands = RedisUtils.getCommands();
commands.set("product:10001", productJson);
Object json = commands.get("product:10001");
//将json字符串反序列化为Product对象
p = new ObjectMapper().readValue(json.toString(), Product.class);
commands.del("product:10001");
log.info("===>" + p);
}
/**
* 自定义序列化器
*/
@Test
public void testSerialize2() {
Product p = new Product();
p.setProductName("iPhone");
p.setFirm("Apple Inc");
p.setPlace("China");
RedisCommands commands = RedisUtils.getCommands();
commands.set("user:1001", p);
p = ( Product) commands.get("user:1001");
log.info(p.getProductName());
log.info(p.getFirm());
log.info(p.getPlace());
}
}
基于Spring
创建RedisConfig配置类
@Configuration
public class RedisConfig {
/**
* 装配lettuce的redis连接工厂
* @return
*/
@Bean
public RedisConnectionFactory connectionFactory() {
//创建单机模式的redis配置
RedisStandaloneConfiguration configuration =
new RedisStandaloneConfiguration("127.0.0.1", 6379);
//设置密码
configuration.setPassword("wangl");
//选择要访问的数据库
configuration.setDatabase(0);
//创建lettuce连接工厂
return new LettuceConnectionFactory(configuration);
}
/**
* 装配String类型的RedisTemplate,用于操作redis数据库,
* 这个template只能用于操作key和value都是String类型的数据
* @return
*/
/*@Bean
public RedisTemplate<String, String> stringRedisTemplate() {
//创建StringRedisTemplate并注入连接工厂
return new StringRedisTemplate(connectionFactory());
}*/
/**
* 装配自定义的RedisTemplate,通过使用不同的序列化器
* 来定制序列化key和value的数据类型
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> template = new RedisTemplate();
//使用StringRedisSerializer来序列化和反序列化key
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
//使用Jackson序列化器来序列化和反序列value
template.setValueSerializer(RedisSerializer.json());
template.setHashValueSerializer(RedisSerializer.json());
//注入RedisConnectionFactory
template.setConnectionFactory(connectionFactory());
return template;
}
}
注意:这里需要在容器中装配一个连接对象工厂,需要设置账号密码和主机地址,然后装配RedisTemplate,这里面需要配置好序列化设置,RedisTemplate会对实体类类型进行转成json型。
测试
@Test
public void testRedisTemplate() {
User user = new User("user1", 21);
RedisTemplate<String, Object> template = getApplicationContext()
.getBean(RedisTemplate.class);
template.opsForValue().set("user:1001", user);
User u = (User) template.opsForValue().get("user:1001");
log.info(u.getUserName());
log.info(String.valueOf(u.getAge()));
}