当前位置: 首页 > 面试题库 >

如何将复杂对象作为参数传递给RESTful服务?

邓昀
2023-03-14
问题内容

我已经成功地建立了一个快速测试,以创建一个“类似REST的”服务,该服务返回序列化为JSON的对象,并且这非常容易且快速(基于本文)。

但是,虽然返回桃子一样的JSON格式的对象很容易,但我还没有看到任何处理非原语输入参数的示例。如何传递复杂的对象作为参数?我正在使用Apache
CXF,但也欢迎使用其他框架(例如杰克逊)的示例:)

客户端可能类似于构建javascript对象,将其传递到JSON.stringify(complexObj),然后将该字符串作为参数之一传递。

该服务可能看起来像这样

@Service("myService")
class RestService {
    @GET
    @Produces("application/json")
    @Path("/fooBar")
    public Result fooBar(@QueryParam("foo") double foo, @QueryParam("bar") double bar,
        @QueryParam("object") MyComplex object) throws WebServiceException {
    ...
    }
}

发送序列化对象作为参数可能会很快触及Internet Explorer施加的2KB
URL限制。在这些情况下,您是否建议使用POST,我是否需要在函数定义中进行很多更改?


问题答案:

深入研究后,我很快发现基本上有两个选择:

您将包含所有其他参数的“包装对象”传递给服务。您可能需要使用@XmlRootElement之类的JAXB批注对该包装类进行批注,以使其能够与基于Jettison的提供程序一起使用,但是如果您代替使用Jackson,则没有必要。只需将内容类型设置为正确的类型,就会调用正确的消息正文阅读器。当然,这仅适用于POST类型的服务(AFAIK)。

这只是使用包装对象将原始问题中提到的服务转换为一个服务的示例。

@Service("myService")
class RestService {

    @POST
    @Produces("application/json")
    @Path("/fooBar")
    public Result fooBar(

          /** 
          * Using "" will inject all form params directly into a ParamsWrapper 
          * @see http://cxf.apache.org/docs/jax-rs-basics.html
          */
          @FormParam("") FooBarParamsWrapper wrapper

        ) throws WebServiceException {
            doSomething(wrapper.foo);
    }
}

class ParamsWrapper {
  double foo, bar;
  MyComplexObject object;
}

选项2

您可以提供一些特殊的字符串格式,将您的对象打包到其中,然后实现采用字符串的构造函数,将采用该字符串并创建对象的类中的static
valueOf(String s)或static fromString(String
s)类。从中。或者非常相似,创建一个执行完全相同的ParameterHandler。

AFAIK,只有第二个版本允许您使用JSONP从浏览器调用服务(因为JSONP是仅限于GET的技巧)。我选择此路由是为了能够在URI中传递复杂对象的数组。

作为其工作方式的示例,请采用以下域类和服务

@GET
@Path("myService")
public void myService(@QueryParam("a") MyClass [] myVals) {
    //do something
}

class MyClass {
    public int foo;
    public int bar;

   /** Deserializes an Object of class MyClass from its JSON representation */
   public static MyClass fromString(String jsonRepresentation) {
           ObjectMapper mapper = new ObjectMapper(); //Jackson's JSON marshaller
           MyClass o= null;
           try {
                   o = mapper.readValue(jsonRepresentation, MyClass.class );
           } catch (IOException e) {
                    throw new WebApplicationException()
           }
           return o;
   }
}

http://my-server.com/myService?a={"foo":1, "bar":2}&a={"foo":100, "bar":200}在这种情况下,URI 将反序列化为由两个MyClass对象组成的数组。

2019年评论:
看到这个答案在2019年仍然很受欢迎,我觉得我应该发表评论。事后看来,我不会建议选项2,因为仅为了能够执行GET调用而执行这些步骤会增加可能不值得的复杂性。如果您的服务接受了如此复杂的输入,由于输入的排列数量众多,您可能仍将无法使用客户端缓存。我只想在服务器上配置正确的跨域共享(CORS)标头,然后输入输入。然后集中精力在服务器上缓存所有内容。



 类似资料:
  • 问题内容: 我想将我域的任意对象(例如Person)作为参数传递给.jrxml。 在.jrxml上执行以下操作: 这样的事情可能吗?在哪里可以找到更复杂的教程,这些教程不仅显示传递java.lang.String的内容,还显示更多的内容? 谢谢 问题答案: 是的,您可以传递任何Java对象,但应确保将其导入JRXML。 在jasperReport标记内。您可以使用标记,例如: 但是,您可以使用对象

  • 我正在使用GraphQL查询一个对象,该对象将由大约15个不同的REST调用组成。这是我的根查询,我在其中传入查询的ID。这对于正确解析的主要student对象非常有效。但是,我需要弄清楚如何将ID传递给地址解析程序。我尝试将args添加到address对象,但出现了一个错误,表明args没有从Student对象传递下来。所以我的问题是:如何将客户机查询中的参数传递给GraphQL服务器中的子对象

  • 我有一个抽象基类,它有以下私有变量 我希望其他所有扩展基类的类都实现以下方法 我的问题是,除了Map之外,我不能为实现选择任何其他类型 如果我不能控制选项映射的类型,但我想让initOptions方法的实现类知道映射中的键是String类型,值可以是任何对象,那么处理这种情况的正确方法是什么。

  • 这可能是一个简单的问题。我尝试过谷歌搜索,但没有成功。我有一个DTO,它是从客户机传递过来的,由restful Web服务使用。但是得到这个例外 这是我的restful方法。 这是我平静的呼唤

  • 问题内容: 我正在创建一种通过传递搜索字段从任何表中选择ID的方法。 但是我得到一个有关语法错误的MySqlException。当我查看“异常”消息时,它向我显示带引号的查询表!如何将表格作为不带引号的参数传递? 问题答案: 大多数数据库不允许您通过参数指定表名或列名。参数用于 值 。如果确实确实需要使它动态化,则应验证输入(它应该是一个已知的表名,并且该表中具有已知的列名),然后将其包括在SQL

  • 问题内容: 我有以下任意JSON对象(字段名称可能会更改)。 -- 我知道我可以像定义具有相同字段名的JSON对象那样定义类,但是我希望控制器接受具有不同字段名的任意JSON对象。 问题答案: 如果您想将自定义JSON对象传递给MVC操作,则可以使用此解决方案,它的工作原理很吸引人。 该解决方案的真正好处是,您不需要为每个参数组合定义一个新类,并且除此之外,您可以轻松地将对象转换为其原始类型。 更