return一个Message(来自Spring)如何表示没有找到信息?

How return a Message (from Spring) to represent that the information was not found?

我正在 Spring 上处理消息,我有一个简单的问题。

当另一个服务发送一条消息,请求能够回答的服务不存在的信息时,我想到的第一件事是传递 "null" 有效载荷:

MyResponse myResponse = service.find(id); //ops, the information with this id does not exists

Message<MyResponse> message = MessageBuilder
        .withPayload(myResponse) // the information does not exists, so null
        .copyHeadersIfAbsent(request.getHeaders())
        .build();

但是方法withPayload不接受null。那么,用 "empty" 值填充此消息以接收结果并知道此信息不存在的原始请求的最佳做法或替代方法是什么?

现在我正在将一个空对象 (new MyResponse()) 传递给有效负载,但这可能会对谁使用消息造成混淆。我可以创建另一个 class 来表示此 "not exists" 状态,但我现在正在尝试了解我的选择。

谢谢!

null 负载不会带来太多信息,并且不受许多网络协议的支持。此外,框架中有很多地方是基于负载类型的,但如果它是 null,我们可能不知道如何处理它以及如何处理它。在某些组件中,null return 值是停止流的信号,并且不产生任何下游消息来回复。

你可能会去的解决方案就像常量对象(MyNullResponse)来表示它是关于一个null

您也可以考虑使用异常而不是尝试 return null 的方法。假设您进行了一些 post 搜索处理以及一系列过滤和转换步骤。在 null 的情况下,您的消息仍将沿着所有流程传播。但是当我们处理异常时(就像 javax.persistence.EntityNotFoundException 一样)我们只是立即将问题冒泡给最终用户。这已经是将异常表示为最终用户可理解的消息的目标服务责任。

我们有一个 JIRA ticket 关于 null payload support。您可以在那里阅读更多原因以及其他人对此事的看法。我允许在这件事上做点什么的想法就像 Optional.empty()。然后我们可以在目标最终用户代码上轻松地将它映射到 null

您必须清楚地区分响应本身(在您的情况下是 MyResponse 对象)和与您的业务逻辑相关的信息的存在与否,您构建的消息必须尽可能通用而不是硬耦合到您的服务层,原因很简单 => 该消息只是您发送给消费者的消息,因此如果可能,请尝试将信息的存在与否嵌入到您的对象 MyResponse(布尔标志)中,并在调用后即时构建它你的服务 而不是

MyResponse myResponse = service.find(id);

你可以试试这个:

     CustomResponse myResponse = service.find(id);
      // use  helper class to respect DRY principal if you need it somewhere   
      MyResponse messageReponse  = ResponseBuilder.constructResponse(myReponse);
 Message<MyResponse> message =// .. construct you message

在上面的示例中,如果 myResponse 为空,ResponseBuilder 会处理它,并完全创建响应(您可以整合所有情况..)

阅读后,我想与大家分享我的解决方案。

我创建了一个 OptionalMessage class,与 Java 8+ 中的 Optional class 非常相似。因为我使用 application/json 作为消息的 content-type

我可以在不同的消息中使用这个 OptionalMessage

OptionalMessage optionalMessage = messaging.find(id);
if (optionalMessage.isPresent()) {
    MyMessage myMessage = optionalMessage.getContent();
}

它还有方法of()empty(),用于在另一端填充OptionalMessage

生成的Json结构遵循这个例子:

{
    "content": { /*attributes */}
}

当我们没有内容时(我的 "null" return),Json 看起来像这样:

{
    "content": null
}

我尝试使用泛型 (OptionalMessage<MyMessage>),但我需要更改 my Jackson setup(在 IntegrationFlow DSL 上)以便在调用 [=23] 时不会收到错误 java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to MyMessage =]方法。