序列化是将对象转换为字节流的过程,而 反序列化 则是将字节流恢复为对象。Java 提供了 Serializable 接口进行序列化,此外还有 JSON、XML、Protobuf 等序列化方式。
在 Spring 和 RPC(远程过程调用)中,序列化用于数据传输、缓存、持久化等场景。以下是一些常见应用:
1. Spring 中的序列化应用
1.1 Spring 缓存(Spring Cache)
Spring Cache 使用 序列化 机制将对象存入 Redis 或其他缓存系统。
默认使用 JDK 序列化
Spring Boot 默认使用 JDK 序列化,但不推荐,因为它占用空间大,性能较低。
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
// 构造方法、getter 和 setter
}
@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
JDK 默认的序列化方式 可能导致缓存存储的对象不兼容,因此可以使用 JSON 或 Protobuf 代替。
1.2 Redis 序列化
Spring Boot Redis 默认使用 JdkSerializationRedisSerializer 进行序列化:
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置 JSON 序列化
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setKeySerializer(new StringRedisSerializer());
return template;
}
改用 JSON 进行序列化后,Redis 存储的数据更易读且跨语言兼容。
1.3 Spring MVC 传输 JSON
Spring MVC 依赖 Jackson 进行 JSON 序列化,默认支持 @RestController 方法的 自动 JSON 转换。
@RestController
public class UserController {
@GetMapping("/user")
public User getUser() {
return new User("Alice", 25);
}
}
Spring 自动使用 Jackson 序列化 User 对象为 JSON:
{
"name": "Alice",
"age": 25
}
2. RPC(远程过程调用)中的序列化
RPC 用于跨进程通信,需要高效的 序列化 和 反序列化 机制。常见的 RPC 框架包括 Dubbo、gRPC、Spring Cloud。
2.1 Dubbo 的序列化
Dubbo 支持多种序列化协议,如:
- Hessian(二进制,性能较好)
- FastJSON(文本格式,适用于 Web)
- Protobuf(高效二进制格式,跨语言支持)
使用 Hessian 作为 Dubbo 序列化方式
<dubbo:protocol name="dubbo" serialization="hessian2" port="20880"/>
Dubbo 服务器端:
@DubboService
public class UserServiceImpl implements UserService {
public User getUser(Long id) {
return new User("Alice", 25);
}
}
Dubbo 客户端:
@DubboReference
private UserService userService;
public void test() {
User user = userService.getUser(1L);
System.out.println(user);
}
Hessian 采用二进制格式,比 Java 序列化更高效。
2.2 gRPC(Google RPC)中的 Protobuf 序列化
gRPC 采用 Protocol Buffers(Protobuf) 进行高效序列化,跨语言兼容性强。
(1) 定义 Protobuf
syntax = "proto3";
package user;
message User {
string name = 1;
int32 age = 2;
}
service UserService {
rpc GetUser (UserRequest) returns (User);
}
message UserRequest {
int64 id = 1;
}
(2) 生成 Java 代码
protoc --java_out=. user.proto
(3) 使用 gRPC 服务
@GrpcService
public class UserServiceImpl extends UserServiceGrpc.UserServiceImplBase {
public void getUser(UserRequest request, StreamObserver<User> responseObserver) {
User user = User.newBuilder().setName("Alice").setAge(25).build();
responseObserver.onNext(user);
responseObserver.onCompleted();
}
}
客户端:
UserServiceGrpc.UserServiceBlockingStub stub = UserServiceGrpc.newBlockingStub(channel);
User user = stub.getUser(UserRequest.newBuilder().setId(1L).build());
System.out.println(user);
Protobuf 具有高效的二进制序列化,适用于高并发 RPC 传输。
3. 序列化方式对比
| 序列化方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| JDK 序列化 | Java 内部对象存储 | 简单、内置支持 | 体积大、性能低 |
| JSON(Jackson) | Web API、Redis | 可读性强、通用性好 | 解析性能比二进制差 |
| Hessian | Dubbo、RPC | 高效、支持对象 | Java 专属 |
| Protobuf | gRPC、高性能 RPC | 高效、跨语言 | 不支持对象类型 |
总结
✅ Spring 主要使用 JSON 或 Redis 进行序列化。
✅ Dubbo 推荐使用 Hessian2 作为序列化方式。
✅ gRPC 使用 Protobuf 进行高效数据传输。
✅ 选择合适的序列化方式,平衡性能、兼容性和可读性。
更多详细内容请关注其他相关文章。