使用JAX-RS继承传入对象消息的最佳实践



我想知道是否有一个好的解决方案来解决我的问题,或者在处理来自对象层次结构的不同消息方面是否有好的实践。

简而言之:我有一个对象层次结构,比方说:

interface IMessage 
abstract Message implements IMessage
class SimpleMessage extends Message
class ReportMessage extends SimpleMessage
class CostReportMessage extends ReportMessage
class IncomeReportMessage extends ReportMessage
... (like 3 other types, similar to the CostReportMessage)

因此,我希望有一个传入的JAX-RS端点方法,因为类的大多数处理程序代码都是相同的,但我们在代码中需要一些条件部分。

例如:

@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML + "; charset=UTF-8", MediaType.APPLICATION_JSON + "; charset=UTF-8"})
public Response createReport(  final ReportMessage, @Context HttpHeaders headers ) {
...
...
}

因此,我们有一些类似上面的方法,但我想让它成为一个方法,比如接收传入的IMessage,然后根据对象类的需要进行处理

你对这个问题有什么建议吗?或者你知道如何解决这类问题的最佳实践吗?

您可以使用父类作为消费对象,然后根据某些条件使用BeanUtils.copyProperties()将所有属性复制到新的专用消息对象,例如:您在SimpleMessage中有messageTypeID变量来判断它应该是什么样的消息。

  @POST
  @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
  @Produces({ MediaType.APPLICATION_XML + "; charset=UTF-8", MediaType.APPLICATION_JSON + "; charset=UTF-8"})
  public Response createReport(  SimpleMessage message, @Context HttpHeaders headers ) {
       SimpleMessage convertedMessage;
       if(//condition//) {
           convertedMessage = new ReportMessage();
           BeanUtils.copyProperties(convertedMessage, message);
       } else { ... }
       ...
  }

虽然我没有发现以下解决方案"不错"或"优雅",但这似乎有效:

步骤1。创建一个函数

private IMessage parseRequest(String request) throws IOException, JAXBException{
    StringReader reader = new StringReader(request);
    // unmarshaller here is a simple JAXB Unmarshaller for the message package
    IMessage message = (SimpleMessage) unmarshaller.unmarshal(reader); 
    return message;
}

步骤2。修改jaxb入口点

@POST
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML + "; charset=UTF-8", MediaType.APPLICATION_JSON + "; charset=UTF-8"})
public Response createReport(  final String request, @Context HttpHeaders headers ) {
    IMessage message = parseRequest(request);
    ...
    ...
    return response;
}

所以我认为,这是因为以下原因(这只是我的理论,但我不知道从哪里寻找真相):

  1. JAX-RS只需检查类型,并创建一个对应于方法签名中给定类型的Unmarshaller
  2. JAX-RS在方法param中提供IMessage时将失败(因为接口没有构造函数)
  3. 由于JAX-RS创建的Unmarshaller只会创建一个知道SimpleMessage的上下文,因此它将无法对任何子类进行Unmarshall,例如CostReportMessage
  4. 好的解决方案是提供一个自定义的MessageBodyReader(@Provider注释),但我无法让它工作
  5. 这可能是因为球衣是如何为给定类型找到内容提供商的(从最通用到最具体,而且因为它找到了比我更通用的内容提供商,所以它不会使用它)

最新更新