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
相关产品推荐
相关产品推荐

