我已经成功设置了一个快速测试来创建一个“类 REST”服务,该服务返回一个序列化为 JSON 的对象,这非常简单快捷(基于 this article)。
但是,虽然返回 JSON 化对象很容易,但我还没有看到任何处理非原始输入参数的示例。如何将复杂对象作为参数传递?我正在使用 Apache CXF,但也欢迎使用其他框架(如 Jackson)的示例 :)
客户端可能类似于构建一个 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 吗?我需要在函数定义中进行很多更改吗?
最佳答案
经过一番挖掘,我很快发现基本上有两种选择:
选项 1
您将包含所有其他参数的“包装器对象”传递给服务。您可能需要使用 @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
您可以提供一些特殊的字符串格式,将您的对象打包到其中,然后在将采用此字符串的类中实现采用字符串的构造函数、静态 valueOf(String s) 或静态 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;
}
}
URI http://my-server.com/myService?a={"foo":1, "bar":2}&a={"foo":100, "bar":200}
在这种情况下会被反序列化为一个由两个 MyClass 对象组成的数组。
2019年评论: 看到这个答案在 2019 年仍然有一些热门,我觉得我应该发表评论。事后看来,我不会推荐选项 2,因为通过这些步骤只是为了能够进行 GET 调用会增加可能不值得的复杂性。如果您的服务接受如此复杂的输入,那么由于输入的排列数量,您可能无论如何都无法使用客户端缓存。我只是去在服务器上配置正确的跨域共享(CORS) header 并发布输入。然后专注于在服务器上缓存所有可以缓存的内容。
关于json - 如何将复杂对象作为参数传递给 RESTful 服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6061292/