寻找一种将STOMP消息有效负载反序列化为通用类型的最佳方法。
我有websocket服务,该服务接收实体,将其保存并向所有订阅的客户端发送消息包装的已保存实体。
在纯JSON中,它应该看起来像这样:
客户发送实体:
{
"name": "New Facility Name"
}
我尝试在客户端处理的来自服务的消息:
{
"type": "ADD",
"entity": {
"id": 123,
"name": "New Facility Name"
}
}
这是Java实现,无法按我期望的那样工作。
实体-具有字段Facility
和id
的JavaBean name
。
消息。
public final class UpdateMessage<T> {
private final Type type;
private final T entity;
@JsonCreator
public UpdateMessage(@JsonProperty("type") Type type, @JsonProperty("entity") T entity) {
this.type = type;
this.entity = entity;
}
// getters
public enum Type {
ADD,
DELETE,
EDIT
}
}
测试。
@RunWith(SpringRunner.class)
@SpringBootTest
public class WebsocketClientTest {
private CompletableFuture<UpdateMessage<Facility>> messageCompletableFuture = new CompletableFuture<>();
@Autowired
private WebsocketClient client;
@Before
public void setUp() {
client.connect();
}
@After
public void setDown() {
client.disconnect();
}
@Test
public void trySpringResolvableType() throws InterruptedException, TimeoutException, ExecutionException {
StompSession session = client.getSession();
session.subscribe("/topic/facility/update", new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return ResolvableType.forClassWithGenerics(UpdateMessage.class, Facility.class).getType();
}
@Override
public void handleFrame(StompHeaders stompHeaders, Object payload) {
//noinspection unchecked
messageCompletableFuture.complete((UpdateMessage<Facility>) payload);
}
});
Facility facility = new Facility();
facility.setName("New Facility Name");
client.getSession().send("/app/facility/post", facility);
UpdateMessage<Facility> message = messageCompletableFuture.get(9, SECONDS);
/* Get 'java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to Facility' here: */
assertEquals(facility.getName(), message.getEntity().getName());
}
}
“ java.lang.ClassCastException:无法将java.util.LinkedHashMap转换为Facility”的结果。
还尝试过杰克逊的TypeReference<T>
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return new TypeReference<UpdateMessage<Facility>>() {}.getType();
}
具有相同结果和TypeFactory
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return TypeFactory.defaultInstance().constructParametricType(UpdateMessage.class, Facility.class);
}
抛出
org.springframework.messaging.converter.MessageConversionException: Unresolvable payload type [[simple type, class UpdateMessage<Facility>]] from handler type [class FacilityController$2]
来自
org.springframework.messaging.simp.stomp.DefaultStompSession.invokeHandler(StompFrameHandler, Message<byte[]>, StompHeaders)
我设法通过包装器类使它正常工作
public final class FacilityUpdateMessage {
private final UpdateMessage<Facility> message;
@JsonCreator
public FacilityUpdateMessage(@JsonProperty("type") UpdateMessage.Type type,
@JsonProperty("entity") Facility entity
) {
message = new UpdateMessage<>(type, entity);
}
public UpdateMessage<Facility> getMessage() {
return message;
}
}
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return FacilityUpdateMessage.class;
}
但我不确定这是否是最佳解决方案。