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

原创
443 人浏览过

序列化是将对象转换为字节流的过程,而 反序列化 则是将字节流恢复为对象。Java 提供了 Serializable 接口进行序列化,此外还有 JSON、XML、Protobuf 等序列化方式。

SpringRPC(远程过程调用)中,序列化用于数据传输、缓存、持久化等场景。以下是一些常见应用:


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 默认的序列化方式 可能导致缓存存储的对象不兼容,因此可以使用 JSONProtobuf 代替。


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 主要使用 JSONRedis 进行序列化。
Dubbo 推荐使用 Hessian2 作为序列化方式。
gRPC 使用 Protobuf 进行高效数据传输。
选择合适的序列化方式,平衡性能、兼容性和可读性。

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

发表回复 0

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