最近项目中要按照对象方式进行存取,使用时再拿出来,于是我们就要学习序列化和反序列化的相关知识。
基于我们的项目,按照课表进行推课的时候,课表中当前课程结束的时候,将执行的颗粒存到redis中。
序列化和反序列化是计算机科学中用于数据存储和传输的重要概念。
是将数据结构或对象转换成一种可存储或可传输格式的过程。在序列化后,数据可以被写入文件、发送到网络或存储在数据库中,以便在需要时可以再次还原成原始的数据结构或对象。序列化的过程通常涉及将数据转换成字节流或类似的格式,使其能够在不同平台和编程语言之间进行传输和交换。
是序列化的逆过程,即将序列化后的数据重新还原成原始的数据结构或对象。反序列化是从文件、网络数据或数据库中读取序列化的数据,并将其转换回原始形式,以便在程序中进行使用和操作。
序列化和反序列化在许多场景中都非常有用,例如:
数据存储:将程序中的数据保存到文件或数据库中,以便在以后重新加载和使用。
网络通信:在网络上传输数据时,需要将数据序列化为字节流,以便在接收端进行反序列化。
分布式系统:在分布式系统中,不同计算节点之间需要通过序列化和反序列化来交换数据。
进程间通信:不同进程之间通信时,数据需要在序列化和反序列化之间进行转换。
常见的序列化格式包括 JSON(JavaScript Object Notation)、XML(eXtensible Markup Language)、Protocol Buffers、MessagePack等。每种格式有其优势和适用场景,选择合适的序列化格式取决于具体的应用需求。
import java.io.*;
public class Serialization {
private static final File SAVE_FILE = new File("D:" + File.separator + "demo.Class");
public static void saveObject(Object object) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE));
oos.writeObject(object); // 序列化
oos.close();
}
public static Object loadObject() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE));
Object obj = ois.readObject(); // 反序列化
ois.close();
return obj;
}
public static void main(String[] args) throws Exception {
saveObject(new Class(new Person("p",11),"class",12));// 序列化
Class c = (Class)loadObject();
System.out.println(c); // 反序列化
}
public static class Person implements Serializable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static class Class implements Serializable{
private Person person;
private String name;
private int age;
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Class{" +
"person=" + person +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public Class(Person person) {
this.person = person;
}
public Class(Person person, String name, int age) {
this.person = person;
this.name = name;
this.age = age;
}
}
}
可以通过打断点的方式查看对象的展示情况
这样我们就了解了序列化和反序列的概念,下面看看在redis是如何实现序列化和反序列化的吧。
建立springboot项目
引入坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
建类
在这里插入代码片
package com.example.redis.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
/**
* RedisTemplate配置
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
// 设置序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置redisTemplate
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(lettuceConnectionFactory);
RedisSerializer<?> stringSerializer = new StringRedisSerializer();
// key序列化
redisTemplate.setKeySerializer(stringSerializer);
// value序列化
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
// Hash key序列化
redisTemplate.setHashKeySerializer(stringSerializer);
// Hash value序列化
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
server:
port: 8081
spring:
redis:
host: **redis.***d.tech
port: 6379
password: ***
database: 0
timeout: 300000ms #连接超时
jedis:
pool:
max-active: 8 #连接池最大的连接数
max-wait: -1ms #连接池最大的阻塞等待时间(负值表示没有限制)
max-idle: 500 #连接池最大的空闲连接
package com.example.redis.Entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class UserInfo implements Serializable {
/**
* id
*/
private Integer id;
/**
* 姓名
*/
private String name;
/**
* 创建时间
*/
private Date createTime;
}
package com.example.redis.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
/**
* @ClassName RedisUtils
* @Description
* @Author Lizhou
* @Date 2020-10-22 10:10:10
**/
@Slf4j
@Component
public class RedisUtils {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
/**
* 根据key读取数据
*/
public Object get(final String key) {
if (StringUtils.isEmpty(key)) {
return null;
}
try {
return redisTemplate.opsForValue().get(key);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 写入数据
*/
public boolean set(final String key, Object value) {
if (StringUtils.isEmpty(key)) {
return false;
}
try {
redisTemplate.opsForValue().set(key, value);
log.info("存入redis成功,key:{},value:{}", key, value);
return true;
} catch (Exception e) {
log.error("存入redis失败,key:{},value:{}", key, value);
e.printStackTrace();
}
return false;
}
}
package com.example.redis;
import com.example.redis.Entity.UserInfo;
import com.example.redis.utils.RedisUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
@SpringBootTest
class RedisTestApplicationTests {
@Autowired
private RedisUtils redisUtil;
@Test
void contextLoads() {
UserInfo userInfo = new UserInfo();
userInfo.setId(1);
userInfo.setName("jack");
userInfo.setCreateTime(new Date());
// 放入redis
redisUtil.set("user", userInfo);
// 从redis中获取
System.out.println("获取到数据:" + redisUtil.get("user"));
}
}
Redis(Remote Dictionary Server)是一种开源的高性能键值存储数据库,它也被称为数据结构服务器,因为它支持多种灵活的数据结构。Redis以内存中的数据结构为基础,提供了快速、高效的数据存储和访问能力。它可以用作数据库、缓存、消息代理和排行榜等多种用途。
以下是 Redis 的一些主要特点:
键值存储:
Redis将数据存储为键值对,其中键是唯一的标识符,而值可以是字符串、哈希、列表、集合、有序集合等各种数据结构。
内存数据库:(因为我们是面向对象开发,所有就要使用内存数据库啦,因为要把对象存取来哦)
Redis的所有数据都存储在内存中,因此具有非常快的读写速度。但是,它也支持将数据持久化到磁盘,以便在重启后恢复数据。
丰富的数据结构:
Redis支持多种数据结构,如字符串、哈希表、列表(链表)、集合、有序集合等。这使得Redis在处理不同类型的数据时非常灵活和高效。
高性能:
由于数据存储在内存中,Redis能够实现非常高的读写速度。此外,它使用单线程模型来避免了多线程带来的竞争条件,使得其在单核系统上也能表现出色。
支持事务:
Redis支持简单的事务,你可以将多个命令放在一个事务中,然后一次性执行这些命令。在事务执行期间,其他客户端不会对其进行干扰。
发布/订阅:
Redis支持发布/订阅模式,允许客户端订阅一个或多个频道,当有消息发布到这些频道时,订阅的客户端将会收到相应的消息。
集群支持:
Redis支持将数据分布在多个节点上,从而实现高可用性和横向扩展。
轻量级:
Redis的代码库相对较小,没有复杂的依赖,因此非常轻量级且易于安装和部署。
Redis广泛应用于Web开发、缓存、会话存储、实时分析、消息队列等场景。由于其高性能和灵活性,Redis成为了许多应用架构中不可或缺的一部分。
序列化在Redis中发挥着重要的作用,它使得数据可以被转换成一种便于存储和传输的格式,并可以通过网络进行传输。当数据需要被存储到Redis中时,通常需要先进行序列化,将数据转换成适合Redis存储的形式。而在从Redis中取出数据时,则需要进行反序列化,将序列化后的数据重新还原成原始的数据结构,以便在程序中进行使用和操作。
总之,序列化和反序列化是数据在存储和传输过程中的桥梁,而Redis作为高性能的键值存储数据库,则利用序列化机制来存储和操作数据,提供快速、灵活的数据存储和访问服务。通过将数据序列化后存储在Redis中,我们可以充分发挥Redis的优势,实现高效的数据处理和管理。