Java 在Jersey中,如何处理深度嵌套的复杂对象的@POST参数?

Java 在Jersey中,如何处理深度嵌套的复杂对象的@POST参数?,java,rest,jersey,jersey-1.0,Java,Rest,Jersey,Jersey 1.0,我在这里使用的是Jersey 1.x,我有一个@POST方法,需要发送一个嵌套很深的复杂对象。我不确定我所有的选择,但似乎有很多: 通常,方法参数的Java类型可能: 是原始类型 具有接受单个字符串参数的构造函数 有一个名为valueOf或fromString的静态方法,该方法接受单个字符串参数(例如,请参阅Integer.valueOf(String)和 fromString(String));或 是列表、集合或分类集合,其中T满足上述2或3。生成的集合是只读的 理想情况下,我希望能够定义这样

我在这里使用的是Jersey 1.x,我有一个
@POST
方法,需要发送一个嵌套很深的复杂对象。我不确定我所有的选择,但似乎有很多:

通常,方法参数的Java类型可能:

  • 是原始类型

  • 具有接受单个字符串参数的构造函数

  • 有一个名为valueOf或fromString的静态方法,该方法接受单个字符串参数(例如,请参阅Integer.valueOf(String)和 fromString(String));或

  • 是列表、集合或分类集合,其中T满足上述2或3。生成的集合是只读的

  • 理想情况下,我希望能够定义这样一种方法:

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Path("complexObject")
    public void complexObject(@FormParam("complexObject") ComplexObject complexObject) throws Exception {
    
    但我想我只能在我的对象满足上述要求的情况下(在我的情况下,它不满足)才能做到这一点。对我来说,似乎我有一个选择

    选项1:从字符串实现
    fromString
    执行上述第3项

    选项2:将
    complexObject
    分块传入 将
    complexObject
    分解为若干部分,使参数如下:

    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Path("complexObject")
    public void complexObject(@FormParam("piece1") LessComplexPiece lessComplexPiece1, 
    @FormParam("piece2") LessComplexPiece lessComplexPiece2, 
    @FormParam("piece3") LessComplexPiece lessComplexPiece3) throws Exception {
    
    如果
    LessComplexPiece
    不满足上述要求,这可能是不够的。我想知道这里最好的选择是什么。在这种情况下人们通常做什么?以下是我能想到的优点和缺点:

    机具
    fromString的缺点
    
    • 必须维护自定义反序列化程序。每次修改类时,此反序列化程序可能会中断。一般来说,出现bug的风险更大
    • 生成描述复杂对象片段的文档可能是不可能的。我得亲手写
    • 对于复杂对象的每一部分,我都必须编写自己的转换和验证逻辑
    • 我不确定post数据会是什么样子。但是,这可能会使某些人很难从网页表单调用API。如果资源接受原语,这将很容易。例如:
      complexObject=seralizedString
      vs
      firstName=John
      lastName=Smith
    • 由于各种原因,您可能无法修改该类(谢天谢地,这不是我的限制)
    实现
    fromString
    • 这可以避免使用大量参数的方法。这将减少API的使用威胁
    • 这个论点是我想在我的方法主体中使用的抽象层次:
    • 我不必手动将这些片段组合在一起(从技术上讲,我会这样做,只需使用反序列化方法)
    • 反序列化程序可以是一个自动化过程的库(XStream、gensen等),可以节省我很多时间。这可以降低bug风险
    • 如果将对象展平以发送碎片,则可能会遇到“名称空间”冲突。例如,想象一下派遣一名
      员工
      。如果他有一个
      老板
      ,你现在必须提供一个
      员工的名字
      和一个
      老板的名字
      。如果只是反序列化对象,则可以适当嵌套数据,而不必在参数名称中包含上下文

    那么我应该选择哪一个选项呢?是否有第三个选项我不知道?

    如果您更喜欢性能,那么将对象转换为json-kryo的特殊处理程序呢?你有


    对于复杂对象模型,您可能想考虑使用JSON或XML绑定而不是URL编码的字符串来将对象传递给资源调用,这样您就可以依赖JAXB框架了吗? Jersey客户端库与JAXB兼容,如果您在类@XmlElementRoot上添加注释,它可以为您透明地处理所有封送处理

    对于文档,如果选择XML绑定,XSD是一个很好的起点。
    其他REST文档工具,如Enounceate,可以将自动生成带到下一个级别。

    我知道这个问题很老,但如果有人遇到这个问题,有一个新的更好的解决方案,自JAX-RS 2.0以来。解决方案是@BeanParam。由于文件原因:

    可用于将自定义JAX-RS“参数聚合器”值对象注入资源类字段、属性或资源方法参数的注释。 JAX-RS运行时将实例化该对象,并注入使用@XxxParam注释(@PathParam,@FormParam…)或@Context注释之一注释的所有字段和属性。对于POJO类,相同的实例化和注入规则适用于请求范围的根资源类的实例化和注入

    如果您想进一步了解这一工作原理,请参阅我找到的文章:

    您是否考虑过使用JSON或XML绑定而不是URL编码的字符串来传递对象,这样您就可以依赖JAXB了?@TheArchitect我已经研究过了,但我很难让它正常工作。但即使我这样做了,它也只是让服务器端的逻辑变得更简单。我认为我提出的客户端问题在这种方法中是有效的。客户端也可以利用JAXB来处理输入参数。如果您使用的是Jersey客户端,它是完全透明的。如果没有,您仍然可以在发送之前在对象上调用JAXB封送器。如果您使用XML绑定,XSD是一个很好的规范和文档,可以与客户端共享。@客户端的架构将是许多语言,如javascript和php,而不仅仅是java。不过,这是一个很好的观点。我计划序列化为JSON,但出于这个原因,也许我应该使用XML