Java 序列化在 Spring 和 RPC 中的应用
                           
天天向上
发布: 2025-03-03 23:12:02

原创
114 人浏览过

序列化是将对象转换为字节流的过程,而 反序列化 则是将字节流恢复为对象。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可读性强、通用性好解析性能比二进制差
HessianDubbo、RPC高效、支持对象Java 专属
ProtobufgRPC、高性能 RPC高效、跨语言不支持对象类型

总结

✅ Spring 主要使用 JSON 或 Redis 进行序列化。
✅ Dubbo 推荐使用 Hessian2 作为序列化方式。
✅ gRPC 使用 Protobuf 进行高效数据传输。
✅ 选择合适的序列化方式,平衡性能、兼容性和可读性。

更多详细内容请关注其他相关文章。

发表回复 0

Your email address will not be published. Required fields are marked *