You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Java RSocket:如何在@ConnectMapping中获取客户端元数据

读取RSocket连接的客户端元数据(Spring项目)

一、客户端传递元数据

在客户端初始化RSocketRequester时,通过metadata()方法附加元数据,同时指定对应的MIME类型(用于服务端识别解析):

// 构建RSocket请求器并附加元数据
RSocketRequester requester = RSocketRequester.builder()
        .dataMimeType(MediaType.APPLICATION_JSON)
        // 指定复合元数据类型(支持多组元数据)
        .metadataMimeType(MimeTypeUtils.parseMimeType(WellKnownMimeType.MESSAGE_RSOCKET_COMPOSITE_METADATA.getString()))
        .tcp("localhost", 7000)
        // 添加第一组元数据:客户端ID,自定义MIME类型
        .metadata("client_001", MimeTypeUtils.parseMimeType("application/vnd.client.id.v1+text"))
        // 可添加多组不同类型的元数据
        .metadata(UserContext.builder().userId("user_100").build(), 
                  MimeTypeUtils.parseMimeType("application/vnd.client.context.v1+json"))
        .build();

二、服务端获取元数据

方式1:直接绑定指定MIME类型的元数据

在@ConnectMapping方法中,通过@Metadata注解指定MIME类型,直接接收对应元数据:

@ConnectMapping
public void handleConnection(RSocketRequester requester, 
                             String somePayload,
                             // 绑定指定MIME类型的元数据
                             @Metadata("application/vnd.client.id.v1+text") String clientId,
                             // 绑定JSON类型的元数据,自动反序列化为对象
                             @Metadata(value = "application/vnd.client.context.v1+json", decoder = Jackson2JsonDecoder.class) UserContext userContext) {
    // 使用客户端传递的元数据
    System.out.println("客户端ID: " + clientId);
    System.out.println("用户上下文: " + userContext.getUserId());
}

方式2:解析复合元数据(多组元数据场景)

如果客户端传递了多组元数据,可直接接收CompositeMetadata对象遍历解析:

@ConnectMapping
public void handleConnection(RSocketRequester requester, 
                             String somePayload,
                             CompositeMetadata compositeMetadata) {
    // 遍历所有元数据条目
    compositeMetadata.forEach(entry -> {
        MimeType mimeType = entry.getMimeType();
        byte[] content = entry.getContent();
        
        if ("application/vnd.client.id.v1+text".equals(mimeType.toString())) {
            String clientId = new String(content);
            System.out.println("客户端ID: " + clientId);
        } else if ("application/vnd.client.context.v1+json".equals(mimeType.toString())) {
            // 手动反序列化JSON元数据
            UserContext userContext = new ObjectMapper().readValue(content, UserContext.class);
            System.out.println("用户上下文: " + userContext.getUserId());
        }
    });
}

方式3:通过RSocketRequester异步获取

也可通过RSocketRequester的metadata()方法异步获取元数据,适合延迟处理场景:

@ConnectMapping
public void handleConnection(RSocketRequester requester, String somePayload) {
    // 异步获取并解析元数据
    requester.metadata()
            .flatMap(metadata -> {
                // 解析复合元数据
                CompositeMetadata compositeMetadata = new CompositeMetadata(metadata.getContent(), metadata.getMimeType());
                // 找到目标元数据条目
                Optional<CompositeMetadata.Entry> clientIdEntry = compositeMetadata.stream()
                        .filter(entry -> "application/vnd.client.id.v1+text".equals(entry.getMimeType().toString()))
                        .findFirst();
                return Mono.justOrEmpty(clientIdEntry);
            })
            .map(entry -> new String(entry.getContent()))
            .subscribe(clientId -> System.out.println("客户端ID: " + clientId));
}

注意:如果客户端只传递单一元数据,可直接指定对应MIME类型,无需使用复合元数据格式,简化解析逻辑。

内容的提问来源于stack exchange,提问作者Anant Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 20:12:37