我想知道是否有一个好的解决方案来解决我的问题,或者在处理来自对象层次结构的不同消息方面是否有好的实践。
简而言之:我有一个对象层次结构,比方说:
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;
}
所以我认为,这是因为以下原因(这只是我的理论,但我不知道从哪里寻找真相):
- JAX-RS只需检查类型,并创建一个对应于方法签名中给定类型的Unmarshaller
- JAX-RS在方法param中提供IMessage时将失败(因为接口没有构造函数)
- 由于JAX-RS创建的Unmarshaller只会创建一个知道SimpleMessage的上下文,因此它将无法对任何子类进行Unmarshall,例如CostReportMessage
- 好的解决方案是提供一个自定义的MessageBodyReader(@Provider注释),但我无法让它工作
- 这可能是因为球衣是如何为给定类型找到内容提供商的(从最通用到最具体,而且因为它找到了比我更通用的内容提供商,所以它不会使用它)